Home | History | Annotate | Download | only in common
      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.
     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