diff options
author | ancarola <raffaele.ancarola@epfl.ch> | 2019-01-22 01:29:43 +0100 |
---|---|---|
committer | ancarola <raffaele.ancarola@epfl.ch> | 2019-01-22 01:29:43 +0100 |
commit | 7170c16a463fdb1f446ab7458270205bf08e7c89 (patch) | |
tree | 58be57180690416272be1167900b74d4a56bfed2 /engine/signal.cpp | |
parent | Fix typo to compile (diff) | |
download | flatland-7170c16a463fdb1f446ab7458270205bf08e7c89.tar.gz flatland-7170c16a463fdb1f446ab7458270205bf08e7c89.zip |
Signal change
Diffstat (limited to 'engine/signal.cpp')
-rw-r--r-- | engine/signal.cpp | 169 |
1 files changed, 169 insertions, 0 deletions
diff --git a/engine/signal.cpp b/engine/signal.cpp new file mode 100644 index 0000000..0a3d887 --- /dev/null +++ b/engine/signal.cpp @@ -0,0 +1,169 @@ +#include "signal.hpp" +#include "task.hpp" + +using namespace std; +using namespace flat::core; + +bool channel::sig_prior_cmp::operator()(const signal& s, const signal& g) const +{ + return s.prior <= g.prior; +} + +map<string, channel*> channel::channels; + +channel::channel(const string& id, task::priority prior) +{ + channel * other = find_channel(id); + + if (!other) + //TODO throw exception + ; + + /* Initialize task, post-process, fifth priority */ + checker = new task<channel>( this, + &channel::post_processing, + 0, + prior); + + string ID = (id.empty()) ? object::random_id() : id; + + set_id(ID); + + channels.insert(pair<string, channel*>(ID, this)); +} + +channel::~channel() +{ + channels.erase(get_id()); + + /* Finalize task */ + delete checker; +} + +void channel::emit(const signal& sig) +{ + if (!sig.priority) { + + /* Execute immediately */ + for (auto listener_s : listener_ss) + listener_s->execute(sig); + + } else + /* Insert in order of priority */ + stack.insert(sig); +} + +void channel::connect(listener_s* l) +{ + /* Control not to double */ + for (auto listener_s : listener_ss) + { + if (listener_s == l) + return; + } + + listener_ss.push_back(l); +} + +void channel::disconnect(listener_s* l) +{ + listener_ss.remove(l); +} + + +channel * channel::findChannel(const string& id) +{ + if (id.empty()) + return 0; + + auto it = channels.find(id); + + return (it == channels.end()) ? 0 : (*it).second; +} + +void channel::post_processing(void*) +{ + if (!stack.empty()) { + + /* for each listener_s, catch signal */ + for (const auto& signal : stack) + { + for (auto listener_s : listener_ss) + listener_s->execute(signal); + } + + stack.clear(); + } +} + + + +/* signal class */ + +signal::signal(FlatObject *sender, const string& id, void *data, Uint8 priority) + : sender(sender), data(data), priority(priority) +{ + set_id(id); +} + +bool signal::emit(const string& channel) const +{ + channel * chan = channel::find_channel(channel); + + if (!chan) + return false; + + /* Finally emit in channel */ + chan->emit(*this); + + return true; +} + + + +/* listener_s class */ + +listener_s::listener_s(const initializer_list<string>& filters) + : filters(filters) {} + +bool listener_s::check_in_filters(const std::string& filter) const +{ + for (const auto& f : filters) + { + if (filter == f) + return true; + } + + return false; +} + +void listener_s::add_filter(const std::string& f) +{ + filters.push_back(f); +} + +void listener_s::remove_filter(const std::string& f) +{ + filters.remove(f); +} + +bool listener_s::connect(const std::string& chan) +{ + channel * c = channel::find_channel(chan); + + if (!c) + c->connect(this); + + return c != 0; +} + +bool listener_s::disconnect(const std::string& chan) +{ + channel * c = channel::find_channel(chan); + + if (!c) + c->connect(this); + + return c != 0; +} + |