// Copyright 2013 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef BASE_ONE_SHOT_EVENT_H_ #define BASE_ONE_SHOT_EVENT_H_ #include #include "base/callback_forward.h" #include "base/check.h" #include "base/memory/ref_counted.h" #include "base/memory/weak_ptr.h" #include "base/threading/thread_checker.h" #include "base/threading/thread_task_runner_handle.h" namespace base { class Location; class SingleThreadTaskRunner; class TimeDelta; // This class represents an event that's expected to happen once. It // allows clients to guarantee that code is run after the OneShotEvent // is signaled. If the OneShotEvent is destroyed before it's // signaled, the closures are destroyed without being run. // // This class is similar to a WaitableEvent combined with several // WaitableEventWatchers, but using it is simpler. // // This class is not thread-safe, and must be used from a single thread. class BASE_EXPORT OneShotEvent { public: OneShotEvent(); // Use the following constructor to create an already signaled event. This is // useful if you construct the event on a different thread from where it is // used, in which case it is not possible to call Signal() just after // construction. explicit OneShotEvent(bool signaled); ~OneShotEvent(); // True if Signal has been called. This function is mostly for // migrating old code; usually calling Post() unconditionally will // result in more readable code. bool is_signaled() const { DCHECK(thread_checker_.CalledOnValidThread()); return signaled_; } // Causes is_signaled() to return true and all tasks to be posted to their // corresponding task runners in the FIFO order. Note that tasks posted to // different SingleThreadTaskRunners may still execute in arbitrary order. // This method must only be called once. void Signal(); // Scheduled |task| to be called on |runner| after is_signaled() // becomes true. If called with |delay|, then the task will happen // (roughly) |delay| after is_signaled(), *not* |delay| after the // post. Inside |task|, if this OneShotEvent is still alive, // CHECK(is_signaled()) will never fail (which implies that // OneShotEvent::Reset() doesn't exist). // // If |*this| is destroyed before being released, none of these // tasks will be executed. // // Tasks are posted in FIFO order, however, tasks posted to different // SingleThreadTaskRunners may still execute in an arbitrary order. Tasks will // never be called on the current thread before this function returns. Beware // that there's no simple way to wait for all tasks on a OneShotEvent to // complete, so it's almost never safe to use base::Unretained() when creating // one. void Post(const Location& from_here, OnceClosure task, scoped_refptr runner = ThreadTaskRunnerHandle::Get()) const; void PostDelayed(const Location& from_here, OnceClosure task, const TimeDelta& delay) const; private: struct TaskInfo; void PostImpl(const Location& from_here, OnceClosure task, scoped_refptr runner, const TimeDelta& delay) const; ThreadChecker thread_checker_; bool signaled_; // The task list is mutable because it's not part of the logical // state of the object. This lets us return const references to the // OneShotEvent to clients that just want to run tasks through it // without worrying that they'll signal the event. // // Optimization note: We could reduce the size of this class to a // single pointer by storing |signaled_| in the low bit of a // pointer, and storing the size and capacity of the array (if any) // on the far end of the pointer. mutable std::vector tasks_; }; } // namespace base #endif // BASE_ONE_SHOT_EVENT_H_