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..528a2220ac245c5064f9c5e75e0a222f40b76244 100644 |
| --- a/webrtc/base/platform_thread.cc |
| +++ b/webrtc/base/platform_thread.cc |
| @@ -13,6 +13,7 @@ |
| #include <string.h> |
| #include "webrtc/base/checks.h" |
| +#include "webrtc/base/thread_checker.h" |
| #if defined(WEBRTC_LINUX) |
| #include <sys/prctl.h> |
| @@ -80,3 +81,201 @@ 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)) |
| + .Pass(); |
|
tommi
2015/11/23 14:49:11
std::move?
pbos-webrtc
2015/11/23 15:05:40
Done.
|
| +} |
| + |
| +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; |
| +}; |
| +#endif // defined(WEBRTC_WIN) |
| +} |
| + |
| +#if defined(WEBRTC_POSIX) |
| +int PlatformThread::ConvertToSystemPriority(ThreadPriority priority, |
|
tommi
2015/11/23 14:49:11
actually, I took a look at the test that calls thi
pbos-webrtc
2015/11/23 15:05:39
Deleted, nuked, gone, done (test is that is).
|
| + 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_POSIX) |
| + |
| +PlatformThread::PlatformThread(ThreadRunFunction func, |
| + void* obj, |
| + const char* thread_name) |
| + : run_function_(func), |
| + obj_(obj), |
| + name_(thread_name ? thread_name : "webrtc"), |
| + thread_checker_(new rtc::ThreadChecker()), |
| +#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) |
| +} |
| + |
| +uint32_t PlatformThread::GetThreadId() { |
| +#if defined(WEBRTC_WIN) |
| + return GetCurrentThreadId(); |
| +#else |
| + return rtc::CurrentThreadId(); |
| +#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 |