• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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  private:
60   struct DeferredTask  {
61     DeferredTask();
62     DeferredTask(DeferredTask&& other);
63     ~DeferredTask();
64     DeferredTask& operator=(DeferredTask&& other);
65 
66     Location posted_from;
67     OnceClosure task;
68     // The delay this task was initially posted with.
69     TimeDelta delay;
70     bool is_non_nestable;
71   };
72 
73   ~DeferredSequencedTaskRunner() override;
74 
75   // Both variants of Start() call into this.
76   void StartImpl();
77 
78   // Creates a |Task| object and adds it to |deferred_tasks_queue_|.
79   void QueueDeferredTask(const Location& from_here,
80                          OnceClosure task,
81                          TimeDelta delay,
82                          bool is_non_nestable);
83 
84   mutable Lock lock_;
85 
86   const PlatformThreadId created_thread_id_;
87 
88   // An atomic pointer that allows to call task_runner methods without lock.
89   // It's possible because the pointer starts as null, is set to a non-null
90   // value only once, and is never changed again.
91   // This is used to implement a lock-free RunsTasksInCurrentSequence method.
92   std::atomic<SequencedTaskRunner*> task_runner_atomic_ptr_{nullptr};
93   bool started_ GUARDED_BY(lock_) = false;
94   scoped_refptr<SequencedTaskRunner> target_task_runner_ GUARDED_BY(lock_);
95   std::vector<DeferredTask> deferred_tasks_queue_ GUARDED_BY(lock_);
96 };
97 
98 }  // namespace base
99 
100 #endif  // BASE_TASK_DEFERRED_SEQUENCED_TASK_RUNNER_H_
101