A 2D tile-based sandbox game.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

EventEmitter.h 1.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475
  1. #pragma once
  2. #include <functional>
  3. #include "util.h"
  4. #include "SlotVector.h"
  5. namespace Swan {
  6. // So that EventListener doesn't have to be a template
  7. class EventEmitterInterface {
  8. public:
  9. virtual void unsubscribe(size_t id) = 0;
  10. };
  11. class EventListener: NonCopyable {
  12. public:
  13. EventListener() {}
  14. EventListener(EventEmitterInterface *emitter, size_t id):
  15. emitter_(emitter), id_(id) {}
  16. EventListener(EventListener &&other) noexcept:
  17. emitter_(other.emitter_), id_(other.id_) {
  18. other.emitter_ = nullptr;
  19. }
  20. EventListener &operator=(EventListener &&other) noexcept {
  21. emitter_ = other.emitter_;
  22. id_ = other.id_;
  23. other.emitter_ = nullptr;
  24. return *this;
  25. }
  26. ~EventListener() {
  27. if (emitter_)
  28. emitter_->unsubscribe(id_);
  29. }
  30. void unsubscribe() {
  31. if (emitter_) {
  32. emitter_->unsubscribe(id_);
  33. emitter_ = nullptr;
  34. }
  35. }
  36. private:
  37. EventEmitterInterface *emitter_ = nullptr;
  38. size_t id_;
  39. };
  40. template<typename... Evt>
  41. class EventEmitter: public EventEmitterInterface {
  42. public:
  43. using Callback = std::function<void(Evt...)>;
  44. void emit(Evt... evt) {
  45. for (auto &cb: callbacks_)
  46. cb(evt...);
  47. }
  48. EventListener subscribe(Callback cb) {
  49. size_t id = callbacks_.insert(std::move(cb));
  50. return EventListener(this, id);
  51. }
  52. void unsubscribe(size_t id) {
  53. callbacks_.erase(id);
  54. }
  55. private:
  56. SlotVector<Callback, SlotVectorDefaultSentinel<std::nullptr_t>> callbacks_;
  57. };
  58. }