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 EXTENSIONS_COMMON_ONE_SHOT_EVENT_H_ 6 #define EXTENSIONS_COMMON_ONE_SHOT_EVENT_H_ 7 8 #include <vector> 9 10 #include "base/callback_forward.h" 11 #include "base/logging.h" 12 #include "base/memory/ref_counted.h" 13 #include "base/memory/weak_ptr.h" 14 #include "base/threading/thread_checker.h" 15 16 namespace base { 17 class TaskRunner; 18 class TimeDelta; 19 } 20 21 namespace tracked_objects { 22 class Location; 23 } 24 25 namespace extensions { 26 27 // This class represents an event that's expected to happen once. It 28 // allows clients to guarantee that code is run after the OneShotEvent 29 // is signaled. If the OneShotEvent is destroyed before it's 30 // signaled, the delayed closures are destroyed without being run. 31 // 32 // This class is similar to a WaitableEvent combined with several 33 // WaitableEventWatchers, but using it is simpler. 34 // 35 // This class is not thread-safe, and must be used from a single thread. 36 class 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 47 // migrating old code; usually calling Post() unconditionally will 48 // result in more readable code. is_signaled()49 bool is_signaled() const { 50 DCHECK(thread_checker_.CalledOnValidThread()); 51 return signaled_; 52 } 53 54 // Causes is_signaled() to return true and all queued tasks to be 55 // run in an arbitrary order. This method must only be called once. 56 void Signal(); 57 58 // Scheduled |task| to be called on |runner| after is_signaled() 59 // becomes true. If called with |delay|, then the task will happen 60 // (roughly) |delay| after is_signaled(), *not* |delay| after the 61 // post. Inside |task|, if this OneShotEvent is still alive, 62 // CHECK(is_signaled()) will never fail (which implies that 63 // OneShotEvent::Reset() doesn't exist). 64 // 65 // If |*this| is destroyed before being released, none of these 66 // tasks will be executed. 67 // 68 // Omitting the |runner| argument indicates that |task| should run 69 // on MessageLoopProxy::current(). 70 // 71 // Tasks may be run in an arbitrary order, not just FIFO. Tasks 72 // will never be called on the current thread before this function 73 // returns. Beware that there's no simple way to wait for all tasks 74 // on a OneShotEvent to complete, so it's almost never safe to use 75 // base::Unretained() when creating one. 76 // 77 // Const because Post() doesn't modify the logical state of this 78 // object (which is just the is_signaled() bit). 79 void Post(const tracked_objects::Location& from_here, 80 const base::Closure& task) const; 81 void Post(const tracked_objects::Location& from_here, 82 const base::Closure& task, 83 const scoped_refptr<base::TaskRunner>& runner) const; 84 void PostDelayed(const tracked_objects::Location& from_here, 85 const base::Closure& task, 86 const base::TimeDelta& delay) const; 87 88 private: 89 struct TaskInfo; 90 91 void PostImpl(const tracked_objects::Location& from_here, 92 const base::Closure& task, 93 const scoped_refptr<base::TaskRunner>& runner, 94 const base::TimeDelta& delay) const; 95 96 base::ThreadChecker thread_checker_; 97 98 bool signaled_; 99 100 // The task list is mutable because it's not part of the logical 101 // state of the object. This lets us return const references to the 102 // OneShotEvent to clients that just want to run tasks through it 103 // without worrying that they'll signal the event. 104 // 105 // Optimization note: We could reduce the size of this class to a 106 // single pointer by storing |signaled_| in the low bit of a 107 // pointer, and storing the size and capacity of the array (if any) 108 // on the far end of the pointer. 109 mutable std::vector<TaskInfo> tasks_; 110 }; 111 112 } // namespace extensions 113 114 #endif // EXTENSIONS_COMMON_ONE_SHOT_EVENT_H_ 115