1f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch/* 2f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * libjingle 3f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * Copyright 2004--2005, Google Inc. 4f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * 5f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * Redistribution and use in source and binary forms, with or without 6f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * modification, are permitted provided that the following conditions are met: 7f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * 8f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * 1. Redistributions of source code must retain the above copyright notice, 9f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * this list of conditions and the following disclaimer. 10f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * 2. Redistributions in binary form must reproduce the above copyright notice, 11f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * this list of conditions and the following disclaimer in the documentation 12f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * and/or other materials provided with the distribution. 13f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * 3. The name of the author may not be used to endorse or promote products 14f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * derived from this software without specific prior written permission. 15f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * 16f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 17f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 18f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 19f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 20f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 21f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 22f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 23f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 24f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 25f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch */ 27f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "talk/base/thread.h" 293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#if defined(WIN32) 313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include <comdef.h> 323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#elif defined(POSIX) 33f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include <time.h> 34f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#endif 35f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 36f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include "talk/base/common.h" 37f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include "talk/base/logging.h" 383345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "talk/base/stringutils.h" 39f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include "talk/base/time.h" 40f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 413345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#ifdef OSX_USE_COCOA 42f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#ifndef OSX 43f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#error OSX_USE_COCOA is defined but not OSX 44f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#endif 45f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include "talk/base/maccocoathreadhelper.h" 46f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#include "talk/base/scoped_autorelease_pool.h" 47f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#endif 48f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 49f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochnamespace talk_base { 50f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 51f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochThreadManager g_thmgr; 52f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 53f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#ifdef POSIX 54f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochpthread_key_t ThreadManager::key_; 55f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 56f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochThreadManager::ThreadManager() { 57f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch pthread_key_create(&key_, NULL); 58f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch main_thread_ = WrapCurrentThread(); 59f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#if defined(OSX_USE_COCOA) 60f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch InitCocoaMultiThreading(); 61f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#endif 62f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 63f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 64f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochThreadManager::~ThreadManager() { 65f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#ifdef OSX_USE_COCOA 66f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // This is called during exit, at which point apparently no NSAutoreleasePools 67f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // are available; but we might still need them to do cleanup (or we get the 68f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // "no autoreleasepool in place, just leaking" warning when exiting). 69f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch ScopedAutoreleasePool pool; 70f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#endif 71f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch UnwrapCurrentThread(); 72f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // Unwrap deletes main_thread_ automatically. 73f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch pthread_key_delete(key_); 74f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 75f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 76f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochThread *ThreadManager::CurrentThread() { 773345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return static_cast<Thread *>(pthread_getspecific(key_)); 78f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 79f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 80f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid ThreadManager::SetCurrent(Thread *thread) { 81f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch pthread_setspecific(key_, thread); 82f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 83f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#endif 84f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 85f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#ifdef WIN32 86f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochDWORD ThreadManager::key_; 87f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 88f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochThreadManager::ThreadManager() { 89f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch key_ = TlsAlloc(); 90f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch main_thread_ = WrapCurrentThread(); 91f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 92f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 93f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochThreadManager::~ThreadManager() { 94f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch UnwrapCurrentThread(); 95f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch TlsFree(key_); 96f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 97f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 98f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochThread *ThreadManager::CurrentThread() { 993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return static_cast<Thread *>(TlsGetValue(key_)); 100f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 101f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 102f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid ThreadManager::SetCurrent(Thread *thread) { 103f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch TlsSetValue(key_, thread); 104f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 105f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#endif 106f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 107f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// static 108f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochThread *ThreadManager::WrapCurrentThread() { 109f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch Thread* result = CurrentThread(); 110f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (NULL == result) { 111f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch result = new Thread(); 112f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#if defined(WIN32) 113f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // We explicitly ask for no rights other than synchronization. 114f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // This gives us the best chance of succeeding. 115f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch result->thread_ = OpenThread(SYNCHRONIZE, FALSE, GetCurrentThreadId()); 116f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (!result->thread_) 117f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch LOG_GLE(LS_ERROR) << "Unable to get handle to thread."; 118f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#elif defined(POSIX) 119f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch result->thread_ = pthread_self(); 120f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#endif 121f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch result->owned_ = false; 122f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch result->started_ = true; 123f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch SetCurrent(result); 124f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 125f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 126f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return result; 127f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 128f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 129f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch// static 130f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid ThreadManager::UnwrapCurrentThread() { 131f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch Thread* t = CurrentThread(); 132f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (t && !(t->IsOwned())) { 133f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // Clears the platform-specific thread-specific storage. 134f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch SetCurrent(NULL); 135f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#ifdef WIN32 136f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (!CloseHandle(t->thread_)) { 137f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch LOG_GLE(LS_ERROR) << "When unwrapping thread, failed to close handle."; 138f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 139f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#endif 140f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch t->started_ = false; 141f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch delete t; 142f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 143f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 144f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 145f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid ThreadManager::Add(Thread *thread) { 146f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch CritScope cs(&crit_); 147f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch threads_.push_back(thread); 148f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 149f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 150f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid ThreadManager::Remove(Thread *thread) { 151f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch CritScope cs(&crit_); 1523345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick threads_.erase(std::remove(threads_.begin(), threads_.end(), thread), 1533345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick threads_.end()); 154f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 155f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 156f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid ThreadManager::StopAllThreads_() { 157f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // TODO: In order to properly implement, Threads need to be ref-counted. 158f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch CritScope cs(&g_thmgr.crit_); 1593345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick for (size_t i = 0; i < g_thmgr.threads_.size(); ++i) { 160f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch g_thmgr.threads_[i]->Stop(); 161f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 162f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 163f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 164f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochstruct ThreadInit { 165f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch Thread* thread; 166f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch Runnable* runnable; 167f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch}; 168f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 169f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochThread::Thread(SocketServer* ss) 170f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch : MessageQueue(ss), 171f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch priority_(PRIORITY_NORMAL), 172f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch started_(false), 173f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch has_sends_(false), 174f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#if defined(WIN32) 175f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch thread_(NULL), 176f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#endif 177f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch owned_(true) { 178f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch g_thmgr.Add(this); 1793345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick SetName("Thread", this); // default name 180f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 181f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 182f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochThread::~Thread() { 183f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch Stop(); 184f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (active_) 185f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch Clear(NULL); 186f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch g_thmgr.Remove(this); 187f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 188f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 189f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochbool Thread::SleepMs(int milliseconds) { 190f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#ifdef WIN32 191f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch ::Sleep(milliseconds); 192f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return true; 193f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#else 194f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // POSIX has both a usleep() and a nanosleep(), but the former is deprecated, 195f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // so we use nanosleep() even though it has greater precision than necessary. 196f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch struct timespec ts; 197f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch ts.tv_sec = milliseconds / 1000; 198f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch ts.tv_nsec = (milliseconds % 1000) * 1000000; 199f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch int ret = nanosleep(&ts, NULL); 200f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (ret != 0) { 201f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch LOG_ERR(LS_WARNING) << "nanosleep() returning early"; 202f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return false; 203f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 204f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return true; 205f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#endif 206f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 207f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 2083345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickbool Thread::SetName(const std::string& name, const void* obj) { 2093345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (started_) return false; 2103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick name_ = name; 2113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (obj) { 2123345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick char buf[16]; 2133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick sprintfn(buf, sizeof(buf), " 0x%p", obj); 2143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick name_ += buf; 2153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 2163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return true; 2173345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 2183345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 2193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickbool Thread::SetPriority(ThreadPriority priority) { 2203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (started_) return false; 2213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick priority_ = priority; 2223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return true; 2233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 2243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 225f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochbool Thread::Start(Runnable* runnable) { 2263345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick ASSERT(owned_); 227f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (!owned_) return false; 2283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick ASSERT(!started_); 229f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (started_) return false; 230f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 231f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch ThreadInit* init = new ThreadInit; 232f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch init->thread = this; 233f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch init->runnable = runnable; 234f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#if defined(WIN32) 235f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch DWORD flags = 0; 236f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (priority_ != PRIORITY_NORMAL) { 237f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch flags = CREATE_SUSPENDED; 238f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 239f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch thread_ = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)PreRun, init, flags, 240f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch NULL); 241f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (thread_) { 242f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (priority_ != PRIORITY_NORMAL) { 243f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (priority_ == PRIORITY_HIGH) { 244f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch ::SetThreadPriority(thread_, THREAD_PRIORITY_HIGHEST); 245f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } else if (priority_ == PRIORITY_ABOVE_NORMAL) { 246f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch ::SetThreadPriority(thread_, THREAD_PRIORITY_ABOVE_NORMAL); 247f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } else if (priority_ == PRIORITY_IDLE) { 248f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch ::SetThreadPriority(thread_, THREAD_PRIORITY_IDLE); 249f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 250f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch ::ResumeThread(thread_); 251f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 252f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } else { 253f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return false; 254f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 255f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#elif defined(POSIX) 256f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch pthread_attr_t attr; 257f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch pthread_attr_init(&attr); 258f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (priority_ != PRIORITY_NORMAL) { 259f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (priority_ == PRIORITY_IDLE) { 260f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // There is no POSIX-standard way to set a below-normal priority for an 261f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // individual thread (only whole process), so let's not support it. 262f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch LOG(LS_WARNING) << "PRIORITY_IDLE not supported"; 263f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } else { 264f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // Set real-time round-robin policy. 265f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (pthread_attr_setschedpolicy(&attr, SCHED_RR) != 0) { 266f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch LOG(LS_ERROR) << "pthread_attr_setschedpolicy"; 267f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 268f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch struct sched_param param; 269f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (pthread_attr_getschedparam(&attr, ¶m) != 0) { 270f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch LOG(LS_ERROR) << "pthread_attr_getschedparam"; 271f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } else { 272f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // The numbers here are arbitrary. 273f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (priority_ == PRIORITY_HIGH) { 274f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch param.sched_priority = 6; // 6 = HIGH 275f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } else { 276f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch ASSERT(priority_ == PRIORITY_ABOVE_NORMAL); 277f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch param.sched_priority = 4; // 4 = ABOVE_NORMAL 278f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 279f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (pthread_attr_setschedparam(&attr, ¶m) != 0) { 280f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch LOG(LS_ERROR) << "pthread_attr_setschedparam"; 281f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 282f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 283f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 284f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 285f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch int error_code = pthread_create(&thread_, &attr, PreRun, init); 286f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (0 != error_code) { 287f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch LOG(LS_ERROR) << "Unable to create pthread, error " << error_code; 288f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return false; 289f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 290f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#endif 291f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch started_ = true; 292f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return true; 293f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 294f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 295f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid Thread::Join() { 296f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (started_) { 297f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch ASSERT(!IsCurrent()); 298f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#if defined(WIN32) 299f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch WaitForSingleObject(thread_, INFINITE); 300f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch CloseHandle(thread_); 301f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch thread_ = NULL; 302f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#elif defined(POSIX) 303f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch void *pv; 304f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch pthread_join(thread_, &pv); 305f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#endif 306f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch started_ = false; 307f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 308f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 309f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 310f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#ifdef WIN32 3113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// As seen on MSDN. 3123345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// http://msdn.microsoft.com/en-us/library/xcb2z8hs(VS.71).aspx 3133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#define MSDEV_SET_THREAD_NAME 0x406D1388 3143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merricktypedef struct tagTHREADNAME_INFO { 315f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch DWORD dwType; 316f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch LPCSTR szName; 317f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch DWORD dwThreadID; 318f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch DWORD dwFlags; 319f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} THREADNAME_INFO; 320f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 3213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid SetThreadName(DWORD dwThreadID, LPCSTR szThreadName) { 322f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch THREADNAME_INFO info; 3233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick info.dwType = 0x1000; 3243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick info.szName = szThreadName; 3253345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick info.dwThreadID = dwThreadID; 3263345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick info.dwFlags = 0; 3273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 3283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick __try { 3293345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick RaiseException(MSDEV_SET_THREAD_NAME, 0, sizeof(info) / sizeof(DWORD), 3303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick reinterpret_cast<DWORD*>(&info)); 331f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 3323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick __except(EXCEPTION_CONTINUE_EXECUTION) { 333f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 334f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 3353345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#endif // WIN32 336f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 337f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid* Thread::PreRun(void* pv) { 338f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch ThreadInit* init = static_cast<ThreadInit*>(pv); 339f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch ThreadManager::SetCurrent(init->thread); 3403345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#if defined(WIN32) 3413345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick SetThreadName(GetCurrentThreadId(), init->thread->name_.c_str()); 3423345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#elif defined(POSIX) 343731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick // TODO: See if naming exists for pthreads. 344f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#endif 345f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#ifdef OSX_USE_COCOA 346f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // Make sure the new thread has an autoreleasepool 347f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch ScopedAutoreleasePool pool; 348f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch#endif 349f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (init->runnable) { 350f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch init->runnable->Run(init->thread); 351f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } else { 352f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch init->thread->Run(); 353f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 354f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch delete init; 355f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return NULL; 356f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 357f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 358f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid Thread::Run() { 359f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch ProcessMessages(kForever); 360f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 361f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 362f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochbool Thread::IsOwned() { 363f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return owned_; 364f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 365f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 366f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid Thread::Stop() { 367f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch MessageQueue::Quit(); 368f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch Join(); 369f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 370f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 371f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid Thread::Send(MessageHandler *phandler, uint32 id, MessageData *pdata) { 372f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (fStop_) 373f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return; 374f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 375f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // Sent messages are sent to the MessageHandler directly, in the context 376f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // of "thread", like Win32 SendMessage. If in the right context, 377f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // call the handler directly. 378f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 379f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch Message msg; 380f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch msg.phandler = phandler; 381f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch msg.message_id = id; 382f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch msg.pdata = pdata; 383f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (IsCurrent()) { 384f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch phandler->OnMessage(&msg); 385f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return; 386f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 387f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 388f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch AutoThread thread; 389f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch Thread *current_thread = Thread::Current(); 390f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch ASSERT(current_thread != NULL); // AutoThread ensures this 391f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 392f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch bool ready = false; 393f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch { 394f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch CritScope cs(&crit_); 395f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch EnsureActive(); 396f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch _SendMessage smsg; 397f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch smsg.thread = current_thread; 398f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch smsg.msg = msg; 399f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch smsg.ready = &ready; 400f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch sendlist_.push_back(smsg); 401f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch has_sends_ = true; 402f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 403f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 404f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // Wait for a reply 405f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 406f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch ss_->WakeUp(); 407f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 408f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch bool waited = false; 409f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch while (!ready) { 410f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch current_thread->ReceiveSends(); 411f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch current_thread->socketserver()->Wait(kForever, false); 412f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch waited = true; 413f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 414f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 415f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // Our Wait loop above may have consumed some WakeUp events for this 416f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // MessageQueue, that weren't relevant to this Send. Losing these WakeUps can 417f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // cause problems for some SocketServers. 418f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // 419f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // Concrete example: 420f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // Win32SocketServer on thread A calls Send on thread B. While processing the 421f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // message, thread B Posts a message to A. We consume the wakeup for that 422f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // Post while waiting for the Send to complete, which means that when we exit 423f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // this loop, we need to issue another WakeUp, or else the Posted message 424f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // won't be processed in a timely manner. 425f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 426f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (waited) { 427f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch current_thread->socketserver()->WakeUp(); 428f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 429f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 430f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 431f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid Thread::ReceiveSends() { 432f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // Before entering critical section, check boolean. 433f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 434f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (!has_sends_) 435f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return; 436f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 437f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // Receive a sent message. Cleanup scenarios: 438f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // - thread sending exits: We don't allow this, since thread can exit 439f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // only via Join, so Send must complete. 440f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // - thread receiving exits: Wakeup/set ready in Thread::Clear() 441f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // - object target cleared: Wakeup/set ready in Thread::Clear() 442f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch crit_.Enter(); 443f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch while (!sendlist_.empty()) { 444f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch _SendMessage smsg = sendlist_.front(); 445f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch sendlist_.pop_front(); 446f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch crit_.Leave(); 447f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch smsg.msg.phandler->OnMessage(&smsg.msg); 448f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch crit_.Enter(); 449f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch *smsg.ready = true; 450f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch smsg.thread->socketserver()->WakeUp(); 451f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 452f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch has_sends_ = false; 453f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch crit_.Leave(); 454f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 455f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 456f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochvoid Thread::Clear(MessageHandler *phandler, uint32 id, 457f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch MessageList* removed) { 458f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch CritScope cs(&crit_); 459f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 460f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // Remove messages on sendlist_ with phandler 461f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // Object target cleared: remove from send list, wakeup/set ready 462f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch // if sender not NULL. 463f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 464f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch std::list<_SendMessage>::iterator iter = sendlist_.begin(); 465f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch while (iter != sendlist_.end()) { 466f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch _SendMessage smsg = *iter; 467f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (smsg.msg.Match(phandler, id)) { 468f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (removed) { 469f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch removed->push_back(smsg.msg); 470f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } else { 471f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch delete smsg.msg.pdata; 472f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 473f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch iter = sendlist_.erase(iter); 474f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch *smsg.ready = true; 475f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch smsg.thread->socketserver()->WakeUp(); 476f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch continue; 477f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 478f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch ++iter; 479f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 480f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 481f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch MessageQueue::Clear(phandler, id, removed); 482f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 483f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 484f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdochbool Thread::ProcessMessages(int cmsLoop) { 485f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch uint32 msEnd = (kForever == cmsLoop) ? 0 : TimeAfter(cmsLoop); 486f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch int cmsNext = cmsLoop; 487f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 488f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch while (true) { 489f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch Message msg; 490f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (!Get(&msg, cmsNext)) 491f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return !IsQuitting(); 492f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch Dispatch(&msg); 493f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 494f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (cmsLoop != kForever) { 495f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch cmsNext = TimeUntil(msEnd); 496f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (cmsNext < 0) 497f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch return true; 498f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 499f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 500f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 501f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 502f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochAutoThread::AutoThread(SocketServer* ss) : Thread(ss) { 503f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (!ThreadManager::CurrentThread()) { 504f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch ThreadManager::SetCurrent(this); 505f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 506f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 507f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 508f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen MurdochAutoThread::~AutoThread() { 509f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch if (ThreadManager::CurrentThread() == this) { 510f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch ThreadManager::SetCurrent(NULL); 511f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch } 512f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch} 513f74420b3285b9fe04a7e00aa3b8c0ab07ea344bcBen Murdoch 5143345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#ifdef WIN32 5153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickvoid ComThread::Run() { 5163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick HRESULT hr = CoInitializeEx(NULL, COINIT_MULTITHREADED); 5173345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick ASSERT(SUCCEEDED(hr)); 5183345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (SUCCEEDED(hr)) { 5193345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick Thread::Run(); 5203345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick CoUninitialize(); 5213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } else { 5223345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick LOG(LS_ERROR) << "CoInitialize failed, hr=" << hr; 5233345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 5243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 5253345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#endif 5263345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 5273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} // namespace talk_base 528