Chromium Code Reviews| Index: webrtc/base/platform_thread.cc |
| diff --git a/webrtc/base/platform_thread.cc b/webrtc/base/platform_thread.cc |
| index 4167392363039e8a4225c8431ddd8ba9ba3f3c08..d32311bcea3ac0260111f57d9551cc0b75779393 100644 |
| --- a/webrtc/base/platform_thread.cc |
| +++ b/webrtc/base/platform_thread.cc |
| @@ -10,8 +10,6 @@ |
| #include "webrtc/base/platform_thread.h" |
| -#include <string.h> |
| - |
| #include "webrtc/base/checks.h" |
| #if defined(WEBRTC_LINUX) |
| @@ -58,7 +56,6 @@ bool IsThreadRefEqual(const PlatformThreadRef& a, const PlatformThreadRef& b) { |
| } |
| void SetCurrentThreadName(const char* name) { |
| - RTC_DCHECK(strlen(name) < 64); |
|
tommi
2015/11/23 15:54:28
why remove?
pbos-webrtc
2015/11/23 16:18:22
Checked in ctor for all platforms now.
|
| #if defined(WEBRTC_WIN) |
| struct { |
| DWORD dwType; |
| @@ -80,3 +77,189 @@ void SetCurrentThreadName(const char* name) { |
| } |
| } // namespace rtc |
| + |
| +namespace webrtc { |
| + |
| +rtc::scoped_ptr<PlatformThread> PlatformThread::CreateThread( |
| + ThreadRunFunction func, |
| + void* obj, |
| + const char* thread_name) { |
| + return rtc::scoped_ptr<PlatformThread>( |
| + new PlatformThread(func, obj, thread_name)); |
| +} |
| + |
| +namespace { |
| +#if defined(WEBRTC_WIN) |
| +void CALLBACK RaiseFlag(ULONG_PTR param) { |
| + *reinterpret_cast<bool*>(param) = true; |
| +} |
| +#else |
| +struct ThreadAttributes { |
| + ThreadAttributes() { pthread_attr_init(&attr); } |
| + ~ThreadAttributes() { pthread_attr_destroy(&attr); } |
| + pthread_attr_t* operator&() { return &attr; } |
| + pthread_attr_t attr; |
| +}; |
| + |
| +int ConvertToSystemPriority(ThreadPriority priority, |
| + int min_prio, |
| + int max_prio) { |
| + RTC_DCHECK(max_prio - min_prio > 2); |
| + const int top_prio = max_prio - 1; |
| + const int low_prio = min_prio + 1; |
| + |
| + switch (priority) { |
| + case kLowPriority: |
| + return low_prio; |
| + case kNormalPriority: |
| + // The -1 ensures that the kHighPriority is always greater or equal to |
| + // kNormalPriority. |
| + return (low_prio + top_prio - 1) / 2; |
| + case kHighPriority: |
| + return std::max(top_prio - 2, low_prio); |
| + case kHighestPriority: |
| + return std::max(top_prio - 1, low_prio); |
| + case kRealtimePriority: |
| + return top_prio; |
| + } |
| + RTC_DCHECK(false); |
| + return low_prio; |
| +} |
| +#endif // defined(WEBRTC_WIN) |
| +} |
| + |
| +PlatformThread::PlatformThread(ThreadRunFunction func, |
| + void* obj, |
| + const char* thread_name) |
| + : run_function_(func), |
| + obj_(obj), |
| + name_(thread_name ? thread_name : "webrtc"), |
| +#if defined(WEBRTC_WIN) |
| + stop_(false), |
| + thread_(NULL) { |
| +#else |
| + stop_event_(false, false), |
| + thread_(0) { |
| +#endif // defined(WEBRTC_WIN) |
| + RTC_DCHECK(func); |
| + RTC_DCHECK(name_.length() < 64); |
| +} |
| + |
| +PlatformThread::~PlatformThread() { |
| + RTC_DCHECK(thread_checker_.CalledOnValidThread()); |
| +#if defined(WEBRTC_WIN) |
| + RTC_DCHECK(!thread_); |
| +#endif // defined(WEBRTC_WIN) |
| +} |
| + |
| +#if defined(WEBRTC_WIN) |
| +DWORD WINAPI PlatformThread::StartThread(void* param) { |
| + static_cast<PlatformThread*>(param)->Run(); |
| + return 0; |
| +} |
| +#else |
| +void* PlatformThread::StartThread(void* param) { |
| + static_cast<PlatformThread*>(param)->Run(); |
| + return 0; |
| +} |
| +#endif // defined(WEBRTC_WIN) |
| + |
| +bool PlatformThread::Start() { |
| + RTC_DCHECK(thread_checker_.CalledOnValidThread()); |
| + RTC_DCHECK(!thread_) << "Thread already started?"; |
| +#if defined(WEBRTC_WIN) |
| + 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); |
| + RTC_CHECK(thread_) << "CreateThread failed"; |
| +#else |
| + ThreadAttributes attr; |
| + // Set the stack stack size to 1M. |
| + pthread_attr_setstacksize(&attr, 1024 * 1024); |
| + RTC_CHECK_EQ(0, pthread_create(&thread_, &attr, &StartThread, this)); |
| +#endif // defined(WEBRTC_WIN) |
| + return true; |
| +} |
| + |
| +bool PlatformThread::Stop() { |
| + RTC_DCHECK(thread_checker_.CalledOnValidThread()); |
| +#if defined(WEBRTC_WIN) |
| + 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; |
| + } |
| +#else |
| + if (!thread_) |
| + return true; |
| + |
| + stop_event_.Set(); |
| + RTC_CHECK_EQ(0, pthread_join(thread_, nullptr)); |
| + thread_ = 0; |
| +#endif // defined(WEBRTC_WIN) |
| + return true; |
| +} |
| + |
| +void PlatformThread::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; |
| +#if defined(WEBRTC_WIN) |
| + // Alertable sleep to permit RaiseFlag to run and update |stop_|. |
| + SleepEx(0, true); |
| + } while (!stop_); |
| +#else |
| + } while (!stop_event_.Wait(0)); |
| +#endif // defined(WEBRTC_WIN) |
| +} |
| + |
| +bool PlatformThread::SetPriority(ThreadPriority priority) { |
| + RTC_DCHECK(thread_checker_.CalledOnValidThread()); |
| +#if defined(WEBRTC_WIN) |
| + return thread_ && SetThreadPriority(thread_, priority); |
| +#else |
| + if (!thread_) |
| + return false; |
| +#if defined(WEBRTC_CHROMIUM_BUILD) && defined(WEBRTC_LINUX) |
| + // TODO(tommi): Switch to the same mechanism as Chromium uses for |
| + // changing thread priorities. |
| + return true; |
| +#else |
| +#ifdef WEBRTC_THREAD_RR |
| + const int policy = SCHED_RR; |
| +#else |
| + const int policy = SCHED_FIFO; |
| +#endif |
| + const int min_prio = sched_get_priority_min(policy); |
| + const int max_prio = sched_get_priority_max(policy); |
| + if (min_prio == -1 || max_prio == -1) { |
| + return false; |
| + } |
| + |
| + if (max_prio - min_prio <= 2) |
| + return false; |
| + |
| + sched_param param; |
| + param.sched_priority = ConvertToSystemPriority(priority, min_prio, max_prio); |
| + if (pthread_setschedparam(thread_, policy, ¶m) != 0) { |
| + return false; |
| + } |
| + |
| + return true; |
| +#endif // defined(WEBRTC_CHROMIUM_BUILD) && defined(WEBRTC_LINUX) |
| +#endif // defined(WEBRTC_WIN) |
| +} |
| + |
| +} // namespace webrtc |