98 lines
2.5 KiB
C++
98 lines
2.5 KiB
C++
#include "foundation/event.h"
|
|
|
|
#include <algorithm>
|
|
|
|
namespace pp::foundation {
|
|
|
|
EventDispatcher::EventDispatcher(std::size_t max_subscriptions) noexcept
|
|
: max_subscriptions_(max_subscriptions)
|
|
{
|
|
subscriptions_.reserve(std::min(max_subscriptions_, max_event_subscriptions));
|
|
}
|
|
|
|
std::size_t EventDispatcher::size() const noexcept
|
|
{
|
|
return subscriptions_.size();
|
|
}
|
|
|
|
bool EventDispatcher::empty() const noexcept
|
|
{
|
|
return subscriptions_.empty();
|
|
}
|
|
|
|
std::size_t EventDispatcher::max_subscriptions() const noexcept
|
|
{
|
|
return max_subscriptions_;
|
|
}
|
|
|
|
Result<std::uint64_t> EventDispatcher::subscribe(std::uint32_t type, EventCallback callback, void* user_data)
|
|
{
|
|
if (max_subscriptions_ == 0U || max_subscriptions_ > max_event_subscriptions) {
|
|
return Result<std::uint64_t>::failure(
|
|
Status::out_of_range("event dispatcher capacity is outside the configured range"));
|
|
}
|
|
|
|
if (type == 0U) {
|
|
return Result<std::uint64_t>::failure(Status::invalid_argument("event type must not be zero"));
|
|
}
|
|
|
|
if (callback == nullptr) {
|
|
return Result<std::uint64_t>::failure(Status::invalid_argument("event callback must not be null"));
|
|
}
|
|
|
|
if (subscriptions_.size() >= max_subscriptions_) {
|
|
return Result<std::uint64_t>::failure(Status::out_of_range("event dispatcher is full"));
|
|
}
|
|
|
|
const auto id = next_subscription_id_++;
|
|
subscriptions_.push_back(EventSubscription {
|
|
.id = id,
|
|
.type = type,
|
|
.callback = callback,
|
|
.user_data = user_data,
|
|
});
|
|
|
|
return Result<std::uint64_t>::success(id);
|
|
}
|
|
|
|
Status EventDispatcher::unsubscribe(std::uint64_t subscription_id) noexcept
|
|
{
|
|
const auto found = std::find_if(
|
|
subscriptions_.begin(),
|
|
subscriptions_.end(),
|
|
[subscription_id](const EventSubscription& subscription) {
|
|
return subscription.id == subscription_id;
|
|
});
|
|
|
|
if (found == subscriptions_.end()) {
|
|
return Status::out_of_range("event subscription id was not found");
|
|
}
|
|
|
|
subscriptions_.erase(found);
|
|
return Status::success();
|
|
}
|
|
|
|
std::size_t EventDispatcher::publish(const Event& event) const noexcept
|
|
{
|
|
if (event.type == 0U) {
|
|
return 0;
|
|
}
|
|
|
|
std::size_t delivered = 0;
|
|
for (const auto& subscription : subscriptions_) {
|
|
if (subscription.type == event.type) {
|
|
subscription.callback(event, subscription.user_data);
|
|
++delivered;
|
|
}
|
|
}
|
|
|
|
return delivered;
|
|
}
|
|
|
|
void EventDispatcher::clear() noexcept
|
|
{
|
|
subscriptions_.clear();
|
|
}
|
|
|
|
}
|