| henrike@webrtc.org | f048872 | 2014-05-13 18:00:26 +0000 | [diff] [blame] | 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 |  | 
| Mirko Bonadei | 92ea95e | 2017-09-15 06:47:31 +0200 | [diff] [blame] | 11 | #ifndef RTC_BASE_THREAD_H_ | 
 | 12 | #define RTC_BASE_THREAD_H_ | 
| henrike@webrtc.org | f048872 | 2014-05-13 18:00:26 +0000 | [diff] [blame] | 13 |  | 
| Henrik Kjellander | ec78f1c | 2017-06-29 07:52:50 +0200 | [diff] [blame] | 14 | #include <algorithm> | 
 | 15 | #include <list> | 
 | 16 | #include <memory> | 
 | 17 | #include <string> | 
| Karl Wiberg | d6b4819 | 2017-10-16 23:01:06 +0200 | [diff] [blame] | 18 | #include <utility> | 
| Henrik Kjellander | ec78f1c | 2017-06-29 07:52:50 +0200 | [diff] [blame] | 19 | #include <vector> | 
| henrike@webrtc.org | f048872 | 2014-05-13 18:00:26 +0000 | [diff] [blame] | 20 |  | 
| Henrik Kjellander | ec78f1c | 2017-06-29 07:52:50 +0200 | [diff] [blame] | 21 | #if defined(WEBRTC_POSIX) | 
 | 22 | #include <pthread.h> | 
 | 23 | #endif | 
| Mirko Bonadei | 92ea95e | 2017-09-15 06:47:31 +0200 | [diff] [blame] | 24 | #include "rtc_base/constructormagic.h" | 
| Mirko Bonadei | 92ea95e | 2017-09-15 06:47:31 +0200 | [diff] [blame] | 25 | #include "rtc_base/messagequeue.h" | 
 | 26 | #include "rtc_base/platform_thread_types.h" | 
| Henrik Kjellander | ec78f1c | 2017-06-29 07:52:50 +0200 | [diff] [blame] | 27 |  | 
 | 28 | #if defined(WEBRTC_WIN) | 
| Mirko Bonadei | 92ea95e | 2017-09-15 06:47:31 +0200 | [diff] [blame] | 29 | #include "rtc_base/win32.h" | 
| Henrik Kjellander | ec78f1c | 2017-06-29 07:52:50 +0200 | [diff] [blame] | 30 | #endif | 
 | 31 |  | 
 | 32 | namespace rtc { | 
 | 33 |  | 
 | 34 | class Thread; | 
 | 35 |  | 
 | 36 | class ThreadManager { | 
 | 37 |  public: | 
 | 38 |   static const int kForever = -1; | 
 | 39 |  | 
 | 40 |   // Singleton, constructor and destructor are private. | 
 | 41 |   static ThreadManager* Instance(); | 
 | 42 |  | 
 | 43 |   Thread* CurrentThread(); | 
 | 44 |   void SetCurrentThread(Thread* thread); | 
 | 45 |  | 
 | 46 |   // Returns a thread object with its thread_ ivar set | 
 | 47 |   // to whatever the OS uses to represent the thread. | 
 | 48 |   // If there already *is* a Thread object corresponding to this thread, | 
 | 49 |   // this method will return that.  Otherwise it creates a new Thread | 
 | 50 |   // object whose wrapped() method will return true, and whose | 
 | 51 |   // handle will, on Win32, be opened with only synchronization privileges - | 
 | 52 |   // if you need more privilegs, rather than changing this method, please | 
 | 53 |   // write additional code to adjust the privileges, or call a different | 
 | 54 |   // factory method of your own devising, because this one gets used in | 
 | 55 |   // unexpected contexts (like inside browser plugins) and it would be a | 
 | 56 |   // shame to break it.  It is also conceivable on Win32 that we won't even | 
 | 57 |   // be able to get synchronization privileges, in which case the result | 
 | 58 |   // will have a null handle. | 
 | 59 |   Thread *WrapCurrentThread(); | 
 | 60 |   void UnwrapCurrentThread(); | 
 | 61 |  | 
 | 62 |   bool IsMainThread(); | 
 | 63 |  | 
 | 64 |  private: | 
 | 65 |   ThreadManager(); | 
 | 66 |   ~ThreadManager(); | 
 | 67 |  | 
 | 68 | #if defined(WEBRTC_POSIX) | 
 | 69 |   pthread_key_t key_; | 
 | 70 | #endif | 
 | 71 |  | 
 | 72 | #if defined(WEBRTC_WIN) | 
| Tommi | 5149242 | 2017-12-04 15:18:23 +0100 | [diff] [blame] | 73 |   const DWORD key_; | 
| Henrik Kjellander | ec78f1c | 2017-06-29 07:52:50 +0200 | [diff] [blame] | 74 | #endif | 
 | 75 |  | 
 | 76 |   // The thread to potentially autowrap. | 
| Tommi | 5149242 | 2017-12-04 15:18:23 +0100 | [diff] [blame] | 77 |   const PlatformThreadRef main_thread_ref_; | 
| Henrik Kjellander | ec78f1c | 2017-06-29 07:52:50 +0200 | [diff] [blame] | 78 |  | 
 | 79 |   RTC_DISALLOW_COPY_AND_ASSIGN(ThreadManager); | 
 | 80 | }; | 
 | 81 |  | 
 | 82 | struct _SendMessage { | 
 | 83 |   _SendMessage() {} | 
 | 84 |   Thread *thread; | 
 | 85 |   Message msg; | 
 | 86 |   bool *ready; | 
 | 87 | }; | 
 | 88 |  | 
 | 89 | class Runnable { | 
 | 90 |  public: | 
 | 91 |   virtual ~Runnable() {} | 
 | 92 |   virtual void Run(Thread* thread) = 0; | 
 | 93 |  | 
 | 94 |  protected: | 
 | 95 |   Runnable() {} | 
 | 96 |  | 
 | 97 |  private: | 
 | 98 |   RTC_DISALLOW_COPY_AND_ASSIGN(Runnable); | 
 | 99 | }; | 
 | 100 |  | 
 | 101 | // WARNING! SUBCLASSES MUST CALL Stop() IN THEIR DESTRUCTORS!  See ~Thread(). | 
 | 102 |  | 
| danilchap | 3c6abd2 | 2017-09-06 05:46:29 -0700 | [diff] [blame] | 103 | class RTC_LOCKABLE Thread : public MessageQueue { | 
| tommi | a8a3515 | 2017-07-13 05:47:25 -0700 | [diff] [blame] | 104 |  public: | 
| tommi | e725159 | 2017-07-14 14:44:46 -0700 | [diff] [blame] | 105 |   // DEPRECATED. | 
 | 106 |   // The default constructor should not be used because it hides whether or | 
 | 107 |   // not a socket server will be associated with the thread. Most instances | 
 | 108 |   // of Thread do actually not need one, so please use either of the Create* | 
 | 109 |   // methods to construct an instance of Thread. | 
| charujain | a117b04 | 2017-07-13 07:06:39 -0700 | [diff] [blame] | 110 |   Thread(); | 
| tommi | e725159 | 2017-07-14 14:44:46 -0700 | [diff] [blame] | 111 |  | 
| Henrik Kjellander | ec78f1c | 2017-06-29 07:52:50 +0200 | [diff] [blame] | 112 |   explicit Thread(SocketServer* ss); | 
 | 113 |   explicit Thread(std::unique_ptr<SocketServer> ss); | 
 | 114 |  | 
 | 115 |   // NOTE: ALL SUBCLASSES OF Thread MUST CALL Stop() IN THEIR DESTRUCTORS (or | 
 | 116 |   // guarantee Stop() is explicitly called before the subclass is destroyed). | 
 | 117 |   // This is required to avoid a data race between the destructor modifying the | 
 | 118 |   // vtable, and the Thread::PreRun calling the virtual method Run(). | 
 | 119 |   ~Thread() override; | 
 | 120 |  | 
 | 121 |   static std::unique_ptr<Thread> CreateWithSocketServer(); | 
 | 122 |   static std::unique_ptr<Thread> Create(); | 
 | 123 |   static Thread* Current(); | 
 | 124 |  | 
 | 125 |   // Used to catch performance regressions. Use this to disallow blocking calls | 
 | 126 |   // (Invoke) for a given scope.  If a synchronous call is made while this is in | 
 | 127 |   // effect, an assert will be triggered. | 
 | 128 |   // Note that this is a single threaded class. | 
 | 129 |   class ScopedDisallowBlockingCalls { | 
 | 130 |    public: | 
 | 131 |     ScopedDisallowBlockingCalls(); | 
 | 132 |     ~ScopedDisallowBlockingCalls(); | 
 | 133 |    private: | 
 | 134 |     Thread* const thread_; | 
 | 135 |     const bool previous_state_; | 
 | 136 |   }; | 
 | 137 |  | 
 | 138 |   bool IsCurrent() const; | 
 | 139 |  | 
 | 140 |   // Sleeps the calling thread for the specified number of milliseconds, during | 
 | 141 |   // which time no processing is performed. Returns false if sleeping was | 
 | 142 |   // interrupted by a signal (POSIX only). | 
 | 143 |   static bool SleepMs(int millis); | 
 | 144 |  | 
 | 145 |   // Sets the thread's name, for debugging. Must be called before Start(). | 
 | 146 |   // If |obj| is non-null, its value is appended to |name|. | 
 | 147 |   const std::string& name() const { return name_; } | 
 | 148 |   bool SetName(const std::string& name, const void* obj); | 
 | 149 |  | 
 | 150 |   // Starts the execution of the thread. | 
 | 151 |   bool Start(Runnable* runnable = nullptr); | 
 | 152 |  | 
 | 153 |   // Tells the thread to stop and waits until it is joined. | 
 | 154 |   // Never call Stop on the current thread.  Instead use the inherited Quit | 
 | 155 |   // function which will exit the base MessageQueue without terminating the | 
 | 156 |   // underlying OS thread. | 
 | 157 |   virtual void Stop(); | 
 | 158 |  | 
 | 159 |   // By default, Thread::Run() calls ProcessMessages(kForever).  To do other | 
 | 160 |   // work, override Run().  To receive and dispatch messages, call | 
 | 161 |   // ProcessMessages occasionally. | 
 | 162 |   virtual void Run(); | 
 | 163 |  | 
 | 164 |   virtual void Send(const Location& posted_from, | 
 | 165 |                     MessageHandler* phandler, | 
 | 166 |                     uint32_t id = 0, | 
 | 167 |                     MessageData* pdata = nullptr); | 
 | 168 |  | 
 | 169 |   // Convenience method to invoke a functor on another thread.  Caller must | 
 | 170 |   // provide the |ReturnT| template argument, which cannot (easily) be deduced. | 
 | 171 |   // Uses Send() internally, which blocks the current thread until execution | 
 | 172 |   // is complete. | 
 | 173 |   // Ex: bool result = thread.Invoke<bool>(RTC_FROM_HERE, | 
 | 174 |   // &MyFunctionReturningBool); | 
 | 175 |   // NOTE: This function can only be called when synchronous calls are allowed. | 
 | 176 |   // See ScopedDisallowBlockingCalls for details. | 
 | 177 |   template <class ReturnT, class FunctorT> | 
| Karl Wiberg | d6b4819 | 2017-10-16 23:01:06 +0200 | [diff] [blame] | 178 |   ReturnT Invoke(const Location& posted_from, FunctorT&& functor) { | 
 | 179 |     FunctorMessageHandler<ReturnT, FunctorT> handler( | 
 | 180 |         std::forward<FunctorT>(functor)); | 
| Henrik Kjellander | ec78f1c | 2017-06-29 07:52:50 +0200 | [diff] [blame] | 181 |     InvokeInternal(posted_from, &handler); | 
 | 182 |     return handler.MoveResult(); | 
 | 183 |   } | 
 | 184 |  | 
 | 185 |   // From MessageQueue | 
 | 186 |   void Clear(MessageHandler* phandler, | 
 | 187 |              uint32_t id = MQID_ANY, | 
 | 188 |              MessageList* removed = nullptr) override; | 
 | 189 |   void ReceiveSends() override; | 
 | 190 |  | 
 | 191 |   // ProcessMessages will process I/O and dispatch messages until: | 
 | 192 |   //  1) cms milliseconds have elapsed (returns true) | 
 | 193 |   //  2) Stop() is called (returns false) | 
 | 194 |   bool ProcessMessages(int cms); | 
 | 195 |  | 
 | 196 |   // Returns true if this is a thread that we created using the standard | 
 | 197 |   // constructor, false if it was created by a call to | 
 | 198 |   // ThreadManager::WrapCurrentThread().  The main thread of an application | 
 | 199 |   // is generally not owned, since the OS representation of the thread | 
 | 200 |   // obviously exists before we can get to it. | 
 | 201 |   // You cannot call Start on non-owned threads. | 
 | 202 |   bool IsOwned(); | 
 | 203 |  | 
| Tommi | 5149242 | 2017-12-04 15:18:23 +0100 | [diff] [blame] | 204 |   // Expose private method IsRunning() for tests. | 
| Henrik Kjellander | ec78f1c | 2017-06-29 07:52:50 +0200 | [diff] [blame] | 205 |   // | 
 | 206 |   // DANGER: this is a terrible public API.  Most callers that might want to | 
 | 207 |   // call this likely do not have enough control/knowledge of the Thread in | 
 | 208 |   // question to guarantee that the returned value remains true for the duration | 
 | 209 |   // of whatever code is conditionally executing because of the return value! | 
| Tommi | 5149242 | 2017-12-04 15:18:23 +0100 | [diff] [blame] | 210 |   bool RunningForTest() { return IsRunning(); } | 
| Henrik Kjellander | ec78f1c | 2017-06-29 07:52:50 +0200 | [diff] [blame] | 211 |  | 
 | 212 |   // Sets the per-thread allow-blocking-calls flag and returns the previous | 
 | 213 |   // value. Must be called on this thread. | 
 | 214 |   bool SetAllowBlockingCalls(bool allow); | 
 | 215 |  | 
 | 216 |   // These functions are public to avoid injecting test hooks. Don't call them | 
 | 217 |   // outside of tests. | 
 | 218 |   // This method should be called when thread is created using non standard | 
 | 219 |   // method, like derived implementation of rtc::Thread and it can not be | 
 | 220 |   // started by calling Start(). This will set started flag to true and | 
 | 221 |   // owned to false. This must be called from the current thread. | 
 | 222 |   bool WrapCurrent(); | 
 | 223 |   void UnwrapCurrent(); | 
 | 224 |  | 
 | 225 |  protected: | 
 | 226 |   // Same as WrapCurrent except that it never fails as it does not try to | 
 | 227 |   // acquire the synchronization access of the thread. The caller should never | 
 | 228 |   // call Stop() or Join() on this thread. | 
 | 229 |   void SafeWrapCurrent(); | 
 | 230 |  | 
 | 231 |   // Blocks the calling thread until this thread has terminated. | 
 | 232 |   void Join(); | 
 | 233 |  | 
 | 234 |   static void AssertBlockingIsAllowedOnCurrentThread(); | 
 | 235 |  | 
 | 236 |   friend class ScopedDisallowBlockingCalls; | 
 | 237 |  | 
 | 238 |  private: | 
 | 239 |   struct ThreadInit { | 
 | 240 |     Thread* thread; | 
 | 241 |     Runnable* runnable; | 
 | 242 |   }; | 
 | 243 |  | 
 | 244 | #if defined(WEBRTC_WIN) | 
 | 245 |   static DWORD WINAPI PreRun(LPVOID context); | 
 | 246 | #else | 
 | 247 |   static void *PreRun(void *pv); | 
 | 248 | #endif | 
 | 249 |  | 
 | 250 |   // ThreadManager calls this instead WrapCurrent() because | 
 | 251 |   // ThreadManager::Instance() cannot be used while ThreadManager is | 
 | 252 |   // being created. | 
 | 253 |   // The method tries to get synchronization rights of the thread on Windows if | 
 | 254 |   // |need_synchronize_access| is true. | 
 | 255 |   bool WrapCurrentWithThreadManager(ThreadManager* thread_manager, | 
 | 256 |                                     bool need_synchronize_access); | 
 | 257 |  | 
| Tommi | 5149242 | 2017-12-04 15:18:23 +0100 | [diff] [blame] | 258 |   // Return true if the thread is currently running. | 
 | 259 |   bool IsRunning(); | 
| Henrik Kjellander | ec78f1c | 2017-06-29 07:52:50 +0200 | [diff] [blame] | 260 |  | 
 | 261 |   // Processes received "Send" requests. If |source| is not null, only requests | 
 | 262 |   // from |source| are processed, otherwise, all requests are processed. | 
 | 263 |   void ReceiveSendsFromThread(const Thread* source); | 
 | 264 |  | 
 | 265 |   // If |source| is not null, pops the first "Send" message from |source| in | 
 | 266 |   // |sendlist_|, otherwise, pops the first "Send" message of |sendlist_|. | 
 | 267 |   // The caller must lock |crit_| before calling. | 
 | 268 |   // Returns true if there is such a message. | 
 | 269 |   bool PopSendMessageFromThread(const Thread* source, _SendMessage* msg); | 
 | 270 |  | 
 | 271 |   void InvokeInternal(const Location& posted_from, MessageHandler* handler); | 
 | 272 |  | 
 | 273 |   std::list<_SendMessage> sendlist_; | 
 | 274 |   std::string name_; | 
| Tommi | 5149242 | 2017-12-04 15:18:23 +0100 | [diff] [blame] | 275 |  | 
| Tommi | 6cea2b0 | 2017-12-04 18:51:16 +0100 | [diff] [blame] | 276 |   // TODO(tommi): Add thread checks for proper use of control methods. | 
 | 277 |   // Ideally we should be able to just use PlatformThread. | 
| Henrik Kjellander | ec78f1c | 2017-06-29 07:52:50 +0200 | [diff] [blame] | 278 |  | 
 | 279 | #if defined(WEBRTC_POSIX) | 
| Tommi | 6cea2b0 | 2017-12-04 18:51:16 +0100 | [diff] [blame] | 280 |   pthread_t thread_ = 0; | 
| Henrik Kjellander | ec78f1c | 2017-06-29 07:52:50 +0200 | [diff] [blame] | 281 | #endif | 
 | 282 |  | 
 | 283 | #if defined(WEBRTC_WIN) | 
| Tommi | 6cea2b0 | 2017-12-04 18:51:16 +0100 | [diff] [blame] | 284 |   HANDLE thread_ = nullptr; | 
 | 285 |   DWORD thread_id_ = 0; | 
| Henrik Kjellander | ec78f1c | 2017-06-29 07:52:50 +0200 | [diff] [blame] | 286 | #endif | 
 | 287 |  | 
| Tommi | 5149242 | 2017-12-04 15:18:23 +0100 | [diff] [blame] | 288 |   // Indicates whether or not ownership of the worker thread lies with | 
 | 289 |   // this instance or not. (i.e. owned_ == !wrapped). | 
 | 290 |   // Must only be modified when the worker thread is not running. | 
 | 291 |   bool owned_ = true; | 
 | 292 |  | 
 | 293 |   // Only touched from the worker thread itself. | 
 | 294 |   bool blocking_calls_allowed_ = true; | 
| Henrik Kjellander | ec78f1c | 2017-06-29 07:52:50 +0200 | [diff] [blame] | 295 |  | 
 | 296 |   friend class ThreadManager; | 
 | 297 |  | 
 | 298 |   RTC_DISALLOW_COPY_AND_ASSIGN(Thread); | 
 | 299 | }; | 
 | 300 |  | 
 | 301 | // AutoThread automatically installs itself at construction | 
 | 302 | // uninstalls at destruction, if a Thread object is | 
 | 303 | // _not already_ associated with the current OS thread. | 
 | 304 |  | 
 | 305 | class AutoThread : public Thread { | 
 | 306 |  public: | 
 | 307 |   AutoThread(); | 
 | 308 |   ~AutoThread() override; | 
 | 309 |  | 
 | 310 |  private: | 
 | 311 |   RTC_DISALLOW_COPY_AND_ASSIGN(AutoThread); | 
 | 312 | }; | 
 | 313 |  | 
 | 314 | // AutoSocketServerThread automatically installs itself at | 
 | 315 | // construction and uninstalls at destruction. If a Thread object is | 
 | 316 | // already associated with the current OS thread, it is temporarily | 
 | 317 | // disassociated and restored by the destructor. | 
 | 318 |  | 
 | 319 | class AutoSocketServerThread : public Thread { | 
 | 320 |  public: | 
 | 321 |   explicit AutoSocketServerThread(SocketServer* ss); | 
 | 322 |   ~AutoSocketServerThread() override; | 
 | 323 |  | 
 | 324 |  private: | 
 | 325 |   rtc::Thread* old_thread_; | 
 | 326 |  | 
 | 327 |   RTC_DISALLOW_COPY_AND_ASSIGN(AutoSocketServerThread); | 
 | 328 | }; | 
 | 329 |  | 
 | 330 | }  // namespace rtc | 
| henrike@webrtc.org | f048872 | 2014-05-13 18:00:26 +0000 | [diff] [blame] | 331 |  | 
| Mirko Bonadei | 92ea95e | 2017-09-15 06:47:31 +0200 | [diff] [blame] | 332 | #endif  // RTC_BASE_THREAD_H_ |