root/extensions/common/one_shot_event.h

/* [<][>][^][v][top][bottom][index][help] */

INCLUDED FROM


// 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 EXTENSIONS_COMMON_ONE_SHOT_EVENT_H_
#define EXTENSIONS_COMMON_ONE_SHOT_EVENT_H_

#include <vector>

#include "base/callback_forward.h"
#include "base/logging.h"
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
#include "base/threading/thread_checker.h"

namespace base {
class TaskRunner;
class TimeDelta;
}

namespace tracked_objects {
class Location;
}

namespace extensions {

// 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 delayed 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 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 queued tasks to be
  // run in an 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.
  //
  // Omitting the |runner| argument indicates that |task| should run
  // on MessageLoopProxy::current().
  //
  // Tasks may be run in an arbitrary order, not just FIFO.  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.
  //
  // Const because Post() doesn't modify the logical state of this
  // object (which is just the is_signaled() bit).
  void Post(const tracked_objects::Location& from_here,
            const base::Closure& task) const;
  void Post(const tracked_objects::Location& from_here,
            const base::Closure& task,
            const scoped_refptr<base::TaskRunner>& runner) const;
  void PostDelayed(const tracked_objects::Location& from_here,
                   const base::Closure& task,
                   const base::TimeDelta& delay) const;

 private:
  struct TaskInfo;

  void PostImpl(const tracked_objects::Location& from_here,
                const base::Closure& task,
                const scoped_refptr<base::TaskRunner>& runner,
                const base::TimeDelta& delay) const;

  base::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 extensions

#endif  // EXTENSIONS_COMMON_ONE_SHOT_EVENT_H_

/* [<][>][^][v][top][bottom][index][help] */