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