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