Home | History | Annotate | Download | only in base
      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