Dispatcher
The dispatcher is responsible for collecting emitted events and calling listeners with the respective events. In Obscura no particular base class is required for creating a listener. All you need is a class that implements the defined callbacks. These callbacks are defined via Event Definitions.
Configurable Dispatcher
-
template<EventDefinitionConcept Definition, EventDefinitionConcept... AdditionalDefinitions>
class ConfigurableDispatcher : public obscura::DispatcherBase<Definition> The class provides an implementation for a dispatcher. It must be configured to be compatible with the event_system that are supposed to be dispatched. For that you must pass event definitions to the template parameters list. A
Definitionmust satisfy the EventDefinitionConcept concept.- Template Parameters:
Definition – Class that satisfies EventDefinitionConcept concept
AdditionalDefinitions – Classes that satisfies EventDefinitionConcept concept
Subclassed by obscura::LoopBase< Dispatcher >
Public Functions
-
void dispatch()
Dispatches all enqueued events to the respective listeners.
-
template<class Listener, bool hasFoundMatchedConcept = false>
void registerListener(Listener &listener, const std::string &listenerGroup = std::string{DispatcherBase<Definition>::DEFAULT_LISTENER_GROUP}) Registers a listener with the dispatcher. The callbacks of the listener will be invoked when dispatch() is called.
- Template Parameters:
Listener – Type of the listener
hasFoundMatchedConcept – Template parameter that indicates if the listener fits any of the configured definitions. The parameter is false by default and should not be manually changed.
- Parameters:
listener – The listener that is registered with the dispatcher. Can be any object as long as it contains at least one of the callback defined via the event definitions. If the listener is not matching any event definition a compile error will be thrown. Each listener can have arbitrarily many supported callbacks.
listenerGroup – The listener group the listener should be registered for. Events can be dispatched to specific listener groups. The default listener listenerGroup is named “default”.
-
template<class Listener>
void unregisterListener(const Listener &listener, const std::string &listenerGroup = std::string{DispatcherBase<Definition>::DEFAULT_LISTENER_GROUP}) Removes a listener from the register of the dispatcher, i.e., event_system will not be dispatched to the respective listener anymore. Throws an KeyError when the listener could not be removed for the given group.
- Template Parameters:
Listener – Type of the listener.
- Parameters:
listener – Reference to the listener.
-
template<class Listener>
auto isListenerRegistered(const Listener &listener, const std::string &listenerGroup = std::string{DispatcherBase<Definition>::DEFAULT_LISTENER_GROUP}) -> bool
Dispatcher Base Class
Every obscura::ConfigurableDispatcher inherits from the following base class.
-
template<EventDefinitionConcept Definition, class ListenerIdType = uintptr_t>
class DispatcherBase Subclassed by obscura::ConfigurableDispatcher< Definition, AdditionalDefinitions >, obscura::ConfigurableDispatcher< Definition >
Public Functions
-
void enqueue(typename Definition::Event &&event, const std::string &listenerGroup = std::string{DEFAULT_LISTENER_GROUP})
Enqueue an event in the dispatcher. The event is passed forward to the respective listener once dispatch() is called.
- Parameters:
event – Can be any event, the dispatcher is configured for. The function only takes event_system that are defined for the dispatcher.
listenerGroup – The group of listeners the event should be dispatched to.
-
void enqueue(const typename Definition::Event &event, const std::string &listenerGroup = std::string{DEFAULT_LISTENER_GROUP})
Same as enqueue(Definition::Event&&, const std::string&) but the function takes a const reference of the event.
- Parameters:
event – Can be any event, the dispatcher is configured for. The function only takes event_system that are defined for the dispatcher.
listenerGroup – The group of listeners the event should be dispatched to.
-
void enqueueForAllGroups(typename Definition::Event &&event)
-
void enqueueForAllGroups(const typename Definition::Event &event)
-
inline auto hasListenerForEvent(const typename Definition::Event&, const std::string &listenerGroup = std::string{DEFAULT_LISTENER_GROUP}) -> bool
Checks whether a listener was appended that a certain event can be dispatched to.
- Parameters:
event – Any event the dispatcher is configured for.
- Returns:
Whether a listener for an event is appended.
Public Static Attributes
-
static constexpr std::string_view DEFAULT_LISTENER_GROUP = {"default"}
-
void enqueue(typename Definition::Event &&event, const std::string &listenerGroup = std::string{DEFAULT_LISTENER_GROUP})
Pre-configured Dispatcher
A predefined dispatcher is available via the following class.
-
using obscura::Dispatcher = ConfigurableDispatcher<TickDefinition, KeyPressedDefinition, MouseMovedDefintion, KeyReleasedDefinition, KeyRepeatedDefinition, WindowClosedDefintion, MouseClickedDefinition, LoopEndDefinition>
The Obscura default dispatcher with all predefined event types pre-configured. Use this class if you have no need to define custom event_system.
Examples
Configure a Custom Dispatcher
#include <obscura/obscura.hxx>
#include <utility>
class CustomEvent: public obscura::Event {
public:
explicit CustomEvent(std::string message)
: obscura::Event(obscura::EventCategory::None, obscura::EventCause::None),
message(std::move(message)) {
}
[[nodiscard]] auto getMessage() const -> const std::string& {
return message;
}
private:
std::string message;
};
template<class Listener>
using CustomEventCallback = CallbackWrapper<Listener, CustomEvent, &Listener::onCustomEvent>;
using CustomEventDefinition = EventDefinition<"CustomEventDefinition", CustomEvent, CustomEventCallback>;
class CustomListener {
public:
void onCustomEvent(const CustomEvent& event) { // NOLINT(readability-convert-member-functions-to-static)
// The function cannot be static because it needs to be registered as a callback.
obscura::logInfo("{}", event.getMessage());
}
};
auto main() -> int {
try {
auto event = CustomEvent("I traveled through the dispatcher!");
auto listener = CustomListener();
// All event definitions that are used in a project should be passed to the
// ConfigurableDispatcher template. Here, we only need one event definition.
auto dispatcher = obscura::ConfigurableDispatcher<CustomEventDefinition>();
dispatcher.registerListener(listener);
dispatcher.enqueue(event);
obscura::logInfo("Event is in queue but not yet dispatched!");
dispatcher.dispatch();
obscura::logInfo("Event was dispatched!");
} catch (const std::exception& e) {
obscura::logError("Exception caught: {}", e.what());
}
return EXIT_SUCCESS;
}