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, ¶m) != 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, ¶m) != 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