IEventDispatcher#

Fully qualified name: carb::eventdispatcher::IEventDispatcher

Defined in carb/eventdispatcher/IEventDispatcher.h

struct IEventDispatcher#

Interface for carb.eventdispatcher.plugin.

Public Functions

template<class Invocable, class ...Args>
ObserverGuard observeEvent(
RStringKey observerName,
Order order,
RString eventName,
Invocable &&invocable,
Args&&... filterArgs,
)#

Registers an observer with the Event Dispatcher system.

An observer is an invocable object (function, functor, lambda, etc.) that is called whenever dispatchEvent() is called. The observers are invoked in the thread that calls dispatchEvent(), and multiple threads could be calling dispatchEvent() simultaneously, so observers must be thread-safe unless the application can ensure synchronization around dispatchEvent() calls.

The invocable callback will always see the eventName that matches the eventName that observeEvent was called with, even if the event was dispatched as an alias. The same invocable callback can observe multiple events; different calls may be differentiated with the Event::eventName property.

Observers can pass zero or any number of filterArgs parameters. These filterArgs cause an observer to only be invoked for a dispatchEvent() call that contains at least the same values. For instance, having a filter pair for key “WindowID” with a specific value will only cause the observer to be called if dispatchEvent() is given the same value as a “WindowID” parameter.

Observers can be added inside of an observer notification (i.e. during a call to dispatchEvent()), however these new observers will not be called for the currently dispatching event. A subsequent recursive call to dispatchEvent() will also call the new observer. The new observer will be available to all other threads potentially before observeEvent() returns. WARNING: this means that the return value may not be available before the observer’s invocable is called. If this is an issue, it is recommended to acquire a mutex before the call to observeEvent() and release it after the ObserverGuard is returned. Any access to the ObserverGuard should acquire the same mutex.

Thread Safety

Safe to perform while any thread is performing any operation against IEventDispatcher. NOTE: the invocable callback can be invoked simultaneously by multiple threads if the event is dispatched simultaneously from multiple threads.

Parameters:
  • observerName – A name for this observer, used in profiling and debugging.

  • order – A value determining call order. Observers with lower order values are called earlier. Observers with the same order value will be called in the order they are registered, regardless of filter arguments.

  • eventName – The name of the event to observe.

  • invocable – An object that is invoked when an event matching the eventName and filterArgs is dispatched. The object must be callable as void(const Event&).

  • filterArgs – Zero or more arguments that filter observer invocations. Each argument must be of type std::pair<RStringKey, T> where the first parameter is the key and the second is the value. The value must be of a type understood by a variant::Translator specialization.

Returns:

An ObserverGuard representing the lifetime of the observer. When the ObserverGuard is reset or destroyed, the observer is unregistered as with stopObserving().

template<class Invocable, class InIter>
ObserverGuard observeEventIter(
RStringKey observerName,
Order order,
RString eventName,
Invocable &&invocable,
InIter begin,
InIter end,
)#

Registers an observer with the Event Dispatcher system.

An observer is an invocable object (function, functor, lambda, etc.) that is called whenever dispatchEvent() is called. The observers are invoked in the thread that calls dispatchEvent(), and multiple threads could be calling dispatchEvent() simultaneously, so observers must be thread-safe unless the application can ensure synchronization around dispatchEvent() calls.

The invocable callback will always see the eventName that matches the eventName that observeEventIter was called with, even if the event was dispatched as an alias. The same invocable callback can observe multiple events; different calls may be differentiated with the Event::eventName property.

Observers can pass zero or any number of filterArgs parameters. These filterArgs cause an observer to only be invoked for a dispatchEvent() call that contains at least the same values. For instance, having a filter pair for key “WindowID” with a specific value will only cause the observer to be called if dispatchEvent() is given the same value as a “WindowID” parameter.

Observers can be added inside of an observer notification (i.e. during a call to dispatchEvent()), however these new observers will not be called for the currently dispatching event. A subsequent recursive call to dispatchEvent() will also call the new observer. The new observer will be available to all other threads potentially before observeEventIter() returns. WARNING: this means that the return value may not be available before the observer’s invocable is called. If this is an issue, it is recommended to acquire a mutex before the call to observeEventIter() and release it after the ObserverGuard is returned. Any access to the ObserverGuard should acquire the same mutex.

Thread Safety

Safe to perform while any thread is performing any operation against IEventDispatcher. NOTE: the invocable callback can be invoked simultaneously by multiple threads if the event is dispatched simultaneously from multiple threads.

Parameters:
  • observerName – A name for this observer, used in profiling and debugging.

  • order – A value determining call order. Observers with lower order values are called earlier. Observers with the same order value will be called in the order they are registered, regardless of filter arguments.

  • eventName – The name of the event to observe.

  • invocable – An object that is invoked when an event matching the eventName and filterArgs is dispatched. The object must be callable as void(const Event&).

  • begin – An InputIterator representing the start of the filter parameters.

  • end – A past-the-end InputIterator representing the end of the filter parameters.

Template Parameters:

InIter – An InputIterator that is forward-iterable and resolves to a NamedVariant when dereferenced.

Returns:

An ObserverGuard representing the lifetime of the observer. When the ObserverGuard is reset or destroyed, the observer is unregistered as with stopObserving().

template<class R, class Invocable>
inline ObserverGuard observeEventRange(
RStringKey observerName,
Order order,
RString eventName,
Invocable &&invocable,
R &&range,
)#

Registers an observer with the Event Dispatcher system.

An observer is an invocable object (function, functor, lambda, etc.) that is called whenever dispatchEvent() is called. The observers are invoked in the thread that calls dispatchEvent(), and multiple threads could be calling dispatchEvent() simultaneously, so observers must be thread-safe unless the application can ensure synchronization around dispatchEvent() calls.

The invocable callback will always see the eventName that matches the eventName that observeEventRange was called with, even if the event was dispatched as an alias. The same invocable callback can observe multiple events; different calls may be differentiated with the Event::eventName property.

Observers can pass zero or any number of filterArgs parameters. These filterArgs cause an observer to only be invoked for a dispatchEvent() call that contains at least the same values. For instance, having a filter pair for key “WindowID” with a specific value will only cause the observer to be called if dispatchEvent() is given the same value as a “WindowID” parameter.

Observers can be added inside of an observer notification (i.e. during a call to dispatchEvent()), however these new observers will not be called for the currently dispatching event. A subsequent recursive call to dispatchEvent() will also call the new observer. The new observer will be available to all other threads potentially before observeEventRange() returns. WARNING: this means that the return value may not be available before the observer’s invocable is called. If this is an issue, it is recommended to acquire a mutex before the call to observeEventRange() and release it after the ObserverGuard is returned. Any access to the ObserverGuard should acquire the same mutex.

Thread Safety

Safe to perform while any thread is performing any operation against IEventDispatcher. NOTE: the invocable callback can be invoked simultaneously by multiple threads if the event is dispatched simultaneously from multiple threads.

Parameters:
  • observerName – A name for this observer, used in profiling and debugging.

  • order – A value determining call order. Observers with lower order values are called earlier. Observers with the same order value will be called in the order they are registered, regardless of filter arguments.

  • eventName – The name of the event to observe.

  • invocable – An object that is invoked when an event matching the eventName and filterArgs is dispatched. The object must be callable as void(const Event&).

  • range – The range to use as message parameters. See explanation of the R type above.

Template Parameters:

R – A range type. Since this implementation is for pre-C++20 and C++20 ranges are not available, this is an approximation: this type must work with std::begin() and std::end() to produce an iterator type that conforms to InputIterator. The iterator must resolve to a std::pair<RStringKey, T> when dereferenced, where the first parameter is the key and the second parameter is the value and must be a type understood by a variant::Translator specialization. Each key must be unique, otherwise it is not defined which non-unique value is obtained when the key is queried.

Returns:

An ObserverGuard representing the lifetime of the observer. When the ObserverGuard is reset or destroyed, the observer is unregistered as with stopObserving().

template<class ...Args>
bool hasObservers(
RString eventName,
Args&&... filterArgs,
)#

Queries the Event Dispatcher whether any observers are listening to a specific event signature.

Emulates a call to dispatchEvent() (without actually calling any observers) and returns true if any observers would be called.

Thread Safety

Safe to perform while any thread is performing any operation against IEventDispatcher.

Parameters:
  • eventName – The name of the event to query.

  • filterArgs – Zero or more key/value pairs that would be used for observer filtering as in a call to dispatchEvent(). Each argument must be of type std::pair<RStringKey, T> where the first parameter is the key and the second is the value. The value must be of a type understood by a variant::Translator specialization.

Returns:

true if at least one observer would be called if the same arguments were passed to dispatchEvent(); false otherwise.

template<class InIter>
bool hasObserversIter(
RString eventName,
InIter begin,
InIter end,
)#

Queries the Event Dispatcher whether any observers are listening to a specific event signature.

Emulates a call to dispatchEvent() (without actually calling any observers) and returns true if any observers would be called.

Thread Safety

Safe to perform while any thread is performing any operation against IEventDispatcher.

Template Parameters:

InIter – An InputIterator that is forward-iterable and resolves to a NamedVariant when dereferenced. The entries are used for observer filtering.

Parameters:
  • eventName – The name of the event to query.

  • begin – An InputIterator representing the start of the event key/value pairs.

  • end – A past-the-end InputIterator representing the end of the event key/value pairs.

Returns:

true if at least one observer would be called if the same arguments were passed to dispatchEvent(); false otherwise.

template<class R>
inline bool hasObserversRange(
RString eventName,
R &&range,
)#

Queries the Event Dispatcher whether any observers are listening to a specific event signature.

Emulates a call to dispatchEvent() (without actually calling any observers) and returns true if any observers would be called.

Thread Safety

Safe to perform while any thread is performing any operation against IEventDispatcher.

Template Parameters:

R – A range type. Since this implementation is for pre-C++20 and C++20 ranges are not available, this is an approximation: this type must work with std::begin() and std::end() to produce an iterator type that conforms to InputIterator. The iterator must resolve to a std::pair<RStringKey, T> when dereferenced, where the first parameter is the key and the second parameter is the value and must be a type understood by a variant::Translator specialization. Each key must be unique, otherwise it is not defined which non-unique value is obtained when the key is queried.

Parameters:
  • eventName – The name of the event to query.

  • range – The range to use as observer parameters. See explanation of the R type above.

Returns:

true if at least one observer would be called if the same arguments were passed to dispatchEvent(); false otherwise.

size_t dispatchEvent(
const Event &event,
RString *newEventName = nullptr,
)#

Re-dispatch an Event potentially as a different eventName.

This can also be combined with a IMessageQueue to dispatch queued events.

Thread Safety

Safe to perform while any thread is performing any operation against IEventDispatcher.

Warning

While it is safe to recursively dispatch events, this call can lead to endless recursion if the event name is unchanged.

Parameters:
  • event – The event to re-dispatch.

  • newEventName – The event name to override Event::eventName from event. Only used if not nullptr.

Returns:

The count of observers that were called. Recursive dispatch calls are not included.

template<class ...Args>
size_t dispatchEvent(
RString eventName,
Args&&... payload,
)#

Dispatches an event and immediately calls all observers that would observe this particular event.

Finds and calls all observers (in the current thread) that observe the given event signature.

It is safe to recursively dispatch events (i.e. call dispatchEvent() from a called observer), but care must be taken to avoid endless recursion. See the rules in observeEvent() for observers added during a dispatchEvent() call.

Thread Safety

Safe to perform while any thread is performing any operation against IEventDispatcher.

Parameters:
  • eventName – The name of the event to dispatch.

  • payload – Zero or more key/value pairs that are used as the event payload and may be queried by observers or used to filter observers. Each argument must be of type std::pair<RStringKey, T> where the first parameter is the key and the second is the value. The value must be of a type understood by a variant::Translator specialization.

Returns:

The count of observers that were called. Recursive dispatch calls are not included.

template<class InIter>
size_t dispatchEventIter(
RString eventName,
InIter begin,
InIter end,
)#

Dispatches an event and immediately calls all observers that would observe this particular event.

Finds and calls all observers (in the current thread) that observe the given event signature.

It is safe to recursively dispatch events (i.e. call dispatchEvent() from a called observer), but care must be taken to avoid endless recursion. See the rules in observeEvent() for observers added during a dispatchEvent() call.

Thread Safety

Safe to perform while any thread is performing any operation against IEventDispatcher.

Template Parameters:

InIter – An InputIterator that is forward-iterable and resolves to a NamedVariant when dereferenced. The entries are used as the event payload and may be queried by observers or used to filter observers.

Parameters:
  • eventName – The name of the event to dispatch.

  • begin – An InputIterator representing the start of the event key/value pairs.

  • end – A past-the-end InputIterator representing the end of the event key/value pairs.

Returns:

The count of observers that were called. Recursive dispatch calls are not included.

template<class R>
inline size_t dispatchEventRange(
RString eventName,
R &&range,
)#

Dispatches an event and immediately calls all observers that would observe this particular event.

Finds and calls all observers (in the current thread) that observe the given event signature.

It is safe to recursively dispatch events (i.e. call dispatchEvent() from a called observer), but care must be taken to avoid endless recursion. See the rules in observeEvent() for observers added during a dispatchEvent() call.

Thread Safety

Safe to perform while any thread is performing any operation against IEventDispatcher.

Template Parameters:

R – A range type. Since this implementation is for pre-C++20 and C++20 ranges are not available, this is an approximation: this type must work with std::begin() and std::end() to produce an iterator type that conforms to InputIterator. The iterator must resolve to a std::pair<RStringKey, T> when dereferenced, where the first parameter is the key and the second parameter is the value and must be a type understood by a variant::Translator specialization. Each key must be unique, otherwise it is not defined which non-unique value is obtained when the key is queried.

Parameters:
  • eventName – The name of the event to dispatch.

  • range – The range to use for key/value pairs. See explanation of the R type above.

Returns:

The count of observers that were called. Recursive dispatch calls are not included.

Public Members

bool (*stopObserving)(Observer ob)#

Stops the given observer.

Safe to perform while dispatching.

Since observers can be in use by this thread or any thread, this function is carefully synchronized with all other IEventDispatcher operations.

  • During stopObserving(), further calls to the observer are prevented, even if other threads are currently dispatching an event that would be observed by the observer in question.

  • If any other thread is currently calling the observer in question, stopObserving() will wait until all other threads have left the observer function.

  • If the observer function is not in the callstack of the current thread, the cleanup function provided to internalObserveEvent() is called and any variant::Variant objects captured to filter events are destroyed.

  • If the observer function is in the callstack of the current thread, stopObserving() will return without waiting, without calling the cleanup function and without destroying variant::Variant objects. Instead, this cleanup will be performed when the dispatchEvent() call in the current thread finishes.

Except when the observer function is in the callstack of the current thread, the following guarantee is made: when stopObserving() returns, the observer function will no longer be called, all calls to it have completed, and the Invocable and any filter arguments passed to observeEvent() (or similar) have been destroyed.

Thread Safety

Safe to perform while any thread is performing any operation against IEventDispatcher.

Warning

This function must be called exactly once per Observer created by observeEvent(). The ObserverGuard calls this function automatically upon destruction or by ObserverGuard::reset().

Param ob:

The Observer to stop.

Return:

true if the Observer was found and stopped; false otherwise.

bool (*isDispatching)(bool currentThread)#

Queries to see if the system is currently dispatching an event.

Thread Safety

Safe to perform while any thread is performing any operation against IEventDispatcher.

Param currentThread:

If false, checks to see if any thread is currently dispatching. However, the return value should be used for debugging purposes only as it is a transient value and could be stale by the time it is read by the application. If true, checks to see if the current thread is dispatching (that is, the callstack includes a call to dispatchEvent()).

Return:

true if any thread or the current thread is dispatching based on the value of currentThread; false otherwise.

bool (*getObserverName)(Observer ob, RStringKey &nameOut)#

Retrieves the name of an observer.

Thread Safety

Safe to perform while any thread is performing any operation against IEventDispatcher.

Param ob:

The observer to query, typically accessed from ObserverGuard::get.

Param nameOut:

Receives the name of the observer, originally passed to observeEvent or similar.

Return:

true if the observer was valid and the name was retrieved; false otherwise.

bool (*getObserverOrder)(Observer ob, Order &orderOut)#

Gets the ‘order’ value of an observer.

Thread Safety

Safe to perform while any thread is performing any operation against IEventDispatcher.

Param ob:

The observer to query, typically accessed from ObserverGuard::get.

Param orderOut:

Receives the order value of the observer.

Return:

true if the observer was valid and the order was retrieved; false otherwise.

bool (*setObserverOrder)(Observer ob, Order newOrder)#

Changes the ‘order’ value of an observer.

Thread Safety

Safe to perform while any thread is performing any operation against IEventDispatcher.

Param ob:

The observer to change, typically accessed from ObserverGuard::get.

Param newOrder:

The new order value to set.

Return:

true if the observer was valid and the order was set; false otherwise.

bool (*getObserverEnabled)(Observer ob, bool &enabledOut)#

Gets the ‘enabled’ state of an observer.

Thread Safety

Safe to perform while any thread is performing any operation against IEventDispatcher.

Param ob:

The observer to query, typically accessed from ObserverGuard::get.

Param enabledOut:

Receives the enabled state of the observer.

Return:

true if the observer was valid and the enabled state was retrieved; false otherwise.

bool (*setObserverEnabled)(Observer ob, bool enabled)#

Changes the ‘enabled’ state of an observer.

Thread Safety

Safe to perform while any thread is performing any operation against IEventDispatcher.

Param ob:

The observer to query, typically accessed from ObserverGuard::get.

Param enabled:

The new enabled state to set.

Return:

true if the observer was valid and the enabled state was set; false otherwise.

size_t (*removeAllObserversFor)(RString eventName)#

Removes all observers for the given event.

Typically a system might do this when it will never send a particular event again, such at shutdown. After calling this, hasObservers() for eventName will return false. Observers with filter arguments for eventName will also be removed. Observers are removed in the reverse of the registration order. ObserverGuard destruction may still occur but will not have an effect. Calls to stopObserving() for observers of this event will return false.

Thread Safety

It is safe to call this from multiple threads, and safe to call from event handlers.

Warning

This will forcibly remove all observers, which will receive no notification that they have been removed.

Warning

Unlike stopObserving(), this function does not have a strong guarantee to wait for the event function to be complete and the observer to be cleaned up before returning. If this is problematic, explicitly call stopObserving() for the observer in question.

Param eventName:

The event to remove all observers for.

Return:

The number of observers that were removed.

bool (*addEventAlias)(RString target, RString alias)#

Adds an alias that can be used to observe and dispatch as a different event.

Event aliases are a powerful tool. An alias target may have as many aliases as necessary, but an alias may not have any aliases of its own. Similarly, an alias target may not function as an alias for any other alias target.

Thus an alias target is considered a primary event, and any aliases that it is known by can also be used to dispatch or receive events.

Dispatching to an alias acts the same as dispatching to an alias target directly: Any observers of any aliases for that alias target will observe the event, as well as the alias target itself. However, the Event::eventName property will be the same as the alias they’re observing, not the alias target and potentially not even the alias that was dispatched. See observeEvent() for more information.

Aliases can be removed with removeEventAlias() or removeAllEventAliasesFor().

While it is possible to add or remove an alias from an observer callback, it will not affect the current event dispatch.

Thread Safety

Safe to perform while any thread is performing any operation against IEventDispatcher.

Param target:

The target event to create an alias for.

Param alias:

The alias that will refer to target.

Retval true:

A new alias was created.

Retval false:

target and alias are the same, target or alias are already used as aliases or targets respectively, or alias already exists as an alias of target.

bool (*removeEventAlias)(RString target, RString alias)#

Removes a previously-added alias.

Aliases are added with addEventAlias().

Once alias is removed as an alias, the alias event can be added as an alias for a different target, or used as a target itself. Similarly, once target has all aliases removed, it can be used as an alias or as a target in the future.

While it is possible to add or remove an alias from an observer callback, it will not affect the current event dispatch.

Thread Safety

Safe to perform while any thread is performing any operation against IEventDispatcher.

Param target:

The target event to remove an alias from.

Param alias:

The alias to remove from target.

Retval true:

An existing alias was found and removed.

Retval false:

target and alias are the same; target is not an event target, or alias is not an event alias; or target does not have an alias alias.

size_t (*removeAllEventAliasesFor)(RString target)#

Removes all aliases for a given event target.

Aliases are added with addEventAlias().

Once an alias is removed from a target, any former alias event can be added as an alias for a different target, or used as a target itself. Similarly, once target has all aliases removed, it can be used as an alias or as a target in the future.

While it is possible to add or remove an alias from an observer callback, it will not affect the current event dispatch.

Thread Safety

Safe to perform while any thread is performing any operation against IEventDispatcher.

Param target:

The target event to remove all aliases from.

Return:

The number of aliases removed. A value of 0 indicates that target is not actually an event target or currently has no aliases.

Public Static Functions

static inline constexpr carb::InterfaceDesc getInterfaceDesc(
) noexcept#

Returns information about this interface.

Auto-generated by CARB_PLUGIN_INTERFACE() or CARB_PLUGIN_INTERFACE_EX.

Returns:

The carb::InterfaceDesc struct with information about this interface.

static inline constexpr carb::InterfaceDesc getLatestInterfaceDesc(
) noexcept#

Returns information about the latest version of this interface.

Auto-generated by CARB_PLUGIN_INTERFACE() or CARB_PLUGIN_INTERFACE_EX.

Returns:

The carb::InterfaceDesc struct with information about the latest version of this interface.