~ubuntu-branches/debian/experimental/kopete/experimental

« back to all changes in this revision

Viewing changes to protocols/jabber/libjingle/talk/base/signalthread.h

  • Committer: Package Import Robot
  • Author(s): Maximiliano Curia
  • Date: 2015-02-24 11:32:57 UTC
  • mfrom: (1.1.41 vivid)
  • Revision ID: package-import@ubuntu.com-20150224113257-gnupg4v7lzz18ij0
Tags: 4:14.12.2-1
* New upstream release (14.12.2).
* Bump Standards-Version to 3.9.6, no changes needed.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * libjingle
 
3
 * Copyright 2004--2009, Google Inc.
 
4
 *
 
5
 * Redistribution and use in source and binary forms, with or without
 
6
 * modification, are permitted provided that the following conditions are met:
 
7
 *
 
8
 *  1. Redistributions of source code must retain the above copyright notice,
 
9
 *     this list of conditions and the following disclaimer.
 
10
 *  2. Redistributions in binary form must reproduce the above copyright notice,
 
11
 *     this list of conditions and the following disclaimer in the documentation
 
12
 *     and/or other materials provided with the distribution.
 
13
 *  3. The name of the author may not be used to endorse or promote products
 
14
 *     derived from this software without specific prior written permission.
 
15
 *
 
16
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
 
17
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 
18
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
 
19
 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 
20
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 
21
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 
22
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 
23
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 
24
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 
25
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
26
 */
 
27
 
 
28
#ifndef TALK_BASE_SIGNALTHREAD_H_
 
29
#define TALK_BASE_SIGNALTHREAD_H_
 
30
 
 
31
#include <string>
 
32
 
 
33
#include "talk/base/constructormagic.h"
 
34
#include "talk/base/thread.h"
 
35
#include "talk/base/sigslot.h"
 
36
 
 
37
namespace talk_base {
 
38
 
 
39
///////////////////////////////////////////////////////////////////////////////
 
40
// SignalThread - Base class for worker threads.  The main thread should call
 
41
//  Start() to begin work, and then follow one of these models:
 
42
//   Normal: Wait for SignalWorkDone, and then call Release to destroy.
 
43
//   Cancellation: Call Release(true), to abort the worker thread.
 
44
//   Fire-and-forget: Call Release(false), which allows the thread to run to
 
45
//    completion, and then self-destruct without further notification.
 
46
//   Periodic tasks: Wait for SignalWorkDone, then eventually call Start()
 
47
//    again to repeat the task. When the instance isn't needed anymore,
 
48
//    call Release. DoWork, OnWorkStart and OnWorkStop are called again,
 
49
//    on a new thread.
 
50
//  The subclass should override DoWork() to perform the background task.  By
 
51
//   periodically calling ContinueWork(), it can check for cancellation.
 
52
//   OnWorkStart and OnWorkDone can be overridden to do pre- or post-work
 
53
//   tasks in the context of the main thread.
 
54
///////////////////////////////////////////////////////////////////////////////
 
55
 
 
56
class SignalThread : public sigslot::has_slots<>, protected MessageHandler {
 
57
 public:
 
58
  SignalThread();
 
59
 
 
60
  // Context: Main Thread.  Call before Start to change the worker's name.
 
61
  bool SetName(const std::string& name, const void* obj);
 
62
 
 
63
  // Context: Main Thread.  Call before Start to change the worker's priority.
 
64
  bool SetPriority(ThreadPriority priority);
 
65
 
 
66
  // Context: Main Thread.  Call to begin the worker thread.
 
67
  void Start();
 
68
 
 
69
  // Context: Main Thread.  If the worker thread is not running, deletes the
 
70
  // object immediately.  Otherwise, asks the worker thread to abort processing,
 
71
  // and schedules the object to be deleted once the worker exits.
 
72
  // SignalWorkDone will not be signalled.  If wait is true, does not return
 
73
  // until the thread is deleted.
 
74
  void Destroy(bool wait);
 
75
 
 
76
  // Context: Main Thread.  If the worker thread is complete, deletes the
 
77
  // object immediately.  Otherwise, schedules the object to be deleted once
 
78
  // the worker thread completes.  SignalWorkDone will be signalled.
 
79
  void Release();
 
80
 
 
81
  // Context: Main Thread.  Signalled when work is complete.
 
82
  sigslot::signal1<SignalThread *> SignalWorkDone;
 
83
 
 
84
  enum { ST_MSG_WORKER_DONE, ST_MSG_FIRST_AVAILABLE };
 
85
 
 
86
 protected:
 
87
  virtual ~SignalThread();
 
88
 
 
89
  Thread* worker() { return &worker_; }
 
90
 
 
91
  // Context: Main Thread.  Subclass should override to do pre-work setup.
 
92
  virtual void OnWorkStart() { }
 
93
 
 
94
  // Context: Worker Thread.  Subclass should override to do work.
 
95
  virtual void DoWork() = 0;
 
96
 
 
97
  // Context: Worker Thread.  Subclass should call periodically to
 
98
  // dispatch messages and determine if the thread should terminate.
 
99
  bool ContinueWork();
 
100
 
 
101
  // Context: Worker Thread.  Subclass should override when extra work is
 
102
  // needed to abort the worker thread.
 
103
  virtual void OnWorkStop() { }
 
104
 
 
105
  // Context: Main Thread.  Subclass should override to do post-work cleanup.
 
106
  virtual void OnWorkDone() { }
 
107
 
 
108
  // Context: Any Thread.  If subclass overrides, be sure to call the base
 
109
  // implementation.  Do not use (message_id < ST_MSG_FIRST_AVAILABLE)
 
110
  virtual void OnMessage(Message *msg);
 
111
 
 
112
 private:
 
113
  enum State {
 
114
    kInit,            // Initialized, but not started
 
115
    kRunning,         // Started and doing work
 
116
    kReleasing,       // Same as running, but to be deleted when work is done
 
117
    kComplete,        // Work is done
 
118
    kStopping,        // Work is being interrupted
 
119
  };
 
120
 
 
121
  class Worker : public Thread {
 
122
   public:
 
123
    explicit Worker(SignalThread* parent) : parent_(parent) {}
 
124
    virtual void Run() { parent_->Run(); }
 
125
 
 
126
   private:
 
127
    SignalThread* parent_;
 
128
 
 
129
    DISALLOW_IMPLICIT_CONSTRUCTORS(Worker);
 
130
  };
 
131
 
 
132
  class EnterExit {
 
133
   public:
 
134
    explicit EnterExit(SignalThread* t) : t_(t) {
 
135
      t_->cs_.Enter();
 
136
      // If refcount_ is zero then the object has already been deleted and we
 
137
      // will be double-deleting it in ~EnterExit()! (shouldn't happen)
 
138
      ASSERT(t_->refcount_ != 0);
 
139
      ++t_->refcount_;
 
140
    }
 
141
    ~EnterExit() {
 
142
      bool d = (0 == --t_->refcount_);
 
143
      t_->cs_.Leave();
 
144
      if (d)
 
145
        delete t_;
 
146
    }
 
147
 
 
148
   private:
 
149
    SignalThread* t_;
 
150
 
 
151
    DISALLOW_IMPLICIT_CONSTRUCTORS(EnterExit);
 
152
  };
 
153
 
 
154
  void Run();
 
155
  void OnMainThreadDestroyed();
 
156
 
 
157
  Thread* main_;
 
158
  Worker worker_;
 
159
  CriticalSection cs_;
 
160
  State state_;
 
161
  int refcount_;
 
162
 
 
163
  DISALLOW_COPY_AND_ASSIGN(SignalThread);
 
164
};
 
165
 
 
166
///////////////////////////////////////////////////////////////////////////////
 
167
 
 
168
}  // namespace talk_base
 
169
 
 
170
#endif  // TALK_BASE_SIGNALTHREAD_H_