Move ThreadWrapper to ProcessThread in base.

Also removes all virtual methods. Permits using a thread from
rtc_base_approved (namely event tracing).

BUG=webrtc:5158
R=tommi@webrtc.org

Review URL: https://codereview.webrtc.org/1469013002

Cr-Commit-Position: refs/heads/master@{#10760}
diff --git a/webrtc/base/platform_thread.cc b/webrtc/base/platform_thread.cc
index 4167392..d32311b 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 @@
 }
 
 void SetCurrentThreadName(const char* name) {
-  RTC_DCHECK(strlen(name) < 64);
 #if defined(WEBRTC_WIN)
   struct {
     DWORD dwType;
@@ -80,3 +77,189 @@
 }
 
 }  // 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, &param) != 0) {
+    return false;
+  }
+
+  return true;
+#endif  // defined(WEBRTC_CHROMIUM_BUILD) && defined(WEBRTC_LINUX)
+#endif  // defined(WEBRTC_WIN)
+}
+
+}  // namespace webrtc