| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182 |
- #ifndef SOPHIAR2_TINY_SIGNAL_HPP
- #define SOPHIAR2_TINY_SIGNAL_HPP
- #include <boost/intrusive/list.hpp>
- #include <cassert>
- #include <type_traits>
- #include <utility>
- namespace sophiar {
- using slot_hook_type = boost::intrusive::list_base_hook<
- boost::intrusive::link_mode<
- boost::intrusive::auto_unlink>>;
- struct tiny_slot_base : public slot_hook_type {
- bool is_enabled = true;
- virtual ~tiny_slot_base() = default;
- void disconnect() {
- assert(this->is_linked());
- this->unlink();
- }
- };
- struct tiny_signal_base {
- virtual ~tiny_signal_base() = default;
- virtual void add_slot_base(tiny_slot_base *slot_base) = 0;
- };
- template<typename... Args>
- class 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_type *>(slot_base);
- assert(slot_ptr != nullptr);
- slot_list.push_back(*slot_ptr);
- }
- 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<false>>;
- slot_list_type slot_list;
- };
- }
- #endif //SOPHIAR2_TINY_SIGNAL_HPP
|