diff options
Diffstat (limited to 'third_party/libjingle/files/talk/base/signalthread.h')
-rw-r--r-- | third_party/libjingle/files/talk/base/signalthread.h | 125 |
1 files changed, 125 insertions, 0 deletions
diff --git a/third_party/libjingle/files/talk/base/signalthread.h b/third_party/libjingle/files/talk/base/signalthread.h new file mode 100644 index 0000000..ad6b46a --- /dev/null +++ b/third_party/libjingle/files/talk/base/signalthread.h @@ -0,0 +1,125 @@ +#ifndef _SIGNALTHREAD_H_ +#define _SIGNALTHREAD_H_ + +#include "talk/base/thread.h" +#include "talk/base/sigslot.h" + +namespace talk_base { + +/////////////////////////////////////////////////////////////////////////////// +// SignalThread - Base class for worker threads. The main thread should call +// Start() to begin work, and then follow one of these models: +// Normal: Wait for SignalWorkDone, and then call Release to destroy. +// Cancellation: Call Release(true), to abort the worker thread. +// Fire-and-forget: Call Release(false), which allows the thread to run to +// completion, and then self-destruct without further notification. +// Periodic tasks: Wait for SignalWorkDone, then eventually call Start() +// again to repeat the task. When the instance isn't needed anymore, +// call Release. DoWork, OnWorkStart and OnWorkStop are called again, +// on a new thread. +// The subclass should override DoWork() to perform the background task. By +// periodically calling ContinueWork(), it can check for cancellation. +// OnWorkStart and OnWorkDone can be overridden to do pre- or post-work +// tasks in the context of the main thread. +/////////////////////////////////////////////////////////////////////////////// + +class SignalThread : public sigslot::has_slots<>, protected MessageHandler { +public: + SignalThread(); + + // Context: Main Thread. Call before Start to change the worker's priority. + void SetPriority(ThreadPriority priority); + + // Context: Main Thread. Call to begin the worker thread. + void Start(); + + // Context: Main Thread. If the worker thread is not running, deletes the + // object immediately. Otherwise, asks the worker thread to abort processing, + // and schedules the object to be deleted once the worker exits. + // SignalWorkDone will not be signalled. If wait is true, does not return + // until the thread is deleted. + void Destroy(bool wait); + + // Context: Main Thread. If the worker thread is complete, deletes the + // object immediately. Otherwise, schedules the object to be deleted once + // the worker thread completes. SignalWorkDone will be signalled. + void Release(); + + // Context: Main Thread. Signalled when work is complete. + sigslot::signal1<SignalThread *> SignalWorkDone; + + enum { ST_MSG_WORKER_DONE, ST_MSG_FIRST_AVAILABLE }; + +protected: + virtual ~SignalThread(); + + // Context: Main Thread. Subclass should override to do pre-work setup. + virtual void OnWorkStart() { } + + // Context: Worker Thread. Subclass should override to do work. + virtual void DoWork() = 0; + + // Context: Worker Thread. Subclass should call periodically to + // dispatch messages and determine if the thread should terminate. + bool ContinueWork(); + + // Context: Worker Thread. Subclass should override when extra work is + // needed to abort the worker thread. + virtual void OnWorkStop() { } + + // Context: Main Thread. Subclass should override to do post-work cleanup. + virtual void OnWorkDone() { } + + // Context: Any Thread. If subclass overrides, be sure to call the base + // implementation. Do not use (message_id < ST_MSG_FIRST_AVAILABLE) + virtual void OnMessage(Message *msg); + +private: + friend class Worker; + class Worker : public Thread { + public: + SignalThread* parent_; + virtual void Run() { parent_->Run(); } + }; + + class EnterExit { + friend class SignalThread; + + SignalThread * t_; + + EnterExit(SignalThread * t) : t_(t) { + t_->cs_.Enter(); + t_->refcount_ += 1; + } + ~EnterExit() { + bool d = (0 == (--(t_->refcount_))); + t_->cs_.Leave(); + if (d) + delete t_; + } + }; + + friend class EnterExit; + + CriticalSection cs_; + int refcount_; + + void Run(); + void OnMainThreadDestroyed(); + + Thread* main_; + Worker worker_; + enum State { + kInit, // Initialized, but not started + kRunning, // Started and doing work + kReleasing, // Same as running, but to be deleted when work is done + kComplete, // Work is done + kStopping, // Work is being interrupted + } state_; +}; + +/////////////////////////////////////////////////////////////////////////////// + +} // namespace talk_base + +#endif // _SIGNALTHREAD_H_ |