| // Copyright 2013 The Chromium Authors |
| // 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 <vector> |
| |
| #include "base/base_export.h" |
| #include "base/check.h" |
| #include "base/functional/callback_forward.h" |
| #include "base/memory/weak_ptr.h" |
| #include "base/task/single_thread_task_runner.h" |
| #include "base/threading/thread_checker.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<SingleThreadTaskRunner> runner = |
| SingleThreadTaskRunner::GetCurrentDefault()) 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<SingleThreadTaskRunner> 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<TaskInfo> tasks_; |
| }; |
| |
| } // namespace base |
| |
| #endif // BASE_ONE_SHOT_EVENT_H_ |