1 // Copyright 2013 The Chromium Authors 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef BASE_TASK_DEFERRED_SEQUENCED_TASK_RUNNER_H_ 6 #define BASE_TASK_DEFERRED_SEQUENCED_TASK_RUNNER_H_ 7 8 #include <vector> 9 10 #include "base/base_export.h" 11 #include "base/compiler_specific.h" 12 #include "base/functional/callback.h" 13 #include "base/synchronization/lock.h" 14 #include "base/task/sequenced_task_runner.h" 15 #include "base/threading/platform_thread.h" 16 #include "base/time/time.h" 17 18 namespace base { 19 20 // A DeferredSequencedTaskRunner is a subclass of SequencedTaskRunner that 21 // queues up all requests until the first call to Start() is issued. 22 // DeferredSequencedTaskRunner may be created in two ways: 23 // . with an explicit SequencedTaskRunner that the events are flushed to 24 // . without a SequencedTaskRunner. In this configuration the 25 // SequencedTaskRunner is supplied in StartWithTaskRunner(). 26 class BASE_EXPORT DeferredSequencedTaskRunner : public SequencedTaskRunner { 27 public: 28 explicit DeferredSequencedTaskRunner( 29 scoped_refptr<SequencedTaskRunner> target_runner); 30 31 // Use this constructor when you don't have the target SequencedTaskRunner. 32 // When using this call StartWithTaskRunner(). 33 DeferredSequencedTaskRunner(); 34 DeferredSequencedTaskRunner(const DeferredSequencedTaskRunner&) = delete; 35 DeferredSequencedTaskRunner& operator=(const DeferredSequencedTaskRunner&) = 36 delete; 37 38 // TaskRunner implementation 39 bool PostDelayedTask(const Location& from_here, 40 OnceClosure task, 41 TimeDelta delay) override; 42 43 // SequencedTaskRunner implementation 44 bool RunsTasksInCurrentSequence() const override; 45 bool PostNonNestableDelayedTask(const Location& from_here, 46 OnceClosure task, 47 TimeDelta delay) override; 48 49 // Start the execution - posts all queued tasks to the target executor. The 50 // deferred tasks are posted with their initial delay, meaning that the task 51 // execution delay is actually measured from Start. 52 // Fails when called a second time. 53 void Start(); 54 55 // Same as Start(), but must be used with the no-arg constructor. 56 void StartWithTaskRunner( 57 scoped_refptr<SequencedTaskRunner> target_task_runner); 58 59 // Returns true if task execution has been started. 60 bool Started() const; 61 62 private: 63 struct DeferredTask { 64 DeferredTask(); 65 DeferredTask(DeferredTask&& other); 66 ~DeferredTask(); 67 DeferredTask& operator=(DeferredTask&& other); 68 69 Location posted_from; 70 OnceClosure task; 71 // The delay this task was initially posted with. 72 TimeDelta delay; 73 bool is_non_nestable; 74 }; 75 76 ~DeferredSequencedTaskRunner() override; 77 78 // Both variants of Start() call into this. 79 void StartImpl(); 80 81 // Creates a |Task| object and adds it to |deferred_tasks_queue_|. 82 void QueueDeferredTask(const Location& from_here, 83 OnceClosure task, 84 TimeDelta delay, 85 bool is_non_nestable); 86 87 mutable Lock lock_; 88 89 const PlatformThreadId created_thread_id_; 90 91 // An atomic pointer that allows to call task_runner methods without lock. 92 // It's possible because the pointer starts as null, is set to a non-null 93 // value only once, and is never changed again. 94 // This is used to implement a lock-free RunsTasksInCurrentSequence method. 95 std::atomic<SequencedTaskRunner*> task_runner_atomic_ptr_{nullptr}; 96 bool started_ GUARDED_BY(lock_) = false; 97 scoped_refptr<SequencedTaskRunner> target_task_runner_ GUARDED_BY(lock_); 98 std::vector<DeferredTask> deferred_tasks_queue_ GUARDED_BY(lock_); 99 }; 100 101 } // namespace base 102 103 #endif // BASE_TASK_DEFERRED_SEQUENCED_TASK_RUNNER_H_ 104