Guest User

Untitled

a guest
Apr 20th, 2018
65
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 7.15 KB | None | 0 0
  1. #ifndef EVENTRECEIVABLE_H
  2. #define EVENTRECEIVABLE_H
  3.  
  4. #include <memory>
  5. #include <atomic>
  6.  
  7. class EventReceivable
  8. {
  9. public:
  10. class EventReceiver
  11. {
  12. public:
  13. explicit EventReceiver(EventReceivable* instance);
  14.  
  15. ~EventReceiver() = default;
  16.  
  17. public:
  18. auto instance() const -> EventReceivable* { return instance_; }
  19.  
  20. void instance(EventReceivable* instance) { instance_ = instance; }
  21.  
  22. private:
  23. EventReceivable* instance_;
  24. };
  25.  
  26. public:
  27. EventReceivable(EventReceivable const& eventReceivable) = delete;
  28.  
  29. public:
  30. EventReceivable& operator=(EventReceivable const& rhs) = delete;
  31.  
  32. public:
  33. auto eventReceiver() const -> std::shared_ptr<EventReceiver> const& { return eventReceiver_; }
  34.  
  35. auto id() const -> uint_fast64_t { return id_; }
  36.  
  37. protected:
  38. EventReceivable();
  39.  
  40. EventReceivable(EventReceivable &&eventReceivable) noexcept;
  41.  
  42. ~EventReceivable() = default;
  43.  
  44. protected:
  45. EventReceivable& operator=(EventReceivable&& rhs) noexcept;
  46.  
  47. private:
  48. std::uint_fast64_t id_;
  49. std::shared_ptr<EventReceiver> eventReceiver_;
  50.  
  51. private:
  52. static std::atomic_uint_fast64_t lastId_;
  53. };
  54.  
  55. #endif //PROJECT_EVENTRECEIVABLE_H
  56.  
  57. #include "EventReceivable.h"
  58.  
  59. std::atomic_uint_fast64_t EventReceivable::lastId_{0};
  60.  
  61. EventReceivable::EventReceiver::EventReceiver(EventReceivable* instance) :
  62. instance_{instance}
  63. {
  64. }
  65.  
  66. EventReceivable::EventReceivable() :
  67. id_{++lastId_}
  68. , eventReceiver_{std::make_shared<EventReceiver>(this)}
  69. {
  70. }
  71.  
  72. EventReceivable::EventReceivable(EventReceivable &&eventReceivable) noexcept :
  73. id_{eventReceivable.id_}
  74. , eventReceiver_{std::move(eventReceivable.eventReceiver_)}
  75. {
  76. eventReceivable.id_ = 0;
  77. eventReceiver_->instance(this);
  78. }
  79.  
  80. EventReceivable& EventReceivable::operator=(EventReceivable&& rhs) noexcept {
  81. eventReceiver_ = std::move(rhs.eventReceiver_);
  82. eventReceiver_->instance(this);
  83.  
  84. id_ = rhs.id_;
  85. rhs.id_ = 0;
  86.  
  87. return *this;
  88. }
  89.  
  90. #ifndef EVENT_H
  91. #define EVENT_H
  92.  
  93. #include <functional>
  94. #include <unordered_map>
  95. #include <algorithm>
  96. #include <utility>
  97. #include <boost/functional/hash.hpp>
  98. #include "EventReceivable.h"
  99.  
  100. template<typename... Args>
  101. class Event
  102. {
  103. private:
  104. struct Dummy {
  105. void func() {};
  106. virtual void vFunc() {};
  107. };
  108.  
  109. using EventHandlerIdentifier = std::array<
  110. std::byte, sizeof(uint_fast64_t) + std::max(sizeof(&Dummy::func), sizeof(&Dummy::vFunc))>;
  111.  
  112. public:
  113. class EventHandler
  114. {
  115. friend Event;
  116.  
  117. public:
  118. template<class T, class M>
  119. EventHandler(T *instance, void (M::*member)(Args...)) :
  120. isStatic_{false}
  121. , identifier_{}
  122. , eventReceiver_{instance->eventReceiver()}
  123. , handler_{}
  124. {
  125. auto id = instance->id();
  126.  
  127. std::memset(identifier_.data(), 0, identifier_.size());
  128. std::memcpy(identifier_.data(), &id, sizeof(uint_fast64_t));
  129. std::memcpy(identifier_.data() + sizeof(uint_fast64_t), &member, sizeof(member));
  130.  
  131. auto eventReceiver = eventReceiver_;
  132.  
  133. handler_ = [eventReceiver, member](auto&&... args) -> void {
  134. assert(!eventReceiver.expired());
  135.  
  136. auto receiver = eventReceiver.lock();
  137.  
  138. ((static_cast<T*>(receiver->instance()))->*member)(std::forward<decltype(args)>(args)...);
  139. };
  140. }
  141.  
  142. template<typename SFunc>
  143. EventHandler(SFunc const& staticHandler) :
  144. isStatic_{true}
  145. , identifier_{}
  146. , eventReceiver_{}
  147. , handler_{[staticHandler](auto&&... args) -> void {
  148. staticHandler(std::forward<decltype(args)>(args)...);
  149. }}
  150. {
  151. std::memset(identifier_.data(), 0, identifier_.size());
  152. std::memcpy(identifier_.data() + sizeof(uint_fast64_t), &staticHandler, sizeof(uintptr_t));
  153. }
  154.  
  155. EventHandler(EventHandler const&) = default;
  156.  
  157. EventHandler(EventHandler&&) = default;
  158.  
  159. ~EventHandler() = default;
  160.  
  161. public:
  162. EventHandler &operator=(EventHandler const&) = default;
  163.  
  164. EventHandler &operator=(EventHandler&&) = default;
  165.  
  166. template<typename... EventArgs>
  167. void operator()(EventArgs&&... args) {
  168. invoke(std::forward<EventArgs>(args)...);
  169. }
  170.  
  171. explicit operator bool() const {
  172. return isStatic_ ? true : !eventReceiver_.expired();
  173. }
  174.  
  175. public:
  176. template<typename... EventArgs>
  177. void invoke(EventArgs&&... args) {
  178. handler_(std::forward<EventArgs>(args)...);
  179. }
  180.  
  181. public:
  182. auto identifier() const -> EventHandlerIdentifier const& { return identifier_; }
  183.  
  184. private:
  185. bool isStatic_;
  186.  
  187. EventHandlerIdentifier identifier_;
  188.  
  189. std::weak_ptr<EventReceivable::EventReceiver> eventReceiver_;
  190.  
  191. std::function<void(Args...)> handler_;
  192. };
  193.  
  194. public:
  195. Event() : eventHandlers_{} { }
  196.  
  197. Event(Event const&) = delete;
  198.  
  199. Event(Event&&) = default;
  200.  
  201. ~Event() = default;
  202.  
  203. public:
  204. Event& operator=(Event const&) = delete;
  205.  
  206. Event& operator=(Event&&) = default;
  207.  
  208. template<typename Handler>
  209. auto operator+=(Handler const& rhs) -> EventHandler
  210. {
  211. static_assert(std::is_same_v<EventHandler, std::decay_t<Handler>> || std::is_invocable_v<Handler, Args...>);
  212.  
  213. if constexpr (std::is_same_v<EventHandler, std::decay_t<Handler>>) {
  214. eventHandlers_.emplace(rhs.identifier(), rhs);
  215. return rhs;
  216. } else {
  217. EventHandler eh{rhs};
  218. eventHandlers_.emplace(eh.identifier(), eh);
  219. return eh;
  220. }
  221. }
  222.  
  223. void operator-=(EventHandler const& rhs)
  224. {
  225. eventHandlers_.erase(rhs.identifier());
  226. }
  227.  
  228. template<typename... EventArgs>
  229. void operator()(EventArgs&&... args)
  230. {
  231. auto it = eventHandlers_.begin();
  232.  
  233. while (it != eventHandlers_.end()) {
  234. EventHandler& eventHandler = (*it).second;
  235.  
  236. if (eventHandler) {
  237. eventHandler(std::forward<EventArgs>(args)...);
  238. it++;
  239. }
  240. else {
  241. it = eventHandlers_.erase(it);
  242. }
  243. }
  244. }
  245.  
  246. private:
  247. std::unordered_map<EventHandlerIdentifier, EventHandler, boost::hash<EventHandlerIdentifier>> eventHandlers_;
  248. };
  249. #endif //PROJECT_EVENT_H
  250.  
  251. class Emitter {
  252. public:
  253. Event<uint32_t> event;
  254. }
  255.  
  256. class Receiver final: public EventReceivable {
  257. public:
  258. void onEvent(uint32_t val) { result_ = val; }
  259.  
  260. auto result() const { return result_; }
  261. private:
  262. uint32_t result_ = 0;
  263. }
  264.  
  265. Emitter emitter;
  266. Receiver receiver1;
  267.  
  268. // ordinary usage:
  269. emitter.event += Event<uint32_t>::EventHandler(&receiver1, &Receiver::onEvent);
  270.  
  271. // RAII test:
  272. {
  273. Receiver receiver2;
  274.  
  275. emitter.event += Event<uint32_t>::EventHandler(&receiver2, &Receiver::onEvent);
  276.  
  277. // do not care if receiver is still alive or deleted
  278. // emitter.event -= Event<uint32_t>::EventHandler(&receiver2,
  279. // &Receiver::onEvent);
  280. }
  281.  
  282. // can use lambdas:
  283. uint32_t result = 0;
  284. emitter.event += [&](uint32_t val) { result = val; };
  285.  
  286. emitter.event(42);
  287.  
  288. public:
  289. public:
  290. public:
  291.  
  292. : identifier_{}, handler_{}
Add Comment
Please, Sign In to add comment