#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 { //class object; namespace 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 * sender; package m_package; signal( object * sender, const std::string& id = "", void * data = 0, priority_t prior = priority_t::none); /* Alias to flat::core::channel::emit() */ bool emit(const std::string& channel) const; }; /* 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 filters; bool check_in_filters(const std::string&) const; }; /* Channel class */ class channel : virtual public labelled, public std::enable_shared_from_this { /* Post processing signal stacking */ queue stack; /* Listeners list */ std::list> listeners; /* Synchronous task checking for signals */ task::ptr checker; /* Channel mapping */ static std::map> channels; bool 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(); }; } }