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