summaryrefslogtreecommitdiffstats
path: root/engine
diff options
context:
space:
mode:
authorancarola <raffaele.ancarola@epfl.ch>2019-01-22 03:09:51 +0100
committerancarola <raffaele.ancarola@epfl.ch>2019-01-22 03:09:51 +0100
commitbd7015d3dd2a3c0df62c552d447dda574543e895 (patch)
tree5e07ac7a6b6d8df30e2a0fcf47561bf588e4b5cf /engine
parentSed (diff)
downloadflatland-bd7015d3dd2a3c0df62c552d447dda574543e895.tar.gz
flatland-bd7015d3dd2a3c0df62c552d447dda574543e895.zip
Woo
Diffstat (limited to 'engine')
-rw-r--r--engine/include/signal.h112
-rw-r--r--engine/signal.cpp56
2 files changed, 151 insertions, 17 deletions
diff --git a/engine/include/signal.h b/engine/include/signal.h
new file mode 100644
index 0000000..db6638b
--- /dev/null
+++ b/engine/include/signal.h
@@ -0,0 +1,112 @@
+#pragma once
+
+#include <map>
+#include <list>
+#include <set>
+#include <initializer_list>
+#include "object.hpp"
+#include "task.hpp"
+#include "types.h"
+#include <functional>
+
+namespace flat
+{
+ namespace core
+ {
+ class signal;
+ class channel;
+ }
+}
+
+class flat::core::signal : virtual public flat::core::object
+{
+
+public:
+
+ flat::core::object * sender;
+ priority prior;
+
+ signal( flat::core::object * sender,
+ const std::string& id = "",
+ priority prior = 5);
+
+ /* Alias to flat::core::channel::emit() */
+ bool emit(const std::string& channel) const;
+
+ enum class priority : uint8_t
+ {
+ instant = 0,
+ highest,
+ high,
+ none,
+ low,
+ lowest
+ };
+};
+
+
+/* Channel class */
+class flat::core::channel : virtual public flat::core::object
+{
+ /* Post processing signal stacking */
+ stack_t stack;
+
+ /* Listeners list */
+ std::list<flat::core::listener> listeners;
+
+ /* Synchronous task checking for signals */
+ task_s * checker;
+
+ /* Channel mapping */
+ static std::map<std::string, channel*> channels;
+
+public:
+
+ flat::core::channel(const std::string& id = "", flat::core::task::priority prior = flat::core::task::priority::none);
+ ~flat::core::channel();
+
+ void emit(const flat::core::signal&);
+
+ void connect(flat::core::listener_s*);
+ void disconnect(flat::core::listener_s*);
+
+ static flat::core::channel * find_channel(const std::string&);
+
+ void post_processing(void*);
+
+ /* Functor for order comparison */
+ struct sig_prior_cmp {
+
+ bool operator()(const flat::core::signal&, const flat::core::signal&) const;
+ };
+
+ typedef std::set<flat::core::signal, sig_prior_cmp> stack_t;
+};
+
+/* Listener class */
+class flat::core::listener : virtual public flat::core::object
+{
+ std::list<std::string> filters;
+
+ bool check_in_filters(const std::string&) const;
+
+ std::function<void(const flat::core::object*)> m_callback;
+
+ flat::core::channel * parent = 0;
+
+public:
+
+ listener( std::function<void()> m_callback,
+ const std::initializer_list<std::string>& 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 flat::core::signal&);
+};
+
diff --git a/engine/signal.cpp b/engine/signal.cpp
index d20d840..98f133e 100644
--- a/engine/signal.cpp
+++ b/engine/signal.cpp
@@ -45,33 +45,33 @@ void channel::emit(const signal& sig)
if (!sig.priority) {
/* Execute immediately */
- for (auto listener_s : listener_ss)
- listener_s->execute(sig);
+ for (auto lis : listeners)
+ lis->execute(sig);
} else
/* Insert in order of priority */
stack.insert(sig);
}
-void channel::connect(listener_s* l)
+void channel::connect(listener* l)
{
/* Control not to double */
- for (auto listener_s : listener_ss)
+ for (auto lis : listeners)
{
- if (listener_s == l)
+ if (lis == l)
return;
}
- listener_ss.push_back(l);
+ listeners.push_back(l);
}
-void channel::disconnect(listener_s* l)
+void channel::disconnect(listener* l)
{
- listener_ss.remove(l);
+ listeners.remove(l);
}
-channel * channel::findChannel(const string& id)
+channel * channel::find_channel(const string& id)
{
if (id.empty())
return 0;
@@ -88,8 +88,8 @@ void channel::post_processing(void*)
/* for each listener_s, catch signal */
for (const auto& signal : stack)
{
- for (auto listener_s : listener_ss)
- listener_s->execute(signal);
+ for (auto l : listeners)
+ l->execute(signal);
}
stack.clear();
@@ -123,10 +123,21 @@ bool signal::emit(const string& channel) const
/* listener_s class */
-listener_s::listener_s(const initializer_list<string>& filters)
- : filters(filters) {}
+listener::listener( std::function<void()> m_callback,
+ const std::initializer_list<std::string>& filters)
-bool listener_s::check_in_filters(const std::string& filter) const
+ : m_callback(m_callback), filters(filters)
+{
+
+}
+
+listener::~listener()
+{
+ if (parent != 0)
+ parent->disconnect(this);
+}
+
+bool listener::check_in_filters(const std::string& filter) const
{
for (const auto& f : filters)
{
@@ -137,23 +148,25 @@ bool listener_s::check_in_filters(const std::string& filter) const
return false;
}
-void listener_s::add_filter(const std::string& f)
+void listener::add_filter(const std::string& f)
{
filters.push_back(f);
}
-void listener_s::remove_filter(const std::string& f)
+void listener::remove_filter(const std::string& f)
{
filters.remove(f);
}
-bool listener_s::connect(const std::string& chan)
+bool listener::connect(const std::string& chan)
{
channel * c = channel::find_channel(chan);
if (!c)
c->connect(this);
+ parent = c;
+
return c != 0;
}
@@ -164,6 +177,15 @@ bool listener_s::disconnect(const std::string& chan)
if (!c)
c->connect(this);
+ parent = 0;
+
return c != 0;
}
+void listener::invoke(const flat::core::signal&)
+{
+ if ((!sig.get_id().empty() && check_in_filters(sig.get_id())) ||
+ (sig.get_id().empty() && filters.empty()))
+ m_callback(sig.sender);
+}
+