• 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_ONE_SHOT_EVENT_H_
6 #define BASE_ONE_SHOT_EVENT_H_
7 
8 #include <vector>
9 
10 #include "base/base_export.h"
11 #include "base/check.h"
12 #include "base/functional/callback_forward.h"
13 #include "base/memory/weak_ptr.h"
14 #include "base/sequence_checker.h"
15 #include "base/task/sequenced_task_runner.h"
16 #include "base/task/single_thread_task_runner.h"
17 
18 namespace base {
19 
20 class Location;
21 class TimeDelta;
22 
23 // This class represents an event that's expected to happen once. It allows
24 // clients to guarantee that code is run after the `OneShotEvent` is signaled.
25 // If the `OneShotEvent` is destroyed before it's signaled, the closures are
26 // destroyed without being run.
27 //
28 // This class is similar to a `WaitableEvent` combined with several
29 // `WaitableEventWatcher`s, but using it is simpler.
30 //
31 // This class' methods must be used from a single sequence (although not
32 // necessarily the one in which it has been constructed).
33 // However, there are no restrictions on the `TaskRunner`s used - and hence, the
34 // sequence/thread on which the posted tasks will run. By default they will
35 // be posted to the current sequence's default task runner.
36 class BASE_EXPORT OneShotEvent {
37  public:
38   OneShotEvent();
39   // Use the following constructor to create an already signaled event. This is
40   // useful if you construct the event on a different thread from where it is
41   // used, in which case it is not possible to call `Signal` just after
42   // construction.
43   explicit OneShotEvent(bool signaled);
44   ~OneShotEvent();
45 
46   // True if `Signal` has been called. This function is mostly for migrating old
47   // code; usually calling `Post` unconditionally will result in more readable
48   // code.
is_signaled()49   bool is_signaled() const {
50     DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
51     return signaled_;
52   }
53 
54   // Causes `is_signaled` to return true and all tasks to be posted to their
55   // corresponding task runners in the FIFO order. Note that tasks posted to
56   // different `TaskRunner`s may still execute in arbitrary order. This
57   // method must only be called once.
58   void Signal();
59 
60   // Schedules `task` to be called on `runner` after `is_signaled` becomes
61   // `true`. If called with `delay`, then the task will happen (roughly) `delay`
62   // after `is_signaled`, *not* `delay` after the post. Inside `task`, if this
63   // `OneShotEvent` is still alive, `CHECK(is_signaled())` will never fail
64   // (which implies that `OneShotEvent::Reset` doesn't exist).
65   //
66   // If `*this` is destroyed before being released, none of these tasks will be
67   // executed.
68   //
69   // Tasks are posted in FIFO order, however, tasks may still execute in an
70   // arbitrary order (specified by the combination and type of `TaskRunner`s
71   // used). Tasks will never be called on the current sequence before this
72   // function returns.
73   // Beware that there's no simple way to wait for all tasks on a `OneShotEvent`
74   // to complete, so it's almost never safe to use `base::Unretained` when
75   // creating one.
76   void Post(const Location& from_here,
77             OnceClosure task,
78             scoped_refptr<TaskRunner> runner =
79                 SequencedTaskRunner::GetCurrentDefault()) const;
80   void PostDelayed(const Location& from_here,
81                    OnceClosure task,
82                    const TimeDelta& delay,
83                    scoped_refptr<TaskRunner> runner =
84                        SequencedTaskRunner::GetCurrentDefault()) const;
85 
86  private:
87   struct TaskInfo;
88   SEQUENCE_CHECKER(sequence_checker_);
89 
90   bool signaled_ = false;
91 
92   // The task list is mutable because it's not part of the logical state of the
93   // object. This lets us return const references to the `OneShotEvent` to
94   // clients that just want to run tasks through it without worrying that
95   // they'll signal the event.
96   //
97   // Optimization note: We could reduce the size of this class to a single
98   // pointer by storing `signaled_` in the low bit of a pointer, and storing the
99   // size and capacity of the array (if any) on the far end of the pointer.
100   mutable std::vector<TaskInfo> tasks_;
101 };
102 
103 }  // namespace base
104 
105 #endif  // BASE_ONE_SHOT_EVENT_H_
106