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 RTC_BASE_DEPRECATED_SIGNAL_THREAD_H_ 12 #define RTC_BASE_DEPRECATED_SIGNAL_THREAD_H_ 13 14 #include <string> 15 16 #include "rtc_base/checks.h" 17 #include "rtc_base/constructor_magic.h" 18 #include "rtc_base/deprecated/recursive_critical_section.h" 19 #include "rtc_base/deprecation.h" 20 #include "rtc_base/message_handler.h" 21 #include "rtc_base/third_party/sigslot/sigslot.h" 22 #include "rtc_base/thread.h" 23 #include "rtc_base/thread_annotations.h" 24 25 namespace rtc { 26 27 /////////////////////////////////////////////////////////////////////////////// 28 // NOTE: this class has been deprecated. Do not use for new code. New code 29 // should use factilities exposed by api/task_queue/ instead. 30 // 31 // SignalThread - Base class for worker threads. The main thread should call 32 // Start() to begin work, and then follow one of these models: 33 // Normal: Wait for SignalWorkDone, and then call Release to destroy. 34 // Cancellation: Call Release(true), to abort the worker thread. 35 // Fire-and-forget: Call Release(false), which allows the thread to run to 36 // completion, and then self-destruct without further notification. 37 // Periodic tasks: Wait for SignalWorkDone, then eventually call Start() 38 // again to repeat the task. When the instance isn't needed anymore, 39 // call Release. DoWork, OnWorkStart and OnWorkStop are called again, 40 // on a new thread. 41 // The subclass should override DoWork() to perform the background task. By 42 // periodically calling ContinueWork(), it can check for cancellation. 43 // OnWorkStart and OnWorkDone can be overridden to do pre- or post-work 44 // tasks in the context of the main thread. 45 /////////////////////////////////////////////////////////////////////////////// 46 47 class DEPRECATED_SignalThread : public sigslot::has_slots<>, 48 protected MessageHandler { 49 public: 50 DEPRECATED_SignalThread(); 51 52 // Context: Main Thread. Call before Start to change the worker's name. 53 bool SetName(const std::string& name, const void* obj); 54 55 // Context: Main Thread. Call to begin the worker thread. 56 void Start(); 57 58 // Context: Main Thread. If the worker thread is not running, deletes the 59 // object immediately. Otherwise, asks the worker thread to abort processing, 60 // and schedules the object to be deleted once the worker exits. 61 // SignalWorkDone will not be signalled. If wait is true, does not return 62 // until the thread is deleted. 63 void Destroy(bool wait); 64 65 // Context: Main Thread. If the worker thread is complete, deletes the 66 // object immediately. Otherwise, schedules the object to be deleted once 67 // the worker thread completes. SignalWorkDone will be signalled. 68 void Release(); 69 70 // Context: Main Thread. Signalled when work is complete. 71 sigslot::signal1<DEPRECATED_SignalThread*> SignalWorkDone; 72 73 enum { ST_MSG_WORKER_DONE, ST_MSG_FIRST_AVAILABLE }; 74 75 protected: 76 ~DEPRECATED_SignalThread() override; 77 worker()78 Thread* worker() { return &worker_; } 79 80 // Context: Main Thread. Subclass should override to do pre-work setup. OnWorkStart()81 virtual void OnWorkStart() {} 82 83 // Context: Worker Thread. Subclass should override to do work. 84 virtual void DoWork() = 0; 85 86 // Context: Worker Thread. Subclass should call periodically to 87 // dispatch messages and determine if the thread should terminate. 88 bool ContinueWork(); 89 90 // Context: Worker Thread. Subclass should override when extra work is 91 // needed to abort the worker thread. OnWorkStop()92 virtual void OnWorkStop() {} 93 94 // Context: Main Thread. Subclass should override to do post-work cleanup. OnWorkDone()95 virtual void OnWorkDone() {} 96 97 // Context: Any Thread. If subclass overrides, be sure to call the base 98 // implementation. Do not use (message_id < ST_MSG_FIRST_AVAILABLE) 99 void OnMessage(Message* msg) override; 100 101 private: 102 enum State { 103 kInit, // Initialized, but not started 104 kRunning, // Started and doing work 105 kReleasing, // Same as running, but to be deleted when work is done 106 kComplete, // Work is done 107 kStopping, // Work is being interrupted 108 }; 109 110 class Worker : public Thread { 111 public: 112 explicit Worker(DEPRECATED_SignalThread* parent); 113 ~Worker() override; 114 void Run() override; 115 bool IsProcessingMessagesForTesting() override; 116 117 private: 118 DEPRECATED_SignalThread* parent_; 119 120 RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(Worker); 121 }; 122 123 class RTC_SCOPED_LOCKABLE EnterExit { 124 public: EnterExit(DEPRECATED_SignalThread * t)125 explicit EnterExit(DEPRECATED_SignalThread* t) 126 RTC_EXCLUSIVE_LOCK_FUNCTION(t->cs_) 127 : t_(t) { 128 t_->cs_.Enter(); 129 // If refcount_ is zero then the object has already been deleted and we 130 // will be double-deleting it in ~EnterExit()! (shouldn't happen) 131 RTC_DCHECK_NE(0, t_->refcount_); 132 ++t_->refcount_; 133 } RTC_UNLOCK_FUNCTION()134 ~EnterExit() RTC_UNLOCK_FUNCTION() { 135 bool d = (0 == --t_->refcount_); 136 t_->cs_.Leave(); 137 if (d) 138 delete t_; 139 } 140 141 private: 142 DEPRECATED_SignalThread* t_; 143 144 RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(EnterExit); 145 }; 146 147 void Run(); 148 void OnMainThreadDestroyed(); 149 150 Thread* main_; 151 Worker worker_; 152 RecursiveCriticalSection cs_; 153 State state_ RTC_GUARDED_BY(cs_); 154 int refcount_ RTC_GUARDED_BY(cs_); 155 bool destroy_called_ RTC_GUARDED_BY(cs_) = false; 156 157 RTC_DISALLOW_COPY_AND_ASSIGN(DEPRECATED_SignalThread); 158 }; 159 160 typedef RTC_DEPRECATED DEPRECATED_SignalThread SignalThread; 161 162 /////////////////////////////////////////////////////////////////////////////// 163 164 } // namespace rtc 165 166 #endif // RTC_BASE_DEPRECATED_SIGNAL_THREAD_H_ 167