| /* |
| * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. |
| * |
| * Use of this source code is governed by a BSD-style license |
| * that can be found in the LICENSE file in the root of the source |
| * tree. An additional intellectual property rights grant can be found |
| * in the file PATENTS. All contributing project authors may |
| * be found in the AUTHORS file in the root of the source tree. |
| */ |
| |
| #include "webrtc/system_wrappers/source/thread_win.h" |
| |
| #include <process.h> |
| #include <stdio.h> |
| #include <windows.h> |
| |
| #include "webrtc/base/checks.h" |
| #include "webrtc/base/platform_thread.h" |
| #include "webrtc/system_wrappers/interface/trace.h" |
| |
| namespace webrtc { |
| namespace { |
| void CALLBACK RaiseFlag(ULONG_PTR param) { |
| *reinterpret_cast<bool*>(param) = true; |
| } |
| } |
| |
| ThreadWindows::ThreadWindows(ThreadRunFunction func, void* obj, |
| const char* thread_name) |
| : run_function_(func), |
| obj_(obj), |
| stop_(false), |
| thread_(NULL), |
| name_(thread_name ? thread_name : "webrtc") { |
| DCHECK(func); |
| } |
| |
| ThreadWindows::~ThreadWindows() { |
| DCHECK(main_thread_.CalledOnValidThread()); |
| DCHECK(!thread_); |
| } |
| |
| // static |
| uint32_t ThreadWrapper::GetThreadId() { |
| return GetCurrentThreadId(); |
| } |
| |
| // static |
| DWORD WINAPI ThreadWindows::StartThread(void* param) { |
| static_cast<ThreadWindows*>(param)->Run(); |
| return 0; |
| } |
| |
| bool ThreadWindows::Start() { |
| DCHECK(main_thread_.CalledOnValidThread()); |
| DCHECK(!thread_); |
| |
| stop_ = false; |
| |
| // See bug 2902 for background on STACK_SIZE_PARAM_IS_A_RESERVATION. |
| // Set the reserved stack stack size to 1M, which is the default on Windows |
| // and Linux. |
| DWORD thread_id; |
| thread_ = ::CreateThread(NULL, 1024 * 1024, &StartThread, this, |
| STACK_SIZE_PARAM_IS_A_RESERVATION, &thread_id); |
| if (!thread_ ) { |
| DCHECK(false) << "CreateThread failed"; |
| return false; |
| } |
| |
| return true; |
| } |
| |
| bool ThreadWindows::Stop() { |
| DCHECK(main_thread_.CalledOnValidThread()); |
| if (thread_) { |
| // Set stop_ to |true| on the worker thread. |
| QueueUserAPC(&RaiseFlag, thread_, reinterpret_cast<ULONG_PTR>(&stop_)); |
| WaitForSingleObject(thread_, INFINITE); |
| CloseHandle(thread_); |
| thread_ = nullptr; |
| } |
| |
| return true; |
| } |
| |
| bool ThreadWindows::SetPriority(ThreadPriority priority) { |
| DCHECK(main_thread_.CalledOnValidThread()); |
| return thread_ && SetThreadPriority(thread_, priority); |
| } |
| |
| void ThreadWindows::Run() { |
| if (!name_.empty()) |
| rtc::SetCurrentThreadName(name_.c_str()); |
| |
| do { |
| // The interface contract of Start/Stop is that for a successfull call to |
| // Start, there should be at least one call to the run function. So we |
| // call the function before checking |stop_|. |
| if (!run_function_(obj_)) |
| break; |
| // Alertable sleep to permit RaiseFlag to run and update |stop_|. |
| SleepEx(0, true); |
| } while (!stop_); |
| } |
| |
| } // namespace webrtc |