147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org/* 247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org * Copyright 2004 The WebRTC Project Authors. All rights reserved. 347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org * 447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org * Use of this source code is governed by a BSD-style license 547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org * that can be found in the LICENSE file in the root of the source 647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org * tree. An additional intellectual property rights grant can be found 747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org * in the file PATENTS. All contributing project authors may 847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org * be found in the AUTHORS file in the root of the source tree. 947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org */ 1047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 1147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#ifndef WEBRTC_BASE_SIGNALTHREAD_H_ 1247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#define WEBRTC_BASE_SIGNALTHREAD_H_ 1347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 1447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include <string> 1547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 1647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include "webrtc/base/constructormagic.h" 1747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include "webrtc/base/sigslot.h" 1847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include "webrtc/base/thread.h" 1947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 2047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgnamespace rtc { 2147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 2247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org/////////////////////////////////////////////////////////////////////////////// 2347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// SignalThread - Base class for worker threads. The main thread should call 2447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// Start() to begin work, and then follow one of these models: 2547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// Normal: Wait for SignalWorkDone, and then call Release to destroy. 2647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// Cancellation: Call Release(true), to abort the worker thread. 2747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// Fire-and-forget: Call Release(false), which allows the thread to run to 2847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// completion, and then self-destruct without further notification. 2947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// Periodic tasks: Wait for SignalWorkDone, then eventually call Start() 3047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// again to repeat the task. When the instance isn't needed anymore, 3147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// call Release. DoWork, OnWorkStart and OnWorkStop are called again, 3247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// on a new thread. 3347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// The subclass should override DoWork() to perform the background task. By 3447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// periodically calling ContinueWork(), it can check for cancellation. 3547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// OnWorkStart and OnWorkDone can be overridden to do pre- or post-work 3647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// tasks in the context of the main thread. 3747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org/////////////////////////////////////////////////////////////////////////////// 3847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 3947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgclass SignalThread 4047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org : public sigslot::has_slots<>, 4147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org protected MessageHandler { 4247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org public: 4347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org SignalThread(); 4447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 4547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // Context: Main Thread. Call before Start to change the worker's name. 4647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org bool SetName(const std::string& name, const void* obj); 4747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 4847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // Context: Main Thread. Call before Start to change the worker's priority. 4947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org bool SetPriority(ThreadPriority priority); 5047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 5147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // Context: Main Thread. Call to begin the worker thread. 5247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org void Start(); 5347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 5447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // Context: Main Thread. If the worker thread is not running, deletes the 5547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // object immediately. Otherwise, asks the worker thread to abort processing, 5647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // and schedules the object to be deleted once the worker exits. 5747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // SignalWorkDone will not be signalled. If wait is true, does not return 5847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // until the thread is deleted. 5947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org void Destroy(bool wait); 6047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 6147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // Context: Main Thread. If the worker thread is complete, deletes the 6247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // object immediately. Otherwise, schedules the object to be deleted once 6347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // the worker thread completes. SignalWorkDone will be signalled. 6447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org void Release(); 6547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 6647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // Context: Main Thread. Signalled when work is complete. 6747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org sigslot::signal1<SignalThread *> SignalWorkDone; 6847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 6947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org enum { ST_MSG_WORKER_DONE, ST_MSG_FIRST_AVAILABLE }; 7047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 7147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org protected: 7247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org virtual ~SignalThread(); 7347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 7447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org Thread* worker() { return &worker_; } 7547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 7647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // Context: Main Thread. Subclass should override to do pre-work setup. 7747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org virtual void OnWorkStart() { } 7847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 7947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // Context: Worker Thread. Subclass should override to do work. 8047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org virtual void DoWork() = 0; 8147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 8247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // Context: Worker Thread. Subclass should call periodically to 8347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // dispatch messages and determine if the thread should terminate. 8447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org bool ContinueWork(); 8547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 8647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // Context: Worker Thread. Subclass should override when extra work is 8747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // needed to abort the worker thread. 8847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org virtual void OnWorkStop() { } 8947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 9047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // Context: Main Thread. Subclass should override to do post-work cleanup. 9147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org virtual void OnWorkDone() { } 9247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 9347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // Context: Any Thread. If subclass overrides, be sure to call the base 9447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // implementation. Do not use (message_id < ST_MSG_FIRST_AVAILABLE) 9547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org virtual void OnMessage(Message *msg); 9647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 9747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org private: 9847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org enum State { 9947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org kInit, // Initialized, but not started 10047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org kRunning, // Started and doing work 10147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org kReleasing, // Same as running, but to be deleted when work is done 10247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org kComplete, // Work is done 10347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org kStopping, // Work is being interrupted 10447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org }; 10547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 10647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org class Worker : public Thread { 10747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org public: 10847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org explicit Worker(SignalThread* parent) : parent_(parent) {} 10947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org virtual ~Worker() { Stop(); } 11047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org virtual void Run() { parent_->Run(); } 11147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 11247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org private: 11347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org SignalThread* parent_; 11447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 11547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org DISALLOW_IMPLICIT_CONSTRUCTORS(Worker); 11647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org }; 11747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 11846c93aa23855b429a7bd3c622842539bf5937d3dpbos@webrtc.org class SCOPED_LOCKABLE EnterExit { 11947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org public: 12046c93aa23855b429a7bd3c622842539bf5937d3dpbos@webrtc.org explicit EnterExit(SignalThread* t) EXCLUSIVE_LOCK_FUNCTION(t->cs_) 12146c93aa23855b429a7bd3c622842539bf5937d3dpbos@webrtc.org : t_(t) { 12247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org t_->cs_.Enter(); 12347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // If refcount_ is zero then the object has already been deleted and we 12447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // will be double-deleting it in ~EnterExit()! (shouldn't happen) 12547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org ASSERT(t_->refcount_ != 0); 12647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org ++t_->refcount_; 12747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 12846c93aa23855b429a7bd3c622842539bf5937d3dpbos@webrtc.org ~EnterExit() UNLOCK_FUNCTION() { 12947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org bool d = (0 == --t_->refcount_); 13047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org t_->cs_.Leave(); 13147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (d) 13247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org delete t_; 13347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 13447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 13547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org private: 13647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org SignalThread* t_; 13747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 13847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org DISALLOW_IMPLICIT_CONSTRUCTORS(EnterExit); 13947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org }; 14047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 14147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org void Run(); 14247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org void OnMainThreadDestroyed(); 14347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 14447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org Thread* main_; 14547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org Worker worker_; 14647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org CriticalSection cs_; 14747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org State state_; 14847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org int refcount_; 14947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 15047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org DISALLOW_COPY_AND_ASSIGN(SignalThread); 15147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}; 15247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 15347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org/////////////////////////////////////////////////////////////////////////////// 15447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 15547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} // namespace rtc 15647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 15747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#endif // WEBRTC_BASE_SIGNALTHREAD_H_ 158