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 |