1 /* 2 * Copyright 2004 The WebRTC Project Authors. All rights reserved. 3 * 4 * Use of this source code is governed by a BSD-style license 5 * that can be found in the LICENSE file in the root of the source 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11 #ifndef WEBRTC_BASE_THREAD_H_ 12 #define WEBRTC_BASE_THREAD_H_ 13 14 #include <algorithm> 15 #include <list> 16 #include <string> 17 #include <vector> 18 19 #if defined(WEBRTC_POSIX) 20 #include <pthread.h> 21 #endif 22 #include "webrtc/base/constructormagic.h" 23 #include "webrtc/base/event.h" 24 #include "webrtc/base/messagequeue.h" 25 26 #if defined(WEBRTC_WIN) 27 #include "webrtc/base/win32.h" 28 #endif 29 30 namespace rtc { 31 32 class Thread; 33 34 class ThreadManager { 35 public: 36 ThreadManager(); 37 ~ThreadManager(); 38 39 static ThreadManager* Instance(); 40 41 Thread* CurrentThread(); 42 void SetCurrentThread(Thread* thread); 43 44 // Returns a thread object with its thread_ ivar set 45 // to whatever the OS uses to represent the thread. 46 // If there already *is* a Thread object corresponding to this thread, 47 // this method will return that. Otherwise it creates a new Thread 48 // object whose wrapped() method will return true, and whose 49 // handle will, on Win32, be opened with only synchronization privileges - 50 // if you need more privilegs, rather than changing this method, please 51 // write additional code to adjust the privileges, or call a different 52 // factory method of your own devising, because this one gets used in 53 // unexpected contexts (like inside browser plugins) and it would be a 54 // shame to break it. It is also conceivable on Win32 that we won't even 55 // be able to get synchronization privileges, in which case the result 56 // will have a NULL handle. 57 Thread *WrapCurrentThread(); 58 void UnwrapCurrentThread(); 59 60 private: 61 #if defined(WEBRTC_POSIX) 62 pthread_key_t key_; 63 #endif 64 65 #if defined(WEBRTC_WIN) 66 DWORD key_; 67 #endif 68 69 DISALLOW_COPY_AND_ASSIGN(ThreadManager); 70 }; 71 72 struct _SendMessage { 73 _SendMessage() {} 74 Thread *thread; 75 Message msg; 76 bool *ready; 77 }; 78 79 enum ThreadPriority { 80 PRIORITY_IDLE = -1, 81 PRIORITY_NORMAL = 0, 82 PRIORITY_ABOVE_NORMAL = 1, 83 PRIORITY_HIGH = 2, 84 }; 85 86 class Runnable { 87 public: 88 virtual ~Runnable() {} 89 virtual void Run(Thread* thread) = 0; 90 91 protected: 92 Runnable() {} 93 94 private: 95 DISALLOW_COPY_AND_ASSIGN(Runnable); 96 }; 97 98 // WARNING! SUBCLASSES MUST CALL Stop() IN THEIR DESTRUCTORS! See ~Thread(). 99 100 class Thread : public MessageQueue { 101 public: 102 explicit Thread(SocketServer* ss = NULL); 103 // NOTE: ALL SUBCLASSES OF Thread MUST CALL Stop() IN THEIR DESTRUCTORS (or 104 // guarantee Stop() is explicitly called before the subclass is destroyed). 105 // This is required to avoid a data race between the destructor modifying the 106 // vtable, and the Thread::PreRun calling the virtual method Run(). 107 virtual ~Thread(); 108 109 static Thread* Current(); 110 111 bool IsCurrent() const { 112 return Current() == this; 113 } 114 115 // Sleeps the calling thread for the specified number of milliseconds, during 116 // which time no processing is performed. Returns false if sleeping was 117 // interrupted by a signal (POSIX only). 118 static bool SleepMs(int millis); 119 120 // Sets the thread's name, for debugging. Must be called before Start(). 121 // If |obj| is non-NULL, its value is appended to |name|. 122 const std::string& name() const { return name_; } 123 bool SetName(const std::string& name, const void* obj); 124 125 // Sets the thread's priority. Must be called before Start(). 126 ThreadPriority priority() const { return priority_; } 127 bool SetPriority(ThreadPriority priority); 128 129 // Starts the execution of the thread. 130 bool Start(Runnable* runnable = NULL); 131 132 // Tells the thread to stop and waits until it is joined. 133 // Never call Stop on the current thread. Instead use the inherited Quit 134 // function which will exit the base MessageQueue without terminating the 135 // underlying OS thread. 136 virtual void Stop(); 137 138 // By default, Thread::Run() calls ProcessMessages(kForever). To do other 139 // work, override Run(). To receive and dispatch messages, call 140 // ProcessMessages occasionally. 141 virtual void Run(); 142 143 virtual void Send(MessageHandler *phandler, uint32 id = 0, 144 MessageData *pdata = NULL); 145 146 // Convenience method to invoke a functor on another thread. Caller must 147 // provide the |ReturnT| template argument, which cannot (easily) be deduced. 148 // Uses Send() internally, which blocks the current thread until execution 149 // is complete. 150 // Ex: bool result = thread.Invoke<bool>(&MyFunctionReturningBool); 151 template <class ReturnT, class FunctorT> 152 ReturnT Invoke(const FunctorT& functor) { 153 FunctorMessageHandler<ReturnT, FunctorT> handler(functor); 154 Send(&handler); 155 return handler.result(); 156 } 157 158 // From MessageQueue 159 virtual void Clear(MessageHandler *phandler, uint32 id = MQID_ANY, 160 MessageList* removed = NULL); 161 virtual void ReceiveSends(); 162 163 // ProcessMessages will process I/O and dispatch messages until: 164 // 1) cms milliseconds have elapsed (returns true) 165 // 2) Stop() is called (returns false) 166 bool ProcessMessages(int cms); 167 168 // Returns true if this is a thread that we created using the standard 169 // constructor, false if it was created by a call to 170 // ThreadManager::WrapCurrentThread(). The main thread of an application 171 // is generally not owned, since the OS representation of the thread 172 // obviously exists before we can get to it. 173 // You cannot call Start on non-owned threads. 174 bool IsOwned(); 175 176 #if defined(WEBRTC_WIN) 177 HANDLE GetHandle() const { 178 return thread_; 179 } 180 DWORD GetId() const { 181 return thread_id_; 182 } 183 #elif defined(WEBRTC_POSIX) 184 pthread_t GetPThread() { 185 return thread_; 186 } 187 #endif 188 189 // This method should be called when thread is created using non standard 190 // method, like derived implementation of rtc::Thread and it can not be 191 // started by calling Start(). This will set started flag to true and 192 // owned to false. This must be called from the current thread. 193 // NOTE: These methods should be used by the derived classes only, added here 194 // only for testing. 195 bool WrapCurrent(); 196 void UnwrapCurrent(); 197 198 // Expose private method running() for tests. 199 // 200 // DANGER: this is a terrible public API. Most callers that might want to 201 // call this likely do not have enough control/knowledge of the Thread in 202 // question to guarantee that the returned value remains true for the duration 203 // of whatever code is conditionally executing because of the return value! 204 bool RunningForTest() { return running(); } 205 // This is a legacy call-site that probably doesn't need to exist in the first 206 // place. 207 // TODO(fischman): delete once the ASSERT added in channelmanager.cc sticks 208 // for a month (ETA 2014/06/22). 209 bool RunningForChannelManager() { return running(); } 210 211 protected: 212 // Blocks the calling thread until this thread has terminated. 213 void Join(); 214 215 private: 216 static void *PreRun(void *pv); 217 218 // ThreadManager calls this instead WrapCurrent() because 219 // ThreadManager::Instance() cannot be used while ThreadManager is 220 // being created. 221 bool WrapCurrentWithThreadManager(ThreadManager* thread_manager); 222 223 // Return true if the thread was started and hasn't yet stopped. 224 bool running() { return running_.Wait(0); } 225 226 std::list<_SendMessage> sendlist_; 227 std::string name_; 228 ThreadPriority priority_; 229 Event running_; // Signalled means running. 230 231 #if defined(WEBRTC_POSIX) 232 pthread_t thread_; 233 #endif 234 235 #if defined(WEBRTC_WIN) 236 HANDLE thread_; 237 DWORD thread_id_; 238 #endif 239 240 bool owned_; 241 242 friend class ThreadManager; 243 244 DISALLOW_COPY_AND_ASSIGN(Thread); 245 }; 246 247 // AutoThread automatically installs itself at construction 248 // uninstalls at destruction, if a Thread object is 249 // _not already_ associated with the current OS thread. 250 251 class AutoThread : public Thread { 252 public: 253 explicit AutoThread(SocketServer* ss = 0); 254 virtual ~AutoThread(); 255 256 private: 257 DISALLOW_COPY_AND_ASSIGN(AutoThread); 258 }; 259 260 // Win32 extension for threads that need to use COM 261 #if defined(WEBRTC_WIN) 262 class ComThread : public Thread { 263 public: 264 ComThread() {} 265 virtual ~ComThread() { Stop(); } 266 267 protected: 268 virtual void Run(); 269 270 private: 271 DISALLOW_COPY_AND_ASSIGN(ComThread); 272 }; 273 #endif 274 275 // Provides an easy way to install/uninstall a socketserver on a thread. 276 class SocketServerScope { 277 public: 278 explicit SocketServerScope(SocketServer* ss) { 279 old_ss_ = Thread::Current()->socketserver(); 280 Thread::Current()->set_socketserver(ss); 281 } 282 ~SocketServerScope() { 283 Thread::Current()->set_socketserver(old_ss_); 284 } 285 286 private: 287 SocketServer* old_ss_; 288 289 DISALLOW_IMPLICIT_CONSTRUCTORS(SocketServerScope); 290 }; 291 292 } // namespace rtc 293 294 #endif // WEBRTC_BASE_THREAD_H_ 295