tiny_signal.hpp 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. #ifndef SOPHIAR2_TINY_SIGNAL_HPP
  2. #define SOPHIAR2_TINY_SIGNAL_HPP
  3. #include <boost/intrusive/list.hpp>
  4. #include <spdlog/spdlog.h>
  5. #include <cassert>
  6. #include <type_traits>
  7. #include <utility>
  8. namespace sophiar {
  9. using slot_hook_type = boost::intrusive::list_base_hook<
  10. boost::intrusive::link_mode<
  11. boost::intrusive::auto_unlink>>;
  12. struct [[deprecated]] tiny_slot_base : public slot_hook_type {
  13. bool is_enabled = true;
  14. virtual ~tiny_slot_base() = default;
  15. void disconnect() {
  16. assert(this->is_linked());
  17. this->unlink();
  18. SPDLOG_TRACE("Slot {} is disconnected.", fmt::ptr(this));
  19. }
  20. };
  21. struct tiny_signal_base {
  22. virtual ~tiny_signal_base() = default;
  23. virtual void add_slot_base(tiny_slot_base *slot_base) = 0;
  24. };
  25. template<typename... Args>
  26. class [[deprecated]] tiny_signal : public tiny_signal_base {
  27. public:
  28. class slot_type : public tiny_slot_base {
  29. public:
  30. void signal_received(Args... args) {
  31. if (!is_enabled) return;
  32. on_signal_received(std::move(args)...);
  33. }
  34. protected:
  35. virtual void on_signal_received(Args... args) = 0;
  36. };
  37. void add_slot_base(tiny_slot_base *slot_base) override {
  38. auto slot_ptr = dynamic_cast<slot_type *>(slot_base);
  39. assert(slot_ptr != nullptr);
  40. slot_list.push_back(*slot_ptr);
  41. SPDLOG_TRACE("Slot {} is connected to signal {}.",
  42. fmt::ptr(slot_ptr), fmt::ptr(this));
  43. }
  44. void emit(Args... args) {
  45. auto iter = slot_list.begin(), iter_end = slot_list.end();
  46. while (iter != iter_end) {
  47. auto this_iter = iter++;
  48. if (iter == iter_end) {
  49. this_iter->signal_received(std::move(args)...);
  50. } else {
  51. this_iter->signal_received(args...);
  52. }
  53. }
  54. }
  55. private:
  56. using slot_list_type = boost::intrusive::list<
  57. slot_type, boost::intrusive::constant_time_size<false>>;
  58. slot_list_type slot_list;
  59. };
  60. }
  61. #endif //SOPHIAR2_TINY_SIGNAL_HPP