Timeout and Interval events

This commit is contained in:
2023-11-25 23:57:07 -06:00
parent 687c5c0257
commit eda0b8d639
15 changed files with 418 additions and 10 deletions

View File

@ -0,0 +1,141 @@
// Copyright (c) 2023 Dominic Masters
//
// This software is released under the MIT License.
// https://opensource.org/licenses/MIT
#pragma once
#include "dawnlibs.hpp"
namespace Dawn {
enum class CustomEventResult {
NOTHING,
REMOVE,
INVOKE,
INVOKE_AND_REMOVE
};
template<
typename InternalData,
typename InternalListenerData,
typename ListenerArgument,
typename ...InvokeArgs
>
class CustomEvent {
private:
int32_t nextId = 0;
std::unordered_map<
int32_t,
std::pair<InternalListenerData, std::function<void(InvokeArgs...)>>
> listeners;
protected:
InternalData internalData;
/**
* Custom event filter. Decides whether or not the event should be emitted
* to the listener.
*
* @param listenerData Data for this listener.
* @param args The arguments to pass to the listeners.
* @return The result of the filter.
*/
virtual enum CustomEventResult shouldEmit(
const InternalListenerData &listenerData,
const InvokeArgs... args
) = 0;
/**
* Transform the arguments for listener data when the listener is first
* subscribed.
*
* @param argument The argument to transform.
* @return The transformed argument into an internal data format.
*/
virtual InternalListenerData transformData(
const ListenerArgument &argument
) = 0;
/**
* Transform the data for listener data after the event has been emitted.
*
* @param internalData The internal data to transform.
* @return Updated/Transformed internal data.
*/
virtual InternalListenerData transformDataAfterEmit(
const InternalListenerData &internalData
) {
return internalData;
}
public:
/**
* Emits the event.
* @param args The arguments to pass to the listeners.
*/
void emit(InvokeArgs... args) {
auto copy = listeners;
for(auto &pair : copy) {
// Check emit test.
auto result = this->shouldEmit(
pair.second.first,
args...
);
if(
result == CustomEventResult::INVOKE ||
result == CustomEventResult::INVOKE_AND_REMOVE
) {
pair.second.second(args...);
}
if(
result == CustomEventResult::REMOVE ||
result == CustomEventResult::INVOKE_AND_REMOVE
) {
listeners.erase(pair.first);
continue;
}
if(
result == CustomEventResult::INVOKE ||
result == CustomEventResult::INVOKE_AND_REMOVE
) {
// Update the internal data.
listeners[pair.first].first = transformDataAfterEmit(
pair.second.first
);
}
}
}
/**
* Listens to the event.
*
* @param data Listener data to use.
* @param listener The listener to add.
* @returns A function that can be called to remove the listener.
*/
std::function<void()> listen(
const ListenerArgument &data,
const std::function<void(InvokeArgs...)> listener
) {
int32_t id = nextId++;
auto pair = std::make_pair(
transformData(data),
listener
);
listeners[id] = pair;
return [this, id]() {
listeners.erase(id);
};
}
/**
* Destroys the custom event.
*/
virtual ~CustomEvent() {
listeners.clear();
}
};
}

View File

@ -37,7 +37,9 @@ namespace Dawn {
* @param listener The listener to add.
* @returns A function that can be called to remove the listener.
*/
std::function<void()> listen(const std::function<void(A...)> listener) {
std::function<void()> listen(
const std::function<void(A...)> listener
) {
int32_t id = nextId++;
listeners[id] = listener;
return [this, id]() {
@ -46,8 +48,7 @@ namespace Dawn {
}
/**
* Removes a listener from the event.
* @param id The id of the listener to remove.
* Destroys the event.
*/
virtual ~Event() {
listeners.clear();