#ifndef SOPHIAR2_TINY_SIGNAL_HPP #define SOPHIAR2_TINY_SIGNAL_HPP #include #include #include #include #include namespace sophiar { using slot_hook_type = boost::intrusive::list_base_hook< boost::intrusive::link_mode< boost::intrusive::auto_unlink>>; struct [[deprecated]] tiny_slot_base : public slot_hook_type { bool is_enabled = true; virtual ~tiny_slot_base() = default; void disconnect() { assert(this->is_linked()); this->unlink(); SPDLOG_TRACE("Slot {} is disconnected.", fmt::ptr(this)); } }; struct tiny_signal_base { virtual ~tiny_signal_base() = default; virtual void add_slot_base(tiny_slot_base *slot_base) = 0; }; template class [[deprecated]] tiny_signal : public tiny_signal_base { public: class slot_type : public tiny_slot_base { public: void signal_received(Args... args) { if (!is_enabled) return; on_signal_received(std::move(args)...); } protected: virtual void on_signal_received(Args... args) = 0; }; void add_slot_base(tiny_slot_base *slot_base) override { auto slot_ptr = dynamic_cast(slot_base); assert(slot_ptr != nullptr); slot_list.push_back(*slot_ptr); SPDLOG_TRACE("Slot {} is connected to signal {}.", fmt::ptr(slot_ptr), fmt::ptr(this)); } void emit(Args... args) { auto iter = slot_list.begin(), iter_end = slot_list.end(); while (iter != iter_end) { auto this_iter = iter++; if (iter == iter_end) { this_iter->signal_received(std::move(args)...); } else { this_iter->signal_received(args...); } } } private: using slot_list_type = boost::intrusive::list< slot_type, boost::intrusive::constant_time_size>; slot_list_type slot_list; }; } #endif //SOPHIAR2_TINY_SIGNAL_HPP