Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1919)

Side by Side Diff: third_party/libjingle_xmpp/task_runner/task.cc

Issue 2694903005: Add a copy of webrtc's TaskRunner abstraction, which is going to be deleted in webrtc. (Closed)
Patch Set: Delete dependencies on webrtc's rtc_task_runner. Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 /*
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 #include "third_party/libjingle_xmpp/task_runner/task.h"
12 #include "third_party/libjingle_xmpp/task_runner/taskrunner.h"
13 #include "third_party/webrtc/base/checks.h"
14
15 namespace rtc {
16
17 int32_t Task::unique_id_seed_ = 0;
18
19 Task::Task(TaskParent *parent)
20 : TaskParent(this, parent),
21 state_(STATE_INIT),
22 blocked_(false),
23 done_(false),
24 aborted_(false),
25 busy_(false),
26 error_(false),
27 start_time_(0),
28 timeout_time_(0),
29 timeout_seconds_(0),
30 timeout_suspended_(false) {
31 unique_id_ = unique_id_seed_++;
32
33 // sanity check that we didn't roll-over our id seed
34 RTC_DCHECK(unique_id_ < unique_id_seed_);
35 }
36
37 Task::~Task() {
38 // Is this task being deleted in the correct manner?
39 #if RTC_DCHECK_IS_ON
40 RTC_DCHECK(!done_ || GetRunner()->is_ok_to_delete(this));
41 #endif
42 RTC_DCHECK(state_ == STATE_INIT || done_);
43 RTC_DCHECK(state_ == STATE_INIT || blocked_);
44
45 // If the task is being deleted without being done, it
46 // means that it hasn't been removed from its parent.
47 // This happens if a task is deleted outside of TaskRunner.
48 if (!done_) {
49 Stop();
50 }
51 }
52
53 int64_t Task::CurrentTime() {
54 return GetRunner()->CurrentTime();
55 }
56
57 int64_t Task::ElapsedTime() {
58 return CurrentTime() - start_time_;
59 }
60
61 void Task::Start() {
62 if (state_ != STATE_INIT)
63 return;
64 // Set the start time before starting the task. Otherwise if the task
65 // finishes quickly and deletes the Task object, setting start_time_
66 // will crash.
67 start_time_ = CurrentTime();
68 GetRunner()->StartTask(this);
69 }
70
71 void Task::Step() {
72 if (done_) {
73 #if RTC_DCHECK_IS_ON
74 // we do not know how !blocked_ happens when done_ - should be impossible.
75 // But it causes problems, so in retail build, we force blocked_, and
76 // under debug we assert.
77 RTC_DCHECK(blocked_);
78 #else
79 blocked_ = true;
80 #endif
81 return;
82 }
83
84 // Async Error() was called
85 if (error_) {
86 done_ = true;
87 state_ = STATE_ERROR;
88 blocked_ = true;
89 // obsolete - an errored task is not considered done now
90 // SignalDone();
91
92 Stop();
93 #if RTC_DCHECK_IS_ON
94 // verify that stop removed this from its parent
95 RTC_DCHECK(!parent()->IsChildTask(this));
96 #endif
97 return;
98 }
99
100 busy_ = true;
101 int new_state = Process(state_);
102 busy_ = false;
103
104 if (aborted_) {
105 Abort(true); // no need to wake because we're awake
106 return;
107 }
108
109 if (new_state == STATE_BLOCKED) {
110 blocked_ = true;
111 // Let the timeout continue
112 } else {
113 state_ = new_state;
114 blocked_ = false;
115 ResetTimeout();
116 }
117
118 if (new_state == STATE_DONE) {
119 done_ = true;
120 } else if (new_state == STATE_ERROR) {
121 done_ = true;
122 error_ = true;
123 }
124
125 if (done_) {
126 // obsolete - call this yourself
127 // SignalDone();
128
129 Stop();
130 #if RTC_DCHECK_IS_ON
131 // verify that stop removed this from its parent
132 RTC_DCHECK(!parent()->IsChildTask(this));
133 #endif
134 blocked_ = true;
135 }
136 }
137
138 void Task::Abort(bool nowake) {
139 // Why only check for done_ (instead of "aborted_ || done_")?
140 //
141 // If aborted_ && !done_, it means the logic for aborting still
142 // needs to be executed (because busy_ must have been true when
143 // Abort() was previously called).
144 if (done_)
145 return;
146 aborted_ = true;
147 if (!busy_) {
148 done_ = true;
149 blocked_ = true;
150 error_ = true;
151
152 // "done_" is set before calling "Stop()" to ensure that this code
153 // doesn't execute more than once (recursively) for the same task.
154 Stop();
155 #if RTC_DCHECK_IS_ON
156 // verify that stop removed this from its parent
157 RTC_DCHECK(!parent()->IsChildTask(this));
158 #endif
159 if (!nowake) {
160 // WakeTasks to self-delete.
161 // Don't call Wake() because it is a no-op after "done_" is set.
162 // Even if Wake() did run, it clears "blocked_" which isn't desireable.
163 GetRunner()->WakeTasks();
164 }
165 }
166 }
167
168 void Task::Wake() {
169 if (done_)
170 return;
171 if (blocked_) {
172 blocked_ = false;
173 GetRunner()->WakeTasks();
174 }
175 }
176
177 void Task::Error() {
178 if (error_ || done_)
179 return;
180 error_ = true;
181 Wake();
182 }
183
184 std::string Task::GetStateName(int state) const {
185 switch (state) {
186 case STATE_BLOCKED: return "BLOCKED";
187 case STATE_INIT: return "INIT";
188 case STATE_START: return "START";
189 case STATE_DONE: return "DONE";
190 case STATE_ERROR: return "ERROR";
191 case STATE_RESPONSE: return "RESPONSE";
192 }
193 return "??";
194 }
195
196 int Task::Process(int state) {
197 int newstate = STATE_ERROR;
198
199 if (TimedOut()) {
200 ClearTimeout();
201 newstate = OnTimeout();
202 SignalTimeout();
203 } else {
204 switch (state) {
205 case STATE_INIT:
206 newstate = STATE_START;
207 break;
208 case STATE_START:
209 newstate = ProcessStart();
210 break;
211 case STATE_RESPONSE:
212 newstate = ProcessResponse();
213 break;
214 case STATE_DONE:
215 case STATE_ERROR:
216 newstate = STATE_BLOCKED;
217 break;
218 }
219 }
220
221 return newstate;
222 }
223
224 void Task::Stop() {
225 // No need to wake because we're either awake or in abort
226 TaskParent::OnStopped(this);
227 }
228
229 int Task::ProcessResponse() {
230 return STATE_DONE;
231 }
232
233 void Task::set_timeout_seconds(const int timeout_seconds) {
234 timeout_seconds_ = timeout_seconds;
235 ResetTimeout();
236 }
237
238 bool Task::TimedOut() {
239 return timeout_seconds_ &&
240 timeout_time_ &&
241 CurrentTime() >= timeout_time_;
242 }
243
244 void Task::ResetTimeout() {
245 int64_t previous_timeout_time = timeout_time_;
246 bool timeout_allowed = (state_ != STATE_INIT)
247 && (state_ != STATE_DONE)
248 && (state_ != STATE_ERROR);
249 if (timeout_seconds_ && timeout_allowed && !timeout_suspended_)
250 timeout_time_ = CurrentTime() +
251 (timeout_seconds_ * kSecToMsec * kMsecTo100ns);
252 else
253 timeout_time_ = 0;
254
255 GetRunner()->UpdateTaskTimeout(this, previous_timeout_time);
256 }
257
258 void Task::ClearTimeout() {
259 int64_t previous_timeout_time = timeout_time_;
260 timeout_time_ = 0;
261 GetRunner()->UpdateTaskTimeout(this, previous_timeout_time);
262 }
263
264 void Task::SuspendTimeout() {
265 if (!timeout_suspended_) {
266 timeout_suspended_ = true;
267 ResetTimeout();
268 }
269 }
270
271 void Task::ResumeTimeout() {
272 if (timeout_suspended_) {
273 timeout_suspended_ = false;
274 ResetTimeout();
275 }
276 }
277
278 int Task::OnTimeout() {
279 // by default, we are finished after timing out
280 return STATE_DONE;
281 }
282
283 } // namespace rtc
OLDNEW
« no previous file with comments | « third_party/libjingle_xmpp/task_runner/task.h ('k') | third_party/libjingle_xmpp/task_runner/task_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698