blob: bc2b01e1615cac18b1527def23dc7c1e8c9ff177 [file]
// Copyright 2016 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 MOJO_SERVICES_MEDIA_FACTORY_EVENT_H_
#define MOJO_SERVICES_MEDIA_FACTORY_EVENT_H_
#include <memory>
#include <vector>
#include "mojo/public/cpp/bindings/callback.h"
namespace mojo {
namespace media {
class EventImpl;
// The Event class provides a facility for executing code as the consequence of
// some occurrence. This can be useful for building state machines and otherwise
// dealing with asynchronous operations.
//
// Event is not a thread-safe class and has no ability to make a thread wait
// or to execute code on a particular thread.
//
// An Event consists of a shared pointer to an implementation object, so copies
// of an Event share state, and all copies of an Event must be deleted before
// that shared state is deleted.
//
// Events rely heavily on lambdas and containers, so they shouln't be used in
// enormous numbers.
//
// An Event (and its copies) can be in one of three states: an initial state,
// an occurred state or a cancelled state. The only state transitions that are
// allowed are from the initial state to one of the other two states. That is,
// an Event may either occur or be cancelled, but not both, and once it occurs
// or is cancelled, it can never occur or be cancelled again.
//
// Code can be executed when an event occurs:
//
// Event event = ...
// event.When([]() {
// // Do something...
// });
//
// The behavior of the When method depends on the event's state. In initial
// state, the consequence is added to a list to be executed when the event
// occurs. In occurred state, When executes the consequence immediately (before
// When returns). In cancelled state, When does nothing.
//
// An Event occurs when its Occur (or Run) method is invoked and the Event is
// in the initial state. All registered consequences of the Event are executed
// during the call to Occur in the order they were added. Subsequent calls to
// Occur, Run or Cancel are ignored.
//
// An Event is cancelled when its Cancel method is invoked and the Event is
// in the initial state. All registered consequences of the Event are destroyed
// during the call to Cancel. Subsequent calls to Occur, Run or Cancel are
// ignored.
//
// Events can be combined using the static methods First and All. First returns
// an Event that occurs when any of the subordinate events occurs, at which
// time, all the subordinates are cancelled. All returns an Event that occurs
// when all of the subordinate events have occurred. First is useful for
// implementing states in which multiple events may occur, each with its own
// consequence. All is useful when multiple operations are performed in
// parallel, and the caller needs to take action when all the operations are
// complete.
//
// As mentioned earlier, Event is really shared pointer to state shared between
// copies of the Event. The shared state's lifetime ends when the last copy of
// the associated Event is deleted. Callers must take care to make sure that
// Events live long enough to do the work for which they are intended.
//
// In many cases, lifetime management more or less takes care of itself, because
// the mechanism that eventually calls Occur or Cancel (usually a lambda) holds
// on to a copy of the Event. This is not the case for Events produced by First
// and All. A First or All event isn't kept alive by its subordinates so it's
// important to keep a copy of such an Event until its done its job.
//
// First and All Events hold a reference to their subordinates so long as those
// subordinates remain in their initial states. Both First and All events cancel
// all of their subordinates in their destructors to ensure that the
// subordinates don't call into a deleted parent Event.
class Event {
public:
// Creates a new Event.
static Event Create();
// Creates a Event that occurs when any of the precursors occurs. When any
// of the precursors occurs, all the other precursors are cancelled and the
// returned Event occurs. If any of the precursors has already occurred when
// this method is called, all the precursors are cancelled immediately and the
// return Event has already occurred when the method call completes. If the
// precursors parameter is empty, the returned event never occurs.
static Event First(const std::vector<Event>& precursors);
// Creates a Event that occurs when the precursors have all occurred. If all
// of the precursors have already occurred when this method is called (or
// precursors is empty), the returned Event has already occurred when the
// method call completes.
static Event All(const std::vector<Event>& precursors);
// Creates a null Event.
Event();
// Creates an Event that references the same underlying object as other.
Event(const Event& other);
~Event();
// Changes this Event to have the same underlying object as other.
const Event& operator=(const Event& other) {
impl_ = other.impl_;
return *this;
}
// Makes this Event null.
const Event& operator=(std::nullptr_t) {
impl_.reset();
return *this;
}
// Determines whether this Event is non-null.
explicit operator bool() const { return static_cast<bool>(impl_); }
// Executes the consequence when this Event occurs. If this Event hasn't
// occurred or been cancelled when this method is called, a copy of the
// consequence is held until this Event occurs or is cancelled. If this Event
// has occurred when this method is called, the consequence is executed
// immediately and no copy of the consequence is held. If this Event is
// cancelled when this method is called, the method does nothing.
// Returns this.
const Event& When(const std::function<void()>& consequence) const;
// Determines if this Event has occurred due to a past call to Occur or Run.
bool occurred() const;
// Determines if this Event has been cancelled.
bool cancelled() const;
// If this Event hasn't yet occurred or been cancelled, this method makes
// this Event occur, executing and deleting all its consequences. Otherwise,
// does nothing.
void Occur() const;
// If this Event hasn't yet occurred or been cancelled, this method cancels
// this Event and deletes all its consequences. Otherwise, does nothing.
void Cancel() const;
// Calls Occur. This method makes an Event convertible to
// mojo::Callback<void()>.
void Run() const { Occur(); }
private:
explicit Event(const std::shared_ptr<EventImpl>& impl);
std::shared_ptr<EventImpl> impl_;
};
} // namespace media
} // namespace mojo
#endif // MOJO_SERVICES_MEDIA_FACTORY_EVENT_H_