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