147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org/*
247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org *  Copyright 2004 The WebRTC Project Authors. All rights reserved.
347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org *
447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org *  Use of this source code is governed by a BSD-style license
547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org *  that can be found in the LICENSE file in the root of the source
647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org *  tree. An additional intellectual property rights grant can be found
747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org *  in the file PATENTS.  All contributing project authors may
847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org *  be found in the AUTHORS file in the root of the source tree.
947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org */
1047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
1147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include "webrtc/base/thread.h"
1247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
1347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#ifndef __has_feature
1447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#define __has_feature(x) 0  // Compatibility with non-clang or LLVM compilers.
1547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#endif  // __has_feature
1647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
1747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#if defined(WEBRTC_WIN)
1847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include <comdef.h>
1947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#elif defined(WEBRTC_POSIX)
2047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include <time.h>
2147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#endif
2247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
2347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include "webrtc/base/common.h"
2447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include "webrtc/base/logging.h"
2547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include "webrtc/base/stringutils.h"
2647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include "webrtc/base/timeutils.h"
2747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
2847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#if !__has_feature(objc_arc) && (defined(WEBRTC_MAC))
2947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include "webrtc/base/maccocoathreadhelper.h"
3047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include "webrtc/base/scoped_autorelease_pool.h"
3147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#endif
3247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
3347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgnamespace rtc {
3447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
3547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgThreadManager* ThreadManager::Instance() {
3647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  LIBJINGLE_DEFINE_STATIC_LOCAL(ThreadManager, thread_manager, ());
3747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return &thread_manager;
3847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
3947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
4047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// static
4147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgThread* Thread::Current() {
4247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return ThreadManager::Instance()->CurrentThread();
4347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
4447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
4547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#if defined(WEBRTC_POSIX)
4647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgThreadManager::ThreadManager() {
4747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  pthread_key_create(&key_, NULL);
4847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#ifndef NO_MAIN_THREAD_WRAPPING
4947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  WrapCurrentThread();
5047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#endif
5147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#if !__has_feature(objc_arc) && (defined(WEBRTC_MAC))
5247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // Under Automatic Reference Counting (ARC), you cannot use autorelease pools
5347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // directly. Instead, you use @autoreleasepool blocks instead.  Also, we are
5447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // maintaining thread safety using immutability within context of GCD dispatch
5547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // queues in this case.
5647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  InitCocoaMultiThreading();
5747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#endif
5847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
5947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
6047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgThreadManager::~ThreadManager() {
6147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#if __has_feature(objc_arc)
6247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  @autoreleasepool
6347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#elif defined(WEBRTC_MAC)
6447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // This is called during exit, at which point apparently no NSAutoreleasePools
6547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // are available; but we might still need them to do cleanup (or we get the
6647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // "no autoreleasepool in place, just leaking" warning when exiting).
6747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  ScopedAutoreleasePool pool;
6847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#endif
6947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  {
7047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    UnwrapCurrentThread();
7147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    pthread_key_delete(key_);
7247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
7347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
7447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
7547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgThread *ThreadManager::CurrentThread() {
7647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return static_cast<Thread *>(pthread_getspecific(key_));
7747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
7847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
7947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgvoid ThreadManager::SetCurrentThread(Thread *thread) {
8047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  pthread_setspecific(key_, thread);
8147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
8247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#endif
8347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
8447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#if defined(WEBRTC_WIN)
8547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgThreadManager::ThreadManager() {
8647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  key_ = TlsAlloc();
8747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#ifndef NO_MAIN_THREAD_WRAPPING
8847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  WrapCurrentThread();
8947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#endif
9047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
9147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
9247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgThreadManager::~ThreadManager() {
9347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  UnwrapCurrentThread();
9447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  TlsFree(key_);
9547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
9647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
9747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgThread *ThreadManager::CurrentThread() {
9847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return static_cast<Thread *>(TlsGetValue(key_));
9947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
10047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
10147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgvoid ThreadManager::SetCurrentThread(Thread *thread) {
10247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  TlsSetValue(key_, thread);
10347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
10447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#endif
10547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
10647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgThread *ThreadManager::WrapCurrentThread() {
10747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  Thread* result = CurrentThread();
10847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (NULL == result) {
10947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    result = new Thread();
110692b0633dd5ffbd0235a73a6f4f7cf864e78b285jiayl@webrtc.org    result->WrapCurrentWithThreadManager(this, true);
11147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
11247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return result;
11347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
11447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
11547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgvoid ThreadManager::UnwrapCurrentThread() {
11647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  Thread* t = CurrentThread();
11747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (t && !(t->IsOwned())) {
11847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    t->UnwrapCurrent();
11947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    delete t;
12047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
12147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
12247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
12347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgstruct ThreadInit {
12447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  Thread* thread;
12547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  Runnable* runnable;
12647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org};
12747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
128d3de227a946cf9f65c5255743efb920977061278henrike@webrtc.orgThread::ScopedDisallowBlockingCalls::ScopedDisallowBlockingCalls()
129d3de227a946cf9f65c5255743efb920977061278henrike@webrtc.org  : thread_(Thread::Current()),
130d3de227a946cf9f65c5255743efb920977061278henrike@webrtc.org    previous_state_(thread_->SetAllowBlockingCalls(false)) {
131d3de227a946cf9f65c5255743efb920977061278henrike@webrtc.org}
132d3de227a946cf9f65c5255743efb920977061278henrike@webrtc.org
133d3de227a946cf9f65c5255743efb920977061278henrike@webrtc.orgThread::ScopedDisallowBlockingCalls::~ScopedDisallowBlockingCalls() {
134d3de227a946cf9f65c5255743efb920977061278henrike@webrtc.org  ASSERT(thread_->IsCurrent());
135d3de227a946cf9f65c5255743efb920977061278henrike@webrtc.org  thread_->SetAllowBlockingCalls(previous_state_);
136d3de227a946cf9f65c5255743efb920977061278henrike@webrtc.org}
137d3de227a946cf9f65c5255743efb920977061278henrike@webrtc.org
13847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgThread::Thread(SocketServer* ss)
13947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    : MessageQueue(ss),
14047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      priority_(PRIORITY_NORMAL),
1410631e37660e5e9b1566089c8306094ad6ee9516efischman@webrtc.org      running_(true, false),
14247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#if defined(WEBRTC_WIN)
14347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      thread_(NULL),
14447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      thread_id_(0),
14547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#endif
146d3de227a946cf9f65c5255743efb920977061278henrike@webrtc.org      owned_(true),
147d3de227a946cf9f65c5255743efb920977061278henrike@webrtc.org      blocking_calls_allowed_(true) {
14847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  SetName("Thread", this);  // default name
14947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
15047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
15147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgThread::~Thread() {
15247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  Stop();
15311e96c736207147b6c79963073f89112a8dbefb4henrike@webrtc.org  Clear(NULL);
15447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
15547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
15647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgbool Thread::SleepMs(int milliseconds) {
157d3de227a946cf9f65c5255743efb920977061278henrike@webrtc.org  AssertBlockingIsAllowedOnCurrentThread();
158d3de227a946cf9f65c5255743efb920977061278henrike@webrtc.org
15947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#if defined(WEBRTC_WIN)
16047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  ::Sleep(milliseconds);
16147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return true;
16247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#else
16347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // POSIX has both a usleep() and a nanosleep(), but the former is deprecated,
16447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // so we use nanosleep() even though it has greater precision than necessary.
16547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  struct timespec ts;
16647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  ts.tv_sec = milliseconds / 1000;
16747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  ts.tv_nsec = (milliseconds % 1000) * 1000000;
16847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  int ret = nanosleep(&ts, NULL);
16947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (ret != 0) {
17047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    LOG_ERR(LS_WARNING) << "nanosleep() returning early";
17147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return false;
17247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
17347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return true;
17447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#endif
17547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
17647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
17747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgbool Thread::SetName(const std::string& name, const void* obj) {
1780631e37660e5e9b1566089c8306094ad6ee9516efischman@webrtc.org  if (running()) return false;
17947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  name_ = name;
18047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (obj) {
18147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    char buf[16];
18247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    sprintfn(buf, sizeof(buf), " 0x%p", obj);
18347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    name_ += buf;
18447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
18547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return true;
18647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
18747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
18847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgbool Thread::SetPriority(ThreadPriority priority) {
18947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#if defined(WEBRTC_WIN)
1900631e37660e5e9b1566089c8306094ad6ee9516efischman@webrtc.org  if (running()) {
191692b0633dd5ffbd0235a73a6f4f7cf864e78b285jiayl@webrtc.org    ASSERT(thread_ != NULL);
19247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    BOOL ret = FALSE;
19347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if (priority == PRIORITY_NORMAL) {
19447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      ret = ::SetThreadPriority(thread_, THREAD_PRIORITY_NORMAL);
19547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    } else if (priority == PRIORITY_HIGH) {
19647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      ret = ::SetThreadPriority(thread_, THREAD_PRIORITY_HIGHEST);
19747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    } else if (priority == PRIORITY_ABOVE_NORMAL) {
19847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      ret = ::SetThreadPriority(thread_, THREAD_PRIORITY_ABOVE_NORMAL);
19947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    } else if (priority == PRIORITY_IDLE) {
20047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      ret = ::SetThreadPriority(thread_, THREAD_PRIORITY_IDLE);
20147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    }
20247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if (!ret) {
20347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      return false;
20447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    }
20547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
20647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  priority_ = priority;
20747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return true;
20847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#else
20947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // TODO: Implement for Linux/Mac if possible.
2100631e37660e5e9b1566089c8306094ad6ee9516efischman@webrtc.org  if (running()) return false;
21147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  priority_ = priority;
21247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return true;
21347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#endif
21447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
21547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
21647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgbool Thread::Start(Runnable* runnable) {
21747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  ASSERT(owned_);
21847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (!owned_) return false;
2190631e37660e5e9b1566089c8306094ad6ee9516efischman@webrtc.org  ASSERT(!running());
2200631e37660e5e9b1566089c8306094ad6ee9516efischman@webrtc.org  if (running()) return false;
22147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
22247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  Restart();  // reset fStop_ if the thread is being restarted
22347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
22447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // Make sure that ThreadManager is created on the main thread before
22547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // we start a new thread.
22647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  ThreadManager::Instance();
22747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
22847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  ThreadInit* init = new ThreadInit;
22947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  init->thread = this;
23047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  init->runnable = runnable;
23147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#if defined(WEBRTC_WIN)
23247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  DWORD flags = 0;
23347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (priority_ != PRIORITY_NORMAL) {
23447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    flags = CREATE_SUSPENDED;
23547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
23647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  thread_ = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)PreRun, init, flags,
23747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org                         &thread_id_);
23847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (thread_) {
2390631e37660e5e9b1566089c8306094ad6ee9516efischman@webrtc.org    running_.Set();
24047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if (priority_ != PRIORITY_NORMAL) {
24147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      SetPriority(priority_);
24247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      ::ResumeThread(thread_);
24347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    }
24447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  } else {
24547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return false;
24647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
24747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#elif defined(WEBRTC_POSIX)
24847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  pthread_attr_t attr;
24947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  pthread_attr_init(&attr);
25047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
25147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // Thread priorities are not supported in NaCl.
25247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#if !defined(__native_client__)
25347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (priority_ != PRIORITY_NORMAL) {
25447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if (priority_ == PRIORITY_IDLE) {
25547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      // There is no POSIX-standard way to set a below-normal priority for an
25647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      // individual thread (only whole process), so let's not support it.
25747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      LOG(LS_WARNING) << "PRIORITY_IDLE not supported";
25847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    } else {
25947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      // Set real-time round-robin policy.
26047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      if (pthread_attr_setschedpolicy(&attr, SCHED_RR) != 0) {
26147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        LOG(LS_ERROR) << "pthread_attr_setschedpolicy";
26247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      }
26347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      struct sched_param param;
26447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      if (pthread_attr_getschedparam(&attr, &param) != 0) {
26547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        LOG(LS_ERROR) << "pthread_attr_getschedparam";
26647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      } else {
26747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        // The numbers here are arbitrary.
26847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        if (priority_ == PRIORITY_HIGH) {
26947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org          param.sched_priority = 6;           // 6 = HIGH
27047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        } else {
27147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org          ASSERT(priority_ == PRIORITY_ABOVE_NORMAL);
27247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org          param.sched_priority = 4;           // 4 = ABOVE_NORMAL
27347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        }
27447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        if (pthread_attr_setschedparam(&attr, &param) != 0) {
27547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org          LOG(LS_ERROR) << "pthread_attr_setschedparam";
27647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        }
27747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      }
27847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    }
27947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
28047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#endif  // !defined(__native_client__)
28147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
28247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  int error_code = pthread_create(&thread_, &attr, PreRun, init);
28347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (0 != error_code) {
28447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    LOG(LS_ERROR) << "Unable to create pthread, error " << error_code;
28547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return false;
28647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
2870631e37660e5e9b1566089c8306094ad6ee9516efischman@webrtc.org  running_.Set();
28847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#endif
28947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return true;
29047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
29147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
292692b0633dd5ffbd0235a73a6f4f7cf864e78b285jiayl@webrtc.orgbool Thread::WrapCurrent() {
293692b0633dd5ffbd0235a73a6f4f7cf864e78b285jiayl@webrtc.org  return WrapCurrentWithThreadManager(ThreadManager::Instance(), true);
294692b0633dd5ffbd0235a73a6f4f7cf864e78b285jiayl@webrtc.org}
295692b0633dd5ffbd0235a73a6f4f7cf864e78b285jiayl@webrtc.org
296692b0633dd5ffbd0235a73a6f4f7cf864e78b285jiayl@webrtc.orgvoid Thread::UnwrapCurrent() {
297692b0633dd5ffbd0235a73a6f4f7cf864e78b285jiayl@webrtc.org  // Clears the platform-specific thread-specific storage.
298692b0633dd5ffbd0235a73a6f4f7cf864e78b285jiayl@webrtc.org  ThreadManager::Instance()->SetCurrentThread(NULL);
299692b0633dd5ffbd0235a73a6f4f7cf864e78b285jiayl@webrtc.org#if defined(WEBRTC_WIN)
300692b0633dd5ffbd0235a73a6f4f7cf864e78b285jiayl@webrtc.org  if (thread_ != NULL) {
301692b0633dd5ffbd0235a73a6f4f7cf864e78b285jiayl@webrtc.org    if (!CloseHandle(thread_)) {
302692b0633dd5ffbd0235a73a6f4f7cf864e78b285jiayl@webrtc.org      LOG_GLE(LS_ERROR) << "When unwrapping thread, failed to close handle.";
303692b0633dd5ffbd0235a73a6f4f7cf864e78b285jiayl@webrtc.org    }
304692b0633dd5ffbd0235a73a6f4f7cf864e78b285jiayl@webrtc.org    thread_ = NULL;
305692b0633dd5ffbd0235a73a6f4f7cf864e78b285jiayl@webrtc.org  }
306692b0633dd5ffbd0235a73a6f4f7cf864e78b285jiayl@webrtc.org#endif
307692b0633dd5ffbd0235a73a6f4f7cf864e78b285jiayl@webrtc.org  running_.Reset();
308692b0633dd5ffbd0235a73a6f4f7cf864e78b285jiayl@webrtc.org}
309692b0633dd5ffbd0235a73a6f4f7cf864e78b285jiayl@webrtc.org
310692b0633dd5ffbd0235a73a6f4f7cf864e78b285jiayl@webrtc.orgvoid Thread::SafeWrapCurrent() {
311692b0633dd5ffbd0235a73a6f4f7cf864e78b285jiayl@webrtc.org  WrapCurrentWithThreadManager(ThreadManager::Instance(), false);
312692b0633dd5ffbd0235a73a6f4f7cf864e78b285jiayl@webrtc.org}
313692b0633dd5ffbd0235a73a6f4f7cf864e78b285jiayl@webrtc.org
31447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgvoid Thread::Join() {
315d3de227a946cf9f65c5255743efb920977061278henrike@webrtc.org  AssertBlockingIsAllowedOnCurrentThread();
316d3de227a946cf9f65c5255743efb920977061278henrike@webrtc.org
3170631e37660e5e9b1566089c8306094ad6ee9516efischman@webrtc.org  if (running()) {
31847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    ASSERT(!IsCurrent());
31947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#if defined(WEBRTC_WIN)
320692b0633dd5ffbd0235a73a6f4f7cf864e78b285jiayl@webrtc.org    ASSERT(thread_ != NULL);
32147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    WaitForSingleObject(thread_, INFINITE);
32247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    CloseHandle(thread_);
32347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    thread_ = NULL;
32447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    thread_id_ = 0;
32547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#elif defined(WEBRTC_POSIX)
32647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    void *pv;
32747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    pthread_join(thread_, &pv);
32847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#endif
3290631e37660e5e9b1566089c8306094ad6ee9516efischman@webrtc.org    running_.Reset();
33047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
33147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
33247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
333d3de227a946cf9f65c5255743efb920977061278henrike@webrtc.orgbool Thread::SetAllowBlockingCalls(bool allow) {
334d3de227a946cf9f65c5255743efb920977061278henrike@webrtc.org  ASSERT(IsCurrent());
335d3de227a946cf9f65c5255743efb920977061278henrike@webrtc.org  bool previous = blocking_calls_allowed_;
336d3de227a946cf9f65c5255743efb920977061278henrike@webrtc.org  blocking_calls_allowed_ = allow;
337d3de227a946cf9f65c5255743efb920977061278henrike@webrtc.org  return previous;
338d3de227a946cf9f65c5255743efb920977061278henrike@webrtc.org}
339d3de227a946cf9f65c5255743efb920977061278henrike@webrtc.org
340d3de227a946cf9f65c5255743efb920977061278henrike@webrtc.org// static
341d3de227a946cf9f65c5255743efb920977061278henrike@webrtc.orgvoid Thread::AssertBlockingIsAllowedOnCurrentThread() {
342d3de227a946cf9f65c5255743efb920977061278henrike@webrtc.org#ifdef _DEBUG
343d3de227a946cf9f65c5255743efb920977061278henrike@webrtc.org  Thread* current = Thread::Current();
344d3de227a946cf9f65c5255743efb920977061278henrike@webrtc.org  ASSERT(!current || current->blocking_calls_allowed_);
345d3de227a946cf9f65c5255743efb920977061278henrike@webrtc.org#endif
346d3de227a946cf9f65c5255743efb920977061278henrike@webrtc.org}
347d3de227a946cf9f65c5255743efb920977061278henrike@webrtc.org
34847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#if defined(WEBRTC_WIN)
34947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// As seen on MSDN.
35047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// http://msdn.microsoft.com/en-us/library/xcb2z8hs(VS.71).aspx
35147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#define MSDEV_SET_THREAD_NAME  0x406D1388
35247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgtypedef struct tagTHREADNAME_INFO {
35347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  DWORD dwType;
35447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  LPCSTR szName;
35547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  DWORD dwThreadID;
35647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  DWORD dwFlags;
35747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} THREADNAME_INFO;
35847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
35947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgvoid SetThreadName(DWORD dwThreadID, LPCSTR szThreadName) {
36047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  THREADNAME_INFO info;
36147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  info.dwType = 0x1000;
36247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  info.szName = szThreadName;
36347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  info.dwThreadID = dwThreadID;
36447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  info.dwFlags = 0;
36547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
36647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  __try {
36747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    RaiseException(MSDEV_SET_THREAD_NAME, 0, sizeof(info) / sizeof(DWORD),
36847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org                   reinterpret_cast<ULONG_PTR*>(&info));
36947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
37047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  __except(EXCEPTION_CONTINUE_EXECUTION) {
37147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
37247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
3730631e37660e5e9b1566089c8306094ad6ee9516efischman@webrtc.org#endif  // WEBRTC_WIN
37447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
37547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgvoid* Thread::PreRun(void* pv) {
37647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  ThreadInit* init = static_cast<ThreadInit*>(pv);
37747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  ThreadManager::Instance()->SetCurrentThread(init->thread);
37847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#if defined(WEBRTC_WIN)
37947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  SetThreadName(GetCurrentThreadId(), init->thread->name_.c_str());
38047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#elif defined(WEBRTC_POSIX)
38147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // TODO: See if naming exists for pthreads.
38247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#endif
38347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#if __has_feature(objc_arc)
38447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  @autoreleasepool
38547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#elif defined(WEBRTC_MAC)
38647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // Make sure the new thread has an autoreleasepool
38747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  ScopedAutoreleasePool pool;
38847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#endif
38947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  {
39047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if (init->runnable) {
39147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      init->runnable->Run(init->thread);
39247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    } else {
39347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      init->thread->Run();
39447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    }
39547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    delete init;
39647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return NULL;
39747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
39847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
39947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
40047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgvoid Thread::Run() {
40147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  ProcessMessages(kForever);
40247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
40347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
40447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgbool Thread::IsOwned() {
40547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return owned_;
40647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
40747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
40847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgvoid Thread::Stop() {
40947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  MessageQueue::Quit();
41047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  Join();
41147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
41247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
41347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgvoid Thread::Send(MessageHandler *phandler, uint32 id, MessageData *pdata) {
41447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (fStop_)
41547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return;
41647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
41747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // Sent messages are sent to the MessageHandler directly, in the context
41847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // of "thread", like Win32 SendMessage. If in the right context,
41947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // call the handler directly.
42047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  Message msg;
42147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  msg.phandler = phandler;
42247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  msg.message_id = id;
42347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  msg.pdata = pdata;
42447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (IsCurrent()) {
42547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    phandler->OnMessage(&msg);
42647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return;
42747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
42847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
4298fd0eda9a5709127accccba383b258faf3503d2bjiayl@webrtc.org  AssertBlockingIsAllowedOnCurrentThread();
4308fd0eda9a5709127accccba383b258faf3503d2bjiayl@webrtc.org
43147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  AutoThread thread;
43247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  Thread *current_thread = Thread::Current();
43347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  ASSERT(current_thread != NULL);  // AutoThread ensures this
43447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
43547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  bool ready = false;
43647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  {
43747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    CritScope cs(&crit_);
43847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    _SendMessage smsg;
43947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    smsg.thread = current_thread;
44047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    smsg.msg = msg;
44147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    smsg.ready = &ready;
44247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    sendlist_.push_back(smsg);
44347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
44447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
44547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // Wait for a reply
44647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
44747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  ss_->WakeUp();
44847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
44947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  bool waited = false;
45047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  crit_.Enter();
45147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  while (!ready) {
45247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    crit_.Leave();
4538fd0eda9a5709127accccba383b258faf3503d2bjiayl@webrtc.org    // We need to limit "ReceiveSends" to |this| thread to avoid an arbitrary
4548fd0eda9a5709127accccba383b258faf3503d2bjiayl@webrtc.org    // thread invoking calls on the current thread.
4558fd0eda9a5709127accccba383b258faf3503d2bjiayl@webrtc.org    current_thread->ReceiveSendsFromThread(this);
45647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    current_thread->socketserver()->Wait(kForever, false);
45747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    waited = true;
45847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    crit_.Enter();
45947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
46047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  crit_.Leave();
46147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
46247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // Our Wait loop above may have consumed some WakeUp events for this
46347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // MessageQueue, that weren't relevant to this Send.  Losing these WakeUps can
46447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // cause problems for some SocketServers.
46547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  //
46647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // Concrete example:
46747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // Win32SocketServer on thread A calls Send on thread B.  While processing the
46847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // message, thread B Posts a message to A.  We consume the wakeup for that
46947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // Post while waiting for the Send to complete, which means that when we exit
47047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // this loop, we need to issue another WakeUp, or else the Posted message
47147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // won't be processed in a timely manner.
47247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
47347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (waited) {
47447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    current_thread->socketserver()->WakeUp();
47547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
47647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
47747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
47847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgvoid Thread::ReceiveSends() {
4798fd0eda9a5709127accccba383b258faf3503d2bjiayl@webrtc.org  ReceiveSendsFromThread(NULL);
4808fd0eda9a5709127accccba383b258faf3503d2bjiayl@webrtc.org}
4818fd0eda9a5709127accccba383b258faf3503d2bjiayl@webrtc.org
4828fd0eda9a5709127accccba383b258faf3503d2bjiayl@webrtc.orgvoid Thread::ReceiveSendsFromThread(const Thread* source) {
48347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // Receive a sent message. Cleanup scenarios:
48447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // - thread sending exits: We don't allow this, since thread can exit
48547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  //   only via Join, so Send must complete.
48647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // - thread receiving exits: Wakeup/set ready in Thread::Clear()
48747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // - object target cleared: Wakeup/set ready in Thread::Clear()
4888fd0eda9a5709127accccba383b258faf3503d2bjiayl@webrtc.org  _SendMessage smsg;
4898fd0eda9a5709127accccba383b258faf3503d2bjiayl@webrtc.org
49047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  crit_.Enter();
4918fd0eda9a5709127accccba383b258faf3503d2bjiayl@webrtc.org  while (PopSendMessageFromThread(source, &smsg)) {
49247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    crit_.Leave();
4938fd0eda9a5709127accccba383b258faf3503d2bjiayl@webrtc.org
49447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    smsg.msg.phandler->OnMessage(&smsg.msg);
4958fd0eda9a5709127accccba383b258faf3503d2bjiayl@webrtc.org
49647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    crit_.Enter();
49747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    *smsg.ready = true;
49847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    smsg.thread->socketserver()->WakeUp();
49947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
50047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  crit_.Leave();
50147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
50247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
5038fd0eda9a5709127accccba383b258faf3503d2bjiayl@webrtc.orgbool Thread::PopSendMessageFromThread(const Thread* source, _SendMessage* msg) {
5048fd0eda9a5709127accccba383b258faf3503d2bjiayl@webrtc.org  for (std::list<_SendMessage>::iterator it = sendlist_.begin();
5058fd0eda9a5709127accccba383b258faf3503d2bjiayl@webrtc.org       it != sendlist_.end(); ++it) {
5068fd0eda9a5709127accccba383b258faf3503d2bjiayl@webrtc.org    if (it->thread == source || source == NULL) {
5078fd0eda9a5709127accccba383b258faf3503d2bjiayl@webrtc.org      *msg = *it;
5088fd0eda9a5709127accccba383b258faf3503d2bjiayl@webrtc.org      sendlist_.erase(it);
5098fd0eda9a5709127accccba383b258faf3503d2bjiayl@webrtc.org      return true;
5108fd0eda9a5709127accccba383b258faf3503d2bjiayl@webrtc.org    }
5118fd0eda9a5709127accccba383b258faf3503d2bjiayl@webrtc.org  }
5128fd0eda9a5709127accccba383b258faf3503d2bjiayl@webrtc.org  return false;
5138fd0eda9a5709127accccba383b258faf3503d2bjiayl@webrtc.org}
5148fd0eda9a5709127accccba383b258faf3503d2bjiayl@webrtc.org
51547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgvoid Thread::Clear(MessageHandler *phandler, uint32 id,
51647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org                   MessageList* removed) {
51747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  CritScope cs(&crit_);
51847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
51947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // Remove messages on sendlist_ with phandler
52047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // Object target cleared: remove from send list, wakeup/set ready
52147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  // if sender not NULL.
52247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
52347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  std::list<_SendMessage>::iterator iter = sendlist_.begin();
52447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  while (iter != sendlist_.end()) {
52547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    _SendMessage smsg = *iter;
52647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    if (smsg.msg.Match(phandler, id)) {
52747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      if (removed) {
52847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        removed->push_back(smsg.msg);
52947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      } else {
53047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        delete smsg.msg.pdata;
53147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      }
53247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      iter = sendlist_.erase(iter);
53347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      *smsg.ready = true;
53447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      smsg.thread->socketserver()->WakeUp();
53547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      continue;
53647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    }
53747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    ++iter;
53847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
53947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
54047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  MessageQueue::Clear(phandler, id, removed);
54147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
54247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
54347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgbool Thread::ProcessMessages(int cmsLoop) {
54447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  uint32 msEnd = (kForever == cmsLoop) ? 0 : TimeAfter(cmsLoop);
54547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  int cmsNext = cmsLoop;
54647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
54747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  while (true) {
54847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#if __has_feature(objc_arc)
54947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    @autoreleasepool
55047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#elif defined(WEBRTC_MAC)
55147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    // see: http://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/NSAutoreleasePool_Class/Reference/Reference.html
55247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    // Each thread is supposed to have an autorelease pool. Also for event loops
55347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    // like this, autorelease pool needs to be created and drained/released
55447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    // for each cycle.
55547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    ScopedAutoreleasePool pool;
55647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#endif
55747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    {
55847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      Message msg;
55947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      if (!Get(&msg, cmsNext))
56047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        return !IsQuitting();
56147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      Dispatch(&msg);
56247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
56347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      if (cmsLoop != kForever) {
56447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        cmsNext = TimeUntil(msEnd);
56547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org        if (cmsNext < 0)
56647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org          return true;
56747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org      }
56847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    }
56947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
57047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
57147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
572692b0633dd5ffbd0235a73a6f4f7cf864e78b285jiayl@webrtc.orgbool Thread::WrapCurrentWithThreadManager(ThreadManager* thread_manager,
573692b0633dd5ffbd0235a73a6f4f7cf864e78b285jiayl@webrtc.org                                          bool need_synchronize_access) {
5740631e37660e5e9b1566089c8306094ad6ee9516efischman@webrtc.org  if (running())
57547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    return false;
576692b0633dd5ffbd0235a73a6f4f7cf864e78b285jiayl@webrtc.org
57747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#if defined(WEBRTC_WIN)
578692b0633dd5ffbd0235a73a6f4f7cf864e78b285jiayl@webrtc.org  if (need_synchronize_access) {
579692b0633dd5ffbd0235a73a6f4f7cf864e78b285jiayl@webrtc.org    // We explicitly ask for no rights other than synchronization.
580692b0633dd5ffbd0235a73a6f4f7cf864e78b285jiayl@webrtc.org    // This gives us the best chance of succeeding.
581692b0633dd5ffbd0235a73a6f4f7cf864e78b285jiayl@webrtc.org    thread_ = OpenThread(SYNCHRONIZE, FALSE, GetCurrentThreadId());
582692b0633dd5ffbd0235a73a6f4f7cf864e78b285jiayl@webrtc.org    if (!thread_) {
583692b0633dd5ffbd0235a73a6f4f7cf864e78b285jiayl@webrtc.org      LOG_GLE(LS_ERROR) << "Unable to get handle to thread.";
584692b0633dd5ffbd0235a73a6f4f7cf864e78b285jiayl@webrtc.org      return false;
585692b0633dd5ffbd0235a73a6f4f7cf864e78b285jiayl@webrtc.org    }
586692b0633dd5ffbd0235a73a6f4f7cf864e78b285jiayl@webrtc.org    thread_id_ = GetCurrentThreadId();
58747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
58847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#elif defined(WEBRTC_POSIX)
58947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  thread_ = pthread_self();
59047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#endif
591692b0633dd5ffbd0235a73a6f4f7cf864e78b285jiayl@webrtc.org
59247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  owned_ = false;
5930631e37660e5e9b1566089c8306094ad6ee9516efischman@webrtc.org  running_.Set();
59447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  thread_manager->SetCurrentThread(this);
59547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  return true;
59647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
59747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
59847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgAutoThread::AutoThread(SocketServer* ss) : Thread(ss) {
59947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (!ThreadManager::Instance()->CurrentThread()) {
60047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    ThreadManager::Instance()->SetCurrentThread(this);
60147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
60247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
60347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
60447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgAutoThread::~AutoThread() {
60547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  Stop();
60647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (ThreadManager::Instance()->CurrentThread() == this) {
60747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    ThreadManager::Instance()->SetCurrentThread(NULL);
60847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
60947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
61047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
61147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#if defined(WEBRTC_WIN)
61247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgvoid ComThread::Run() {
61347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  HRESULT hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
61447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  ASSERT(SUCCEEDED(hr));
61547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  if (SUCCEEDED(hr)) {
61647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    Thread::Run();
61747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    CoUninitialize();
61847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  } else {
61947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org    LOG(LS_ERROR) << "CoInitialize failed, hr=" << hr;
62047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org  }
62147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}
62247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#endif
62347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org
62447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}  // namespace rtc
625