blob: f6ca64678185e83ae46170a0450fb906cabb7b8e [file] [log] [blame]
akalin@chromium.org062f9682012-02-15 10:43:19 +09001// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
dbeam@chromium.org36f60402013-05-08 14:35:24 +09005#ifndef BASE_SEQUENCED_TASKRUNNER_H_
6#define BASE_SEQUENCED_TASKRUNNER_H_
akalin@chromium.org062f9682012-02-15 10:43:19 +09007
8#include "base/base_export.h"
dbeam@chromium.org36f60402013-05-08 14:35:24 +09009#include "base/sequenced_task_runner_helpers.h"
akalin@chromium.org062f9682012-02-15 10:43:19 +090010#include "base/task_runner.h"
11
12namespace base {
13
14// A SequencedTaskRunner is a subclass of TaskRunner that provides
15// additional guarantees on the order that tasks are started, as well
16// as guarantees on when tasks are in sequence, i.e. one task finishes
17// before the other one starts.
18//
19// Summary
20// -------
akalin@chromium.orgd3f79b72012-12-18 09:32:18 +090021// Non-nested tasks with the same delay will run one by one in FIFO
22// order.
akalin@chromium.org062f9682012-02-15 10:43:19 +090023//
24// Detailed guarantees
25// -------------------
26//
27// SequencedTaskRunner also adds additional methods for posting
28// non-nestable tasks. In general, an implementation of TaskRunner
29// may expose task-running methods which are themselves callable from
30// within tasks. A non-nestable task is one that is guaranteed to not
31// be run from within an already-running task. Conversely, a nestable
32// task (the default) is a task that can be run from within an
33// already-running task.
34//
35// The guarantees of SequencedTaskRunner are as follows:
36//
37// - Given two tasks T2 and T1, T2 will start after T1 starts if:
38//
akalin@chromium.orgd3f79b72012-12-18 09:32:18 +090039// * T2 is posted after T1; and
akalin@chromium.org062f9682012-02-15 10:43:19 +090040// * T2 has equal or higher delay than T1; and
41// * T2 is non-nestable or T1 is nestable.
42//
43// - If T2 will start after T1 starts by the above guarantee, then
akalin@chromium.orgd3f79b72012-12-18 09:32:18 +090044// T2 will start after T1 finishes and is destroyed if:
akalin@chromium.org062f9682012-02-15 10:43:19 +090045//
46// * T2 is non-nestable, or
47// * T1 doesn't call any task-running methods.
48//
49// - If T2 will start after T1 finishes by the above guarantee, then
akalin@chromium.orgd3f79b72012-12-18 09:32:18 +090050// all memory changes in T1 and T1's destruction will be visible
51// to T2.
akalin@chromium.org062f9682012-02-15 10:43:19 +090052//
53// - If T2 runs nested within T1 via a call to the task-running
54// method M, then all memory changes in T1 up to the call to M
55// will be visible to T2, and all memory changes in T2 will be
56// visible to T1 from the return from M.
57//
58// Note that SequencedTaskRunner does not guarantee that tasks are run
59// on a single dedicated thread, although the above guarantees provide
60// most (but not all) of the same guarantees. If you do need to
61// guarantee that tasks are run on a single dedicated thread, see
62// SingleThreadTaskRunner (in single_thread_task_runner.h).
63//
64// Some corollaries to the above guarantees, assuming the tasks in
65// question don't call any task-running methods:
66//
67// - Tasks posted via PostTask are run in FIFO order.
68//
69// - Tasks posted via PostNonNestableTask are run in FIFO order.
70//
71// - Tasks posted with the same delay and the same nestable state
72// are run in FIFO order.
73//
74// - A list of tasks with the same nestable state posted in order of
75// non-decreasing delay is run in FIFO order.
76//
77// - A list of tasks posted in order of non-decreasing delay with at
78// most a single change in nestable state from nestable to
79// non-nestable is run in FIFO order. (This is equivalent to the
80// statement of the first guarantee above.)
81//
82// Some theoretical implementations of SequencedTaskRunner:
83//
84// - A SequencedTaskRunner that wraps a regular TaskRunner but makes
85// sure that only one task at a time is posted to the TaskRunner,
86// with appropriate memory barriers in between tasks.
87//
88// - A SequencedTaskRunner that, for each task, spawns a joinable
89// thread to run that task and immediately quit, and then
90// immediately joins that thread.
91//
92// - A SequencedTaskRunner that stores the list of posted tasks and
93// has a method Run() that runs each runnable task in FIFO order
94// that can be called from any thread, but only if another
95// (non-nested) Run() call isn't already happening.
96class BASE_EXPORT SequencedTaskRunner : public TaskRunner {
97 public:
98 // The two PostNonNestable*Task methods below are like their
99 // nestable equivalents in TaskRunner, but they guarantee that the
100 // posted task will not run nested within an already-running task.
101 //
102 // A simple corollary is that posting a task as non-nestable can
103 // only delay when the task gets run. That is, posting a task as
104 // non-nestable may not affect when the task gets run, or it could
105 // make it run later than it normally would, but it won't make it
106 // run earlier than it normally would.
107
108 // TODO(akalin): Get rid of the boolean return value for the methods
109 // below.
110
111 bool PostNonNestableTask(const tracked_objects::Location& from_here,
112 const Closure& task);
113
114 virtual bool PostNonNestableDelayedTask(
115 const tracked_objects::Location& from_here,
116 const Closure& task,
tedvessenes@gmail.com01b5a4d2012-02-26 17:17:37 +0900117 base::TimeDelta delay) = 0;
118
akalin@chromium.org062f9682012-02-15 10:43:19 +0900119 // Submits a non-nestable task to delete the given object. Returns
120 // true if the object may be deleted at some point in the future,
121 // and false if the object definitely will not be deleted.
122 template <class T>
123 bool DeleteSoon(const tracked_objects::Location& from_here,
124 const T* object) {
125 return
126 subtle::DeleteHelperInternal<T, bool>::DeleteViaSequencedTaskRunner(
127 this, from_here, object);
128 }
129
130 // Submits a non-nestable task to release the given object. Returns
131 // true if the object may be released at some point in the future,
132 // and false if the object definitely will not be released.
133 template <class T>
134 bool ReleaseSoon(const tracked_objects::Location& from_here,
135 T* object) {
136 return
137 subtle::ReleaseHelperInternal<T, bool>::ReleaseViaSequencedTaskRunner(
138 this, from_here, object);
139 }
140
rsleevi@chromium.orgd595b422012-04-06 12:14:30 +0900141 protected:
142 virtual ~SequencedTaskRunner() {}
143
144 private:
akalin@chromium.org062f9682012-02-15 10:43:19 +0900145 template <class T, class R> friend class subtle::DeleteHelperInternal;
146 template <class T, class R> friend class subtle::ReleaseHelperInternal;
147
148 bool DeleteSoonInternal(const tracked_objects::Location& from_here,
149 void(*deleter)(const void*),
150 const void* object);
151
152 bool ReleaseSoonInternal(const tracked_objects::Location& from_here,
153 void(*releaser)(const void*),
154 const void* object);
155};
156
157} // namespace base
158
dbeam@chromium.org36f60402013-05-08 14:35:24 +0900159#endif // BASE_SEQUENCED_TASKRUNNER_H_