#include "foundation/event.h" #include 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 EventDispatcher::subscribe(std::uint32_t type, EventCallback callback, void* user_data) { if (max_subscriptions_ == 0U || max_subscriptions_ > max_event_subscriptions) { return Result::failure( Status::out_of_range("event dispatcher capacity is outside the configured range")); } if (type == 0U) { return Result::failure(Status::invalid_argument("event type must not be zero")); } if (callback == nullptr) { return Result::failure(Status::invalid_argument("event callback must not be null")); } if (subscriptions_.size() >= max_subscriptions_) { return Result::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::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(); } }