#pragma once #include #include #include #include #include "task.hpp" #include "types.hpp" #include "object.hpp" #include #include #include "priority.hpp" #include "labelled.hpp" namespace flat::core { class signal : virtual public labelled, virtual public prioritized { public: struct package { package(void *data) : data(data) {} template T * get() { return reinterpret_cast(data); } void * data; }; object *m_sender; package m_package; signal(object * sender, const std::string& id = "", void * data = 0, priority_t prior = priority_t::none); }; /* Listener class */ class listener { public: using callback = std::function; using ptr = std::shared_ptr; listener(callback m_callback, const std::initializer_list& filters = {}); ~listener(); void add_filter(const std::string&); void remove_filter(const std::string&); bool connect(const std::string&); bool disconnect(const std::string&); void invoke(const signal&); /* Allow to safely bind a functor */ template static ptr create( R T::*mf, T& obj, const std::initializer_list& filters = {}) { return std::make_shared(std::bind(mf, obj), filters); } private: callback m_callback; std::list m_filters; bool check_in_filters(const std::string&) const; }; /* Channel class */ class channel : virtual public labelled, public std::enable_shared_from_this { private: /* Post processing signal stacking */ queue m_stack; /* Listeners list */ std::list> m_listeners; /* Synchronous task checking for signals */ task::ptr m_checker; /* Channel mapping */ static std::map> m_channels; bool m_mapped; public: using ptr = std::shared_ptr; channel(const std::string& id = ""); ~channel(); void start(priority_t task_priority = priority_t::none); bool map(); void emit(const signal&); bool connect(listener::ptr l); void disconnect(listener::ptr l); bool connect(listener* l); void disconnect(listener* l); listener::ptr connect(listener::callback f, const std::initializer_list& filters = {}); template inline listener::ptr connect(R T::*mf, T* obj, const std::initializer_list& filters = {}) { using namespace std::placeholders; return connect(std::bind(mf, obj, _1, _2), filters); } static ptr find(const std::string&); static ptr create(const std::string& id, priority_t prior = priority_t::none); void check_and_call(); }; }