diff options
author | crupest <crupest@outlook.com> | 2019-06-25 00:28:52 +0800 |
---|---|---|
committer | crupest <crupest@outlook.com> | 2019-06-25 00:28:52 +0800 |
commit | 35abeab46fb0ccb115d10e73315e3251cc9dc880 (patch) | |
tree | bdbcd25c58692327ecd34518c5df8f343606ba0c /include/cru/common | |
parent | 28c7884d0186ad80db7b9ffa12dd5e52bcb6c52b (diff) | |
download | cru-35abeab46fb0ccb115d10e73315e3251cc9dc880.tar.gz cru-35abeab46fb0ccb115d10e73315e3251cc9dc880.tar.bz2 cru-35abeab46fb0ccb115d10e73315e3251cc9dc880.zip |
...
Diffstat (limited to 'include/cru/common')
-rw-r--r-- | include/cru/common/event.hpp | 53 | ||||
-rw-r--r-- | include/cru/common/self_resolvable.hpp | 9 |
2 files changed, 41 insertions, 21 deletions
diff --git a/include/cru/common/event.hpp b/include/cru/common/event.hpp index 144513b6..cc21cb91 100644 --- a/include/cru/common/event.hpp +++ b/include/cru/common/event.hpp @@ -1,6 +1,8 @@ #pragma once #include "base.hpp" +#include "self_resolvable.hpp" + #include <functional> #include <list> #include <map> @@ -15,13 +17,13 @@ namespace details { // It erases event args types and provides a // unified form to create event revoker and // revoke(remove) handler. -class EventBase { +class EventBase : private SelfResovable<EventBase> { friend EventRevoker; protected: using EventHandlerToken = long; - EventBase() : resolver_(new EventBase*(this)) {} + EventBase() {} EventBase(const EventBase& other) = delete; EventBase(EventBase&& other) = delete; EventBase& operator=(const EventBase& other) = delete; @@ -35,9 +37,6 @@ class EventBase { // Create a revoker with the given token. inline EventRevoker CreateRevoker(EventHandlerToken token); - - private: - std::shared_ptr<EventBase*> resolver_; }; } // namespace details @@ -47,14 +46,14 @@ class EventRevoker { friend class ::cru::details::EventBase; private: - EventRevoker(const std::shared_ptr<details::EventBase*>& resolver, + EventRevoker(ObjectResovler<details::EventBase>&& resolver, details::EventBase::EventHandlerToken token) - : weak_resolver_(resolver), token_(token) {} + : resolver_(std::move(resolver)), token_(token) {} public: - EventRevoker(const EventRevoker& other) = delete; + EventRevoker(const EventRevoker& other) = default; EventRevoker(EventRevoker&& other) = default; - EventRevoker& operator=(const EventRevoker& other) = delete; + EventRevoker& operator=(const EventRevoker& other) = default; EventRevoker& operator=(EventRevoker&& other) = default; ~EventRevoker() = default; @@ -63,20 +62,18 @@ class EventRevoker { // copies calls this, then other copies's calls will have no // effect. (They have the same token.) void operator()() const { - const auto true_resolver = weak_resolver_.lock(); - // if true_resolver is nullptr, then the event has been destroyed. - if (true_resolver) { - (*true_resolver)->RemoveHandler(token_); + if (const auto event = resolver_.Resolve()) { + event->RemoveHandler(token_); } } private: - std::weak_ptr<details::EventBase*> weak_resolver_; + ObjectResovler<details::EventBase> resolver_; details::EventBase::EventHandlerToken token_; }; inline EventRevoker details::EventBase::CreateRevoker(EventHandlerToken token) { - return EventRevoker(resolver_, token); + return EventRevoker(CreateResolver(), token); } // int -> int @@ -160,19 +157,35 @@ class Event : public details::EventBase, public IEvent<TEventArgs> { EventHandlerToken current_token_ = 0; }; +namespace details { +struct EventRevokerDestroyer { + void operator()(EventRevoker* p) { + (*p)(); + delete p; + } +}; +} // namespace details + class EventRevokerGuard { public: explicit EventRevokerGuard(EventRevoker&& revoker) - : revoker_(std::move(revoker)) {} + : revoker_(new EventRevoker(std::move(revoker))) {} EventRevokerGuard(const EventRevokerGuard& other) = delete; EventRevokerGuard(EventRevokerGuard&& other) = default; EventRevokerGuard& operator=(const EventRevokerGuard& other) = delete; EventRevokerGuard& operator=(EventRevokerGuard&& other) = default; - ~EventRevokerGuard() { revoker_(); } + ~EventRevokerGuard() = default; - EventRevoker ReleaseAndGet() { return std::move(revoker_); } + EventRevoker Get() { + // revoker is only null when this is moved + // you shouldn't use a moved instance + assert(revoker_); + return *revoker_; + } + + void Release() { revoker_.release(); } private: - EventRevoker revoker_; -}; + std::unique_ptr<EventRevoker, details::EventRevokerDestroyer> revoker_; +}; // namespace cru } // namespace cru diff --git a/include/cru/common/self_resolvable.hpp b/include/cru/common/self_resolvable.hpp index edeb1434..3e9d74ed 100644 --- a/include/cru/common/self_resolvable.hpp +++ b/include/cru/common/self_resolvable.hpp @@ -1,7 +1,9 @@ #pragma once #include "pre_config.hpp" +#include <cassert> #include <memory> +#include <type_traits> namespace cru { template <typename T> @@ -21,7 +23,12 @@ class ObjectResovler { ObjectResovler& operator=(ObjectResovler&&) = default; ~ObjectResovler() = default; - T* Resolve() const { return *resolver_; } + T* Resolve() const { + // resolver_ is null only when this has been moved. + // You shouldn't resolve a moved resolver. So assert it. + assert(resolver_); + return *resolver_; + } private: std::shared_ptr<T*> resolver_; |