1a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin/*
2a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
3a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin *
4a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin *  Use of this source code is governed by a BSD-style license
5a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin *  that can be found in the LICENSE file in the root of the source
6a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin *  tree. An additional intellectual property rights grant can be found
7a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin *  in the file PATENTS.  All contributing project authors may
8a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin *  be found in the AUTHORS file in the root of the source tree.
9a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin */
10a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin
11a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin#include "thread_win.h"
12a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin
13a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin#include <assert.h>
14a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin#include <process.h>
15a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin#include <stdio.h>
16a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin#include <windows.h>
17a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin
18a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin#include "set_thread_name_win.h"
19a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin#include "trace.h"
20a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin
21a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkinnamespace webrtc {
22a6451827d543eb00824bc95097e47d0aac51ae93Alexander GutkinThreadWindows::ThreadWindows(ThreadRunFunction func, ThreadObj obj,
23a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin                             ThreadPriority prio, const char* threadName)
24a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    : ThreadWrapper(),
25a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin      _runFunction(func),
26a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin      _obj(obj),
27a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin      _alive(false),
28a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin      _dead(true),
29a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin      _doNotCloseHandle(false),
30a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin      _prio(prio),
31a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin      _event(NULL),
32a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin      _thread(NULL),
33a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin      _id(0),
34a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin      _name(),
35a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin      _setThreadName(false)
36a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin{
37a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    _event = EventWrapper::Create();
38a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    _critsectStop = CriticalSectionWrapper::CreateCriticalSection();
39a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    if (threadName != NULL)
40a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    {
41a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        // Set the thread name to appear in the VS debugger.
42a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        _setThreadName = true;
43a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        strncpy(_name, threadName, kThreadMaxNameLength);
44a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    }
45a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin}
46a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin
47a6451827d543eb00824bc95097e47d0aac51ae93Alexander GutkinThreadWindows::~ThreadWindows()
48a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin{
49a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin#ifdef _DEBUG
50a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    assert(!_alive);
51a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin#endif
52a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    if (_thread)
53a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    {
54a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        CloseHandle(_thread);
55a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    }
56a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    if(_event)
57a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    {
58a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        delete _event;
59a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    }
60a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    if(_critsectStop)
61a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    {
62a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        delete _critsectStop;
63a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    }
64a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin}
65a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin
66a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkinuint32_t ThreadWrapper::GetThreadId() {
67a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin  return GetCurrentThreadId();
68a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin}
69a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin
70a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkinunsigned int WINAPI ThreadWindows::StartThread(LPVOID lpParameter)
71a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin{
72a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    static_cast<ThreadWindows*>(lpParameter)->Run();
73a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    return 0;
74a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin}
75a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin
76a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkinbool ThreadWindows::Start(unsigned int& threadID)
77a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin{
78a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    _doNotCloseHandle = false;
79a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin
80a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    // Set stack size to 1M
81a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    _thread=(HANDLE)_beginthreadex(NULL, 1024*1024, StartThread, (void*)this, 0,
82a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin                                   &threadID);
83a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    if(_thread == NULL)
84a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    {
85a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        return false;
86a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    }
87a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    _id = threadID;
88a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    _event->Wait(INFINITE);
89a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin
90a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    switch(_prio)
91a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    {
92a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    case kLowPriority:
93a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        SetThreadPriority(_thread, THREAD_PRIORITY_BELOW_NORMAL);
94a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        break;
95a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    case kNormalPriority:
96a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        SetThreadPriority(_thread, THREAD_PRIORITY_NORMAL);
97a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        break;
98a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    case kHighPriority:
99a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        SetThreadPriority(_thread, THREAD_PRIORITY_ABOVE_NORMAL);
100a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        break;
101a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    case kHighestPriority:
102a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        SetThreadPriority(_thread, THREAD_PRIORITY_HIGHEST);
103a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        break;
104a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    case kRealtimePriority:
105a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        SetThreadPriority(_thread, THREAD_PRIORITY_TIME_CRITICAL);
106a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        break;
107a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    };
108a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    return true;
109a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin}
110a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin
111a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkinbool ThreadWindows::SetAffinity(const int* processorNumbers,
112a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin                                const unsigned int amountOfProcessors)
113a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin{
114a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    DWORD_PTR processorBitMask = 0;
115a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    for(unsigned int processorIndex = 0;
116a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        processorIndex < amountOfProcessors;
117a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        processorIndex++)
118a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    {
119a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        // Convert from an array with processor numbers to a bitmask
120a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        // Processor numbers start at zero.
121a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        // TODO (hellner): this looks like a bug. Shouldn't the '=' be a '+='?
122a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        // Or even better |=
123a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        processorBitMask = 1 << processorNumbers[processorIndex];
124a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    }
125a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    return SetThreadAffinityMask(_thread,processorBitMask) != 0;
126a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin}
127a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin
128a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkinvoid ThreadWindows::SetNotAlive()
129a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin{
130a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    _alive = false;
131a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin}
132a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin
133a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkinbool ThreadWindows::Shutdown()
134a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin{
135a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    DWORD exitCode = 0;
136a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    BOOL ret = TRUE;
137a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    if (_thread)
138a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    {
139a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        ret = TerminateThread(_thread, exitCode);
140a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        _alive = false;
141a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        _dead = true;
142a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        _thread = NULL;
143a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    }
144a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    return ret == TRUE;
145a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin}
146a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin
147a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkinbool ThreadWindows::Stop()
148a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin{
149a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    _critsectStop->Enter();
150a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    // Prevents the handle from being closed in ThreadWindows::Run()
151a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    _doNotCloseHandle = true;
152a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    _alive = false;
153a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    bool signaled = false;
154a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    if (_thread && !_dead)
155a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    {
156a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        _critsectStop->Leave();
157a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        // Wait up to 2 seconds for the thread to complete.
158a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        if( WAIT_OBJECT_0 == WaitForSingleObject(_thread, 2000))
159a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        {
160a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin            signaled = true;
161a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        }
162a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        _critsectStop->Enter();
163a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    }
164a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    if (_thread)
165a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    {
166a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        CloseHandle(_thread);
167a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        _thread = NULL;
168a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    }
169a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    _critsectStop->Leave();
170a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin
171a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    if (_dead || signaled)
172a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    {
173a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        return true;
174a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    }
175a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    else
176a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    {
177a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        return false;
178a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    }
179a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin}
180a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin
181a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkinvoid ThreadWindows::Run()
182a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin{
183a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    _alive = true;
184a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    _dead = false;
185a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    _event->Set();
186a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin
187a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    // All tracing must be after _event->Set to avoid deadlock in Trace.
188a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    if (_setThreadName)
189a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    {
190a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        WEBRTC_TRACE(kTraceStateInfo, kTraceUtility, _id,
191a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin                     "Thread with name:%s started ", _name);
192a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        SetThreadName(-1, _name); // -1, set thread name for the calling thread.
193a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    }else
194a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    {
195a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        WEBRTC_TRACE(kTraceStateInfo, kTraceUtility, _id,
196a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin                     "Thread without name started");
197a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    }
198a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin
199a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    do
200a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    {
201a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        if (_runFunction)
202a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        {
203a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin            if (!_runFunction(_obj))
204a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin            {
205a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin                _alive = false;
206a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin            }
207a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        } else {
208a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin            _alive = false;
209a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        }
210a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    } while(_alive);
211a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin
212a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    if (_setThreadName)
213a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    {
214a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        WEBRTC_TRACE(kTraceStateInfo, kTraceUtility, _id,
215a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin                     "Thread with name:%s stopped", _name);
216a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    } else {
217a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        WEBRTC_TRACE(kTraceStateInfo, kTraceUtility,_id,
218a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin                     "Thread without name stopped");
219a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    }
220a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin
221a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    _critsectStop->Enter();
222a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin
223a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    if (_thread && !_doNotCloseHandle)
224a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    {
225a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        HANDLE thread = _thread;
226a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        _thread = NULL;
227a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin        CloseHandle(thread);
228a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    }
229a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    _dead = true;
230a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin
231a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin    _critsectStop->Leave();
232a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin};
233a6451827d543eb00824bc95097e47d0aac51ae93Alexander Gutkin} // namespace webrtc
234