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