190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// found in the LICENSE file.
490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#ifndef EXTENSIONS_COMMON_ONE_SHOT_EVENT_H_
690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#define EXTENSIONS_COMMON_ONE_SHOT_EVENT_H_
790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include <vector>
990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
1090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "base/callback_forward.h"
1190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "base/logging.h"
1290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "base/memory/ref_counted.h"
1390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "base/memory/weak_ptr.h"
1490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "base/threading/thread_checker.h"
1590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
1690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)namespace base {
1790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)class TaskRunner;
18e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdochclass TimeDelta;
1990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
2090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
2190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)namespace tracked_objects {
2290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)class Location;
2390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
2490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
2590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)namespace extensions {
2690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
2790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// This class represents an event that's expected to happen once.  It
2890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// allows clients to guarantee that code is run after the OneShotEvent
2990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// is signaled.  If the OneShotEvent is destroyed before it's
3090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// signaled, the delayed closures are destroyed without being run.
3190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)//
3290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// This class is similar to a WaitableEvent combined with several
3390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// WaitableEventWatchers, but using it is simpler.
3490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)//
3590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// This class is not thread-safe, and must be used from a single thread.
3690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)class OneShotEvent {
3790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) public:
3890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  OneShotEvent();
395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Use the following constructor to create an already signaled event. This is
405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // useful if you construct the event on a different thread from where it is
415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // used, in which case it is not possible to call Signal() just after
425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // construction.
435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  explicit OneShotEvent(bool signaled);
4490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  ~OneShotEvent();
4590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
4690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // True if Signal has been called.  This function is mostly for
4790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // migrating old code; usually calling Post() unconditionally will
4890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // result in more readable code.
4990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  bool is_signaled() const {
5090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    DCHECK(thread_checker_.CalledOnValidThread());
5190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return signaled_;
5290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
5390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
5490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Causes is_signaled() to return true and all queued tasks to be
5590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // run in an arbitrary order.  This method must only be called once.
5690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  void Signal();
5790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
5890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Scheduled |task| to be called on |runner| after is_signaled()
59e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  // becomes true. If called with |delay|, then the task will happen
60e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  // (roughly) |delay| after is_signaled(), *not* |delay| after the
61e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  // post. Inside |task|, if this OneShotEvent is still alive,
62e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  // CHECK(is_signaled()) will never fail (which implies that
6390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // OneShotEvent::Reset() doesn't exist).
6490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  //
6590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // If |*this| is destroyed before being released, none of these
6690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // tasks will be executed.
6790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  //
6890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Omitting the |runner| argument indicates that |task| should run
6990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // on MessageLoopProxy::current().
7090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  //
7190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Tasks may be run in an arbitrary order, not just FIFO.  Tasks
7290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // will never be called on the current thread before this function
7390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // returns.  Beware that there's no simple way to wait for all tasks
7490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // on a OneShotEvent to complete, so it's almost never safe to use
7590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // base::Unretained() when creating one.
7690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  //
7790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Const because Post() doesn't modify the logical state of this
7890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // object (which is just the is_signaled() bit).
7990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  void Post(const tracked_objects::Location& from_here,
8090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)            const base::Closure& task) const;
8190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  void Post(const tracked_objects::Location& from_here,
8290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)            const base::Closure& task,
8390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)            const scoped_refptr<base::TaskRunner>& runner) const;
84e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  void PostDelayed(const tracked_objects::Location& from_here,
85e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                   const base::Closure& task,
86e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                   const base::TimeDelta& delay) const;
8790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
8890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) private:
8990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  struct TaskInfo;
9090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
91e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  void PostImpl(const tracked_objects::Location& from_here,
92e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                const base::Closure& task,
93e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                const scoped_refptr<base::TaskRunner>& runner,
94e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                const base::TimeDelta& delay) const;
95e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
9690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  base::ThreadChecker thread_checker_;
9790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
9890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  bool signaled_;
9990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
10090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // The task list is mutable because it's not part of the logical
10190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // state of the object.  This lets us return const references to the
10290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // OneShotEvent to clients that just want to run tasks through it
10390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // without worrying that they'll signal the event.
10490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  //
10590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Optimization note: We could reduce the size of this class to a
10690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // single pointer by storing |signaled_| in the low bit of a
10790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // pointer, and storing the size and capacity of the array (if any)
10890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // on the far end of the pointer.
10990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  mutable std::vector<TaskInfo> tasks_;
11090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)};
11190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
11290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}  // namespace extensions
11390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
11490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#endif  // EXTENSIONS_COMMON_ONE_SHOT_EVENT_H_
115