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