| 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);
|
| #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
|
|
|