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

« back to all changes in this revision

Viewing changes to protocols/jabber/googletalk/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_