blob: 77d767a78c2fe58cf2796c4265d65425392a41cd [file] [log] [blame]
henrike@webrtc.orgf7795df2014-05-13 18:00:26 +00001/*
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_TASK_H__
12#define WEBRTC_BASE_TASK_H__
13
14#include <string>
15#include "webrtc/base/basictypes.h"
16#include "webrtc/base/scoped_ptr.h"
17#include "webrtc/base/sigslot.h"
18#include "webrtc/base/taskparent.h"
19
20/////////////////////////////////////////////////////////////////////
21//
22// TASK
23//
24/////////////////////////////////////////////////////////////////////
25//
26// Task is a state machine infrastructure. States are pushed forward by
27// pushing forwards a TaskRunner that holds on to all Tasks. The purpose
28// of Task is threefold:
29//
30// (1) It manages ongoing work on the UI thread. Multitasking without
31// threads, keeping it easy, keeping it real. :-) It does this by
32// organizing a set of states for each task. When you return from your
33// Process*() function, you return an integer for the next state. You do
34// not go onto the next state yourself. Every time you enter a state,
35// you check to see if you can do anything yet. If not, you return
36// STATE_BLOCKED. If you _could_ do anything, do not return
37// STATE_BLOCKED - even if you end up in the same state, return
38// STATE_mysamestate. When you are done, return STATE_DONE and then the
39// task will self-delete sometime afterwards.
40//
41// (2) It helps you avoid all those reentrancy problems when you chain
42// too many triggers on one thread. Basically if you want to tell a task
43// to process something for you, you feed your task some information and
44// then you Wake() it. Don't tell it to process it right away. If it
45// might be working on something as you send it information, you may want
46// to have a queue in the task.
47//
48// (3) Finally it helps manage parent tasks and children. If a parent
49// task gets aborted, all the children tasks are too. The nice thing
50// about this, for example, is if you have one parent task that
51// represents, say, and Xmpp connection, then you can spawn a whole bunch
52// of infinite lifetime child tasks and now worry about cleaning them up.
53// When the parent task goes to STATE_DONE, the task engine will make
54// sure all those children are aborted and get deleted.
55//
56// Notice that Task has a few built-in states, e.g.,
57//
58// STATE_INIT - the task isn't running yet
59// STATE_START - the task is in its first state
60// STATE_RESPONSE - the task is in its second state
61// STATE_DONE - the task is done
62//
63// STATE_ERROR - indicates an error - we should audit the error code in
64// light of any usage of it to see if it should be improved. When I
65// first put down the task stuff I didn't have a good sense of what was
66// needed for Abort and Error, and now the subclasses of Task will ground
67// the design in a stronger way.
68//
69// STATE_NEXT - the first undefined state number. (like WM_USER) - you
70// can start defining more task states there.
71//
72// When you define more task states, just override Process(int state) and
73// add your own switch statement. If you want to delegate to
74// Task::Process, you can effectively delegate to its switch statement.
75// No fancy method pointers or such - this is all just pretty low tech,
76// easy to debug, and fast.
77//
78// Also notice that Task has some primitive built-in timeout functionality.
79//
80// A timeout is defined as "the task stays in STATE_BLOCKED longer than
81// timeout_seconds_."
82//
83// Descendant classes can override this behavior by calling the
84// various protected methods to change the timeout behavior. For
85// instance, a descendand might call SuspendTimeout() when it knows
86// that it isn't waiting for anything that might timeout, but isn't
87// yet in the STATE_DONE state.
88//
89
90namespace rtc {
91
92// Executes a sequence of steps
93class Task : public TaskParent {
94 public:
95 Task(TaskParent *parent);
96 virtual ~Task();
97
98 int32 unique_id() { return unique_id_; }
99
100 void Start();
101 void Step();
102 int GetState() const { return state_; }
103 bool HasError() const { return (GetState() == STATE_ERROR); }
104 bool Blocked() const { return blocked_; }
105 bool IsDone() const { return done_; }
106 int64 ElapsedTime();
107
108 // Called from outside to stop task without any more callbacks
109 void Abort(bool nowake = false);
110
111 bool TimedOut();
112
113 int64 timeout_time() const { return timeout_time_; }
114 int timeout_seconds() const { return timeout_seconds_; }
115 void set_timeout_seconds(int timeout_seconds);
116
117 sigslot::signal0<> SignalTimeout;
118
119 // Called inside the task to signal that the task may be unblocked
120 void Wake();
121
122 protected:
123
124 enum {
125 STATE_BLOCKED = -1,
126 STATE_INIT = 0,
127 STATE_START = 1,
128 STATE_DONE = 2,
129 STATE_ERROR = 3,
130 STATE_RESPONSE = 4,
131 STATE_NEXT = 5, // Subclasses which need more states start here and higher
132 };
133
134 // Called inside to advise that the task should wake and signal an error
135 void Error();
136
137 int64 CurrentTime();
138
139 virtual std::string GetStateName(int state) const;
140 virtual int Process(int state);
141 virtual void Stop();
142 virtual int ProcessStart() = 0;
143 virtual int ProcessResponse() { return STATE_DONE; }
144
145 void ResetTimeout();
146 void ClearTimeout();
147
148 void SuspendTimeout();
149 void ResumeTimeout();
150
151 protected:
152 virtual int OnTimeout() {
153 // by default, we are finished after timing out
154 return STATE_DONE;
155 }
156
157 private:
158 void Done();
159
160 int state_;
161 bool blocked_;
162 bool done_;
163 bool aborted_;
164 bool busy_;
165 bool error_;
166 int64 start_time_;
167 int64 timeout_time_;
168 int timeout_seconds_;
169 bool timeout_suspended_;
170 int32 unique_id_;
171
172 static int32 unique_id_seed_;
173};
174
175} // namespace rtc
176
177#endif // WEBRTC_BASE_TASK_H__