From a94a806f69586e08a30fff0cdb3e52b0ce7acfa5 Mon Sep 17 00:00:00 2001 From: crupest Date: Fri, 5 Apr 2019 00:11:36 +0800 Subject: Refactor event. --- include/cru/common/event.hpp | 127 +++++++++++++++++++++++++++++-------------- 1 file changed, 86 insertions(+), 41 deletions(-) (limited to 'include/cru/common/event.hpp') diff --git a/include/cru/common/event.hpp b/include/cru/common/event.hpp index 6228d867..987bcdd6 100644 --- a/include/cru/common/event.hpp +++ b/include/cru/common/event.hpp @@ -2,73 +2,102 @@ #include "base.hpp" #include +#include #include #include #include namespace cru { -using EventHandlerRevoker = std::function; +class EventRevoker; + +namespace details { +class EventBase { + friend EventRevoker; + + protected: + using EventHandlerToken = long; + + EventBase() : resolve_ptr_(new std::reference_wrapper(*this)) {} + + EventBase(const EventBase& other) = delete; + EventBase(EventBase&& other) = delete; + EventBase& operator=(const EventBase& other) = delete; + EventBase& operator=(EventBase&& other) = delete; + virtual ~EventBase() = default; + + virtual void RemoveHandler(EventHandlerToken token) = 0; + + inline EventRevoker CreateRevoker(EventHandlerToken token); + + private: + std::shared_ptr> resolve_ptr_; +}; +} // namespace details + +class EventRevoker { + friend class ::cru::details::EventBase; -// A non-copyable non-movable Event class. -// It stores a list of event handlers. -template -class Event { private: - using EventResolver = std::function; - class EventHandlerRevokerImpl { - public: - EventHandlerRevokerImpl(const std::shared_ptr& resolver, - long token) - : resolver_(resolver), token_(token) {} - EventHandlerRevokerImpl(const EventHandlerRevokerImpl& other) = default; - EventHandlerRevokerImpl(EventHandlerRevokerImpl&& other) = default; - EventHandlerRevokerImpl& operator=(const EventHandlerRevokerImpl& other) = - default; - EventHandlerRevokerImpl& operator=(EventHandlerRevokerImpl&& other) = - default; - ~EventHandlerRevokerImpl() = default; - - void operator()() { - const auto true_resolver = resolver_.lock(); - if (true_resolver) { - (*true_resolver)()->RemoveHandler(token_); - } + EventRevoker(const std::shared_ptr< + std::reference_wrapper>& resolve_ptr, + details::EventBase::EventHandlerToken token) + : weak_ptr_(resolve_ptr), token_(token) {} + + public: + EventRevoker(const EventRevoker& other) = default; + EventRevoker(EventRevoker&& other) = default; + EventRevoker& operator=(const EventRevoker& other) = default; + EventRevoker& operator=(EventRevoker&& other) = default; + ~EventRevoker() = default; + + void operator()() const { + const auto true_resolver = weak_ptr_.lock(); + if (true_resolver) { + (*true_resolver).get().RemoveHandler(token_); } + } + + private: + std::weak_ptr> weak_ptr_; + details::EventBase::EventHandlerToken token_; +}; - private: - std::weak_ptr resolver_; - long token_; - }; +inline EventRevoker details::EventBase::CreateRevoker(EventHandlerToken token) { + return EventRevoker(resolve_ptr_, token); +} +// A non-copyable non-movable Event class. +// It stores a list of event handlers. +template +class Event : public details::EventBase { public: using EventHandler = std::function; - Event() - : event_resolver_(new std::function([this] { return this; })) {} + Event() = default; Event(const Event&) = delete; Event& operator=(const Event&) = delete; Event(Event&&) = delete; Event& operator=(Event&&) = delete; ~Event() = default; - EventHandlerRevoker AddHandler(const EventHandler& handler) { + EventRevoker AddHandler(const EventHandler& handler) { const auto token = current_token_++; handlers_.emplace(token, handler); - return EventHandlerRevoker(EventHandlerRevokerImpl(event_resolver_, token)); + return CreateRevoker(token); } - EventHandlerRevoker AddHandler(EventHandler&& handler) { + EventRevoker AddHandler(EventHandler&& handler) { const auto token = current_token_++; handlers_.emplace(token, std::move(handler)); - return EventHandlerRevoker(EventHandlerRevokerImpl(event_resolver_, token)); + return CreateRevoker(token); } template - EventHandlerRevoker AddHandler(Arg&& handler) { + EventRevoker AddHandler(Arg&& handler) { static_assert(std::is_invocable_v, "Handler not invocable."); const auto token = current_token_++; handlers_.emplace(token, EventHandler(std::forward(handler))); - return EventHandlerRevoker(EventHandlerRevokerImpl(event_resolver_, token)); + return CreateRevoker(token); } template @@ -77,15 +106,31 @@ class Event { (handler.second)(std::forward(args)...); } - private: - void RemoveHandler(const long token) { + protected: + void RemoveHandler(EventHandlerToken token) override { auto find_result = handlers_.find(token); if (find_result != handlers_.cend()) handlers_.erase(find_result); } private: - std::map handlers_{}; - long current_token_ = 0; - std::shared_ptr event_resolver_; + std::map handlers_{}; + EventHandlerToken current_token_ = 0; +}; + +class EventRevokerGuard { + public: + EventRevokerGuard() = default; + EventRevokerGuard(const EventRevokerGuard& other) = delete; + EventRevokerGuard(EventRevokerGuard&& other) = delete; + EventRevokerGuard& operator=(const EventRevokerGuard& other) = delete; + EventRevokerGuard& operator=(EventRevokerGuard&& other) = delete; + ~EventRevokerGuard() { + for (const auto revoker : revokers_) revoker(); + } + + void Add(EventRevoker revoker) { revokers_.push_back(std::move(revoker)); } + + private: + std::list revokers_; }; } // namespace cru -- cgit v1.2.3