Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #ifndef EVENTRECEIVABLE_H
- #define EVENTRECEIVABLE_H
- #include <memory>
- #include <atomic>
- class EventReceivable
- {
- public:
- class EventReceiver
- {
- public:
- explicit EventReceiver(EventReceivable* instance);
- ~EventReceiver() = default;
- public:
- auto instance() const -> EventReceivable* { return instance_; }
- void instance(EventReceivable* instance) { instance_ = instance; }
- private:
- EventReceivable* instance_;
- };
- public:
- EventReceivable(EventReceivable const& eventReceivable) = delete;
- public:
- EventReceivable& operator=(EventReceivable const& rhs) = delete;
- public:
- auto eventReceiver() const -> std::shared_ptr<EventReceiver> const& { return eventReceiver_; }
- auto id() const -> uint_fast64_t { return id_; }
- protected:
- EventReceivable();
- EventReceivable(EventReceivable &&eventReceivable) noexcept;
- ~EventReceivable() = default;
- protected:
- EventReceivable& operator=(EventReceivable&& rhs) noexcept;
- private:
- std::uint_fast64_t id_;
- std::shared_ptr<EventReceiver> eventReceiver_;
- private:
- static std::atomic_uint_fast64_t lastId_;
- };
- #endif //PROJECT_EVENTRECEIVABLE_H
- #include "EventReceivable.h"
- std::atomic_uint_fast64_t EventReceivable::lastId_{0};
- EventReceivable::EventReceiver::EventReceiver(EventReceivable* instance) :
- instance_{instance}
- {
- }
- EventReceivable::EventReceivable() :
- id_{++lastId_}
- , eventReceiver_{std::make_shared<EventReceiver>(this)}
- {
- }
- EventReceivable::EventReceivable(EventReceivable &&eventReceivable) noexcept :
- id_{eventReceivable.id_}
- , eventReceiver_{std::move(eventReceivable.eventReceiver_)}
- {
- eventReceivable.id_ = 0;
- eventReceiver_->instance(this);
- }
- EventReceivable& EventReceivable::operator=(EventReceivable&& rhs) noexcept {
- eventReceiver_ = std::move(rhs.eventReceiver_);
- eventReceiver_->instance(this);
- id_ = rhs.id_;
- rhs.id_ = 0;
- return *this;
- }
- #ifndef EVENT_H
- #define EVENT_H
- #include <functional>
- #include <unordered_map>
- #include <algorithm>
- #include <utility>
- #include <boost/functional/hash.hpp>
- #include "EventReceivable.h"
- template<typename... Args>
- class Event
- {
- private:
- struct Dummy {
- void func() {};
- virtual void vFunc() {};
- };
- using EventHandlerIdentifier = std::array<
- std::byte, sizeof(uint_fast64_t) + std::max(sizeof(&Dummy::func), sizeof(&Dummy::vFunc))>;
- public:
- class EventHandler
- {
- friend Event;
- public:
- template<class T, class M>
- EventHandler(T *instance, void (M::*member)(Args...)) :
- isStatic_{false}
- , identifier_{}
- , eventReceiver_{instance->eventReceiver()}
- , handler_{}
- {
- auto id = instance->id();
- std::memset(identifier_.data(), 0, identifier_.size());
- std::memcpy(identifier_.data(), &id, sizeof(uint_fast64_t));
- std::memcpy(identifier_.data() + sizeof(uint_fast64_t), &member, sizeof(member));
- auto eventReceiver = eventReceiver_;
- handler_ = [eventReceiver, member](auto&&... args) -> void {
- assert(!eventReceiver.expired());
- auto receiver = eventReceiver.lock();
- ((static_cast<T*>(receiver->instance()))->*member)(std::forward<decltype(args)>(args)...);
- };
- }
- template<typename SFunc>
- EventHandler(SFunc const& staticHandler) :
- isStatic_{true}
- , identifier_{}
- , eventReceiver_{}
- , handler_{[staticHandler](auto&&... args) -> void {
- staticHandler(std::forward<decltype(args)>(args)...);
- }}
- {
- std::memset(identifier_.data(), 0, identifier_.size());
- std::memcpy(identifier_.data() + sizeof(uint_fast64_t), &staticHandler, sizeof(uintptr_t));
- }
- EventHandler(EventHandler const&) = default;
- EventHandler(EventHandler&&) = default;
- ~EventHandler() = default;
- public:
- EventHandler &operator=(EventHandler const&) = default;
- EventHandler &operator=(EventHandler&&) = default;
- template<typename... EventArgs>
- void operator()(EventArgs&&... args) {
- invoke(std::forward<EventArgs>(args)...);
- }
- explicit operator bool() const {
- return isStatic_ ? true : !eventReceiver_.expired();
- }
- public:
- template<typename... EventArgs>
- void invoke(EventArgs&&... args) {
- handler_(std::forward<EventArgs>(args)...);
- }
- public:
- auto identifier() const -> EventHandlerIdentifier const& { return identifier_; }
- private:
- bool isStatic_;
- EventHandlerIdentifier identifier_;
- std::weak_ptr<EventReceivable::EventReceiver> eventReceiver_;
- std::function<void(Args...)> handler_;
- };
- public:
- Event() : eventHandlers_{} { }
- Event(Event const&) = delete;
- Event(Event&&) = default;
- ~Event() = default;
- public:
- Event& operator=(Event const&) = delete;
- Event& operator=(Event&&) = default;
- template<typename Handler>
- auto operator+=(Handler const& rhs) -> EventHandler
- {
- static_assert(std::is_same_v<EventHandler, std::decay_t<Handler>> || std::is_invocable_v<Handler, Args...>);
- if constexpr (std::is_same_v<EventHandler, std::decay_t<Handler>>) {
- eventHandlers_.emplace(rhs.identifier(), rhs);
- return rhs;
- } else {
- EventHandler eh{rhs};
- eventHandlers_.emplace(eh.identifier(), eh);
- return eh;
- }
- }
- void operator-=(EventHandler const& rhs)
- {
- eventHandlers_.erase(rhs.identifier());
- }
- template<typename... EventArgs>
- void operator()(EventArgs&&... args)
- {
- auto it = eventHandlers_.begin();
- while (it != eventHandlers_.end()) {
- EventHandler& eventHandler = (*it).second;
- if (eventHandler) {
- eventHandler(std::forward<EventArgs>(args)...);
- it++;
- }
- else {
- it = eventHandlers_.erase(it);
- }
- }
- }
- private:
- std::unordered_map<EventHandlerIdentifier, EventHandler, boost::hash<EventHandlerIdentifier>> eventHandlers_;
- };
- #endif //PROJECT_EVENT_H
- class Emitter {
- public:
- Event<uint32_t> event;
- }
- class Receiver final: public EventReceivable {
- public:
- void onEvent(uint32_t val) { result_ = val; }
- auto result() const { return result_; }
- private:
- uint32_t result_ = 0;
- }
- Emitter emitter;
- Receiver receiver1;
- // ordinary usage:
- emitter.event += Event<uint32_t>::EventHandler(&receiver1, &Receiver::onEvent);
- // RAII test:
- {
- Receiver receiver2;
- emitter.event += Event<uint32_t>::EventHandler(&receiver2, &Receiver::onEvent);
- // do not care if receiver is still alive or deleted
- // emitter.event -= Event<uint32_t>::EventHandler(&receiver2,
- // &Receiver::onEvent);
- }
- // can use lambdas:
- uint32_t result = 0;
- emitter.event += [&](uint32_t val) { result = val; };
- emitter.event(42);
- public:
- public:
- public:
- : identifier_{}, handler_{}
Add Comment
Please, Sign In to add comment