summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorancarola <raffaele.ancarola@epfl.ch>2019-01-23 19:43:09 +0100
committerancarola <raffaele.ancarola@epfl.ch>2019-01-23 19:43:09 +0100
commit40a2e6ae3d17e271f9eaa07a53d934fc5d5457db (patch)
tree0da332dbff1d621306d5bfc4d1e54fccb795a206
parentTask debugging (diff)
downloadflatland-40a2e6ae3d17e271f9eaa07a53d934fc5d5457db.tar.gz
flatland-40a2e6ae3d17e271f9eaa07a53d934fc5d5457db.zip
Labelled, signal
-rw-r--r--engine/include/core/labelled.hpp26
-rw-r--r--engine/include/core/object.hpp38
-rw-r--r--engine/include/core/signal.hpp60
-rw-r--r--engine/include/flatland.h20
-rw-r--r--engine/labelled.cpp19
-rw-r--r--engine/object.cpp62
-rw-r--r--engine/signal.cpp126
7 files changed, 178 insertions, 173 deletions
diff --git a/engine/include/core/labelled.hpp b/engine/include/core/labelled.hpp
new file mode 100644
index 0000000..7363e8d
--- /dev/null
+++ b/engine/include/core/labelled.hpp
@@ -0,0 +1,26 @@
+#pragma once
+
+#include <list>
+#include <vector>
+#include <string>
+#include <initializer_list>
+
+#include "types.hpp"
+
+namespace flat
+{
+ namespace core
+ {
+ class labelled;
+ }
+}
+
+struct flat::core::labelled
+{
+ const std::string label;
+
+ labelled(const std::string& label = "");
+
+ static std::string random_label(uint8_t length = 8);
+};
+
diff --git a/engine/include/core/object.hpp b/engine/include/core/object.hpp
index 1992d2a..cd5da5e 100644
--- a/engine/include/core/object.hpp
+++ b/engine/include/core/object.hpp
@@ -1,42 +1,12 @@
#pragma once
-#include <list>
-#include <vector>
-#include <string>
-#include <initializer_list>
-
-#include "types.hpp"
-
namespace flat
{
namespace core
{
- class object;
+ struct object
+ {
+ // it exists
+ };
}
}
-
-class flat::core::object
-{
- std::string id;
-
- /* Common list of objects */
- static std::list<object*> all_objects;
-
-public:
-
- object();
- ~object();
-
- void set_id(const std::string&);
-
- const std::string& get_id() const;
-
- /* Static accessors to allObject */
-
- static bool is_allocated(object*);
-
- static std::vector<object*>& get_by_id(const std::string& id, std::vector<object*>&);
-
- static std::string random_id(uint8_t length = 8);
-};
-
diff --git a/engine/include/core/signal.hpp b/engine/include/core/signal.hpp
index 2393bc7..4270aa5 100644
--- a/engine/include/core/signal.hpp
+++ b/engine/include/core/signal.hpp
@@ -8,73 +8,92 @@
#include "task.hpp"
#include "types.h"
#include <functional>
+#include <memory>
#include "priority.hpp"
+#include "labelled.hpp"
namespace flat
{
namespace core
{
- class signal : virtual public object, public prioritized
+ class signal : virtual public labelled, virtual public prioritized
{
public:
object * sender;
- void * data; // TODO, avoid this void pointer
+ package m_package;
priority_t prior;
signal( object * sender,
const std::string& id = "",
- void * data,
+ void * data = 0,
priority_t prior = priority_t::none);
/* Alias to flat::core::channel::emit() */
bool emit(const std::string& channel) const;
+
+ struct package
+ {
+ package(void *data) : data(data) {}
+
+ template<class T>
+ T * get() {
+
+ return dynamic_cast<T>(data);
+ }
+
+ void * data;
+ };
};
/* Channel class */
- class channel : virtual public object
+ class channel : virtual public labelled
{
/* Post processing signal stacking */
queue<signal> stack;
/* Listeners list */
- std::list<listener*> listeners;
+ std::list<std::weak_ptr<listener>> listeners;
/* Synchronous task checking for signals */
- task * checker;
+ task::ptr checker;
/* Channel mapping */
- static std::map<std::string, channel*> channels;
+ static std::map<std::string, std::weak_ptr<channel>> channels;
public:
channel(const std::string& id = "", priority_t task_priority = priority_t::none);
~channel();
+
+ void start();
+ bool map();
void emit(const signal&);
- void connect(const listener*);
- void disconnect(const listener*);
+ bool connect(listener::ptr l);
+ void disconnect(listener::ptr l);
- static channel * find_channel(const std::string&);
+ static ptr find(const std::string&);
+
+ static ptr create(const string& id, priority_t prior);
- void post_processing();
+ void check_and_call();
+
+ typedef shared_ptr<channel> ptr;
};
/* Listener class */
- class listener : virtual public object
+ class listener
{
-
std::list<std::string> filters;
bool check_in_filters(const std::string&) const;
callback_t m_callback;
-
- channel * parent;
public:
@@ -93,14 +112,15 @@ namespace flat
/* Allow to safely bind e functor */
template<class T>
- static listener create( const (T::*method(const object*, void*))& fct,
- T* ptr,
- const std::initializer_list<std::string>& filters = {})
+ static ptr make( const (T::*method(const object*, void*))& fct,
+ T* obj,
+ const std::initializer_list<std::string>& filters = {})
{
- return listener(std::bind(fct, ptr), filters);
+ return new listener(std::bind(fct, ptr), filters);
}
- typedef std::function<void(const object*, void*)> callback_t;
+ typedef std::function<void(const object*, signal::package)> callback_t;
+ typedef shared_ptr<listener> ptr;
};
}
diff --git a/engine/include/flatland.h b/engine/include/flatland.h
index 27d2d12..c5f3eb5 100644
--- a/engine/include/flatland.h
+++ b/engine/include/flatland.h
@@ -1,6 +1,8 @@
#ifndef __FLATLAND_H__
#define __FLATLAND_H__
+namespace flat {
+
class FlatWindow;
typedef void (*gameloop)(float);
@@ -38,11 +40,21 @@ struct flat_status
int init_flatland(FlatWindow*, gameloop, const flat_status&, float fps = 60);
void quit_flatland();
-/* Core channel */
+namespace core {
+
+ class job;
+ class task;
+ class channel;
+}
+
+/* Engine channels */
-class SignalChannel;
+channel& core_chan();
+channel& error_chan();
-SignalChannel * getCoreChannel();
+/* Main job access */
+
+job& game_job();
/* Window and status accessors */
@@ -58,4 +70,6 @@ void load_flatland_status(const flat_status&);
extern float flatland_dt;
+}
+
#endif
diff --git a/engine/labelled.cpp b/engine/labelled.cpp
new file mode 100644
index 0000000..ede43d6
--- /dev/null
+++ b/engine/labelled.cpp
@@ -0,0 +1,19 @@
+#include "core/labelled.hpp"
+
+#include <stdlib.h>
+
+using namespace std;
+using namespace flat::core;
+
+labelled::labelled(const std::string& label) : label(label) {}
+
+string labelled::random_id(uint8_t length) {
+
+ string out;
+
+ for (uint8_t i = 0; i < length; ++i)
+ out += (char)(rand() % 93 + 33);
+
+ return out;
+}
+
diff --git a/engine/object.cpp b/engine/object.cpp
deleted file mode 100644
index 7134061..0000000
--- a/engine/object.cpp
+++ /dev/null
@@ -1,62 +0,0 @@
-#include "core/object.hpp"
-
-#include <stdlib.h>
-
-using namespace std;
-using namespace flat::core;
-
-list<object*> object::all_objects;
-
-object::object()
-{
- /* Collect this object */
- object::all_objects.push_back(this);
-}
-
-object::~object()
-{
- /* Eliminate this object reference */
- object::all_objects.remove(this);
-}
-
-void object::set_id(const string& id)
-{
- this->id = id;
-}
-
-const string& object::get_id() const
-{
- return id;
-}
-
-string object::random_id(uint8_t length) {
-
- string out;
-
- for (uint8_t i = 0; i < length; ++i)
- out += (char)(rand() % 93 + 33);
-
- return out;
-}
-
-bool object::is_allocated(object *obj)
-{
- for (object * o : object::all_objects)
- {
- if (o == obj)
- return true;
- }
-
- return false;
-}
-
-vector<object*>& object::get_by_id(const string& id, vector<object*>& l)
-{
- for (object * obj : object::all_objects)
- {
- if (id == obj->get_id())
- l.push_back(obj);
- }
-
- return l;
-}
diff --git a/engine/signal.cpp b/engine/signal.cpp
index 5eac3eb..2af4a68 100644
--- a/engine/signal.cpp
+++ b/engine/signal.cpp
@@ -1,5 +1,6 @@
#include "core/signal.hpp"
#include <functional>
+#include "flatland.h"
using namespace std;
using namespace flat::core;
@@ -7,30 +8,27 @@ using namespace flat::core;
map<string, channel*> channel::channels;
channel::channel(const string& id, priority_t prior)
+ : labelled(id.empty() ? object::random_id(): id)
{
- channel * other = find_channel(id);
-
- if (!other)
- //TODO throw exception
- ;
-
- /* Initialize task, post-process, fifth priority */
- checker = new task( bind(&channel::post_processing, this),
- prior);
-
- string ID = (id.empty()) ? object::random_id() : id;
+}
- set_id(ID);
+channel::~channel()
+{
+ // by default it should be there
+ channels.erase(label);
+}
- channels.insert(pair<string, channel*>(ID, this));
+void channel::start()
+{
+ // Initialize task
+ checker = flat::game_job().delegate_task<channel>(&channel::check_and_call, this, prior);
}
-channel::~channel()
+bool channel::map()
{
- channels.erase(get_id());
+ channel * other = find_channel(label);
- /* Finalize task */
- delete checker;
+ return other ? false : channels.insert(pair<string, channel*>(label, this));
}
void channel::emit(const signal& sig)
@@ -38,52 +36,77 @@ void channel::emit(const signal& sig)
stack.insert(sig);
}
-void channel::connect(const listener* l)
+bool channel::connect(listener::ptr l)
{
/* Control not to double */
for (auto lis : listeners)
{
- if (lis == l)
- return;
+ if (lis.get() == l.get())
+ return false;
}
listeners.push_back(l);
+ return true;
}
-void channel::disconnect(const listener* l)
+void channel::disconnect(listener::ptr l)
{
listeners.remove(l);
}
+channel::ptr channel::create(const string& id, priority_t prior)
+{
+ ptr out = std::make_ptr(new channel(id, prior));
+
+ if (!out.map())
+ return nullptr;
+
+ out.start();
+
+ return out;
+}
-channel * channel::find_channel(const string& id)
+channel::ptr channel::find(const string& id)
{
if (id.empty())
- return 0;
+ return nullptr;
auto it = channels.find(id);
- return (it == channels.end()) ? 0 : (*it).second;
+ return (it == channels.end()) ? nullptr : (*it).second.lock();
}
-void channel::post_processing()
+void channel::check_and_call()
{
if (!stack.empty()) {
+ vector<weak_ptr<listener>> to_erase;
+
// TODO, maybe it exists pop
/* for each listener_s, catch signal */
- for (const auto& signal : stack)
+
+ for (auto l : listeners)
{
- for (auto l : listeners)
- l->invoke(signal);
+ listener::ptr pt;
+
+ if (pt = l.lock())
+ {
+ for (const auto& sig : stack)
+ l->invoke(sig);
+ }
+ else
+ to_erase.push_back(l);
}
+
+ /* Erase invalidated listeners */
+ for (auto e : to_erase)
+ listeners.remove(e);
- stack.clear();
+ stack.clear(); // TODO not so efficient
}
}
-
/* signal class */
signal::signal( object *sender,
@@ -91,40 +114,39 @@ signal::signal( object *sender,
void *data,
priority_t priority)
- : sender(sender), data(data), priority(priority)
+ : labelled(id),
+ sender(sender),
+ m_package(package(data)),
+ priority(priority)
{
- set_id(id);
}
-bool signal::emit(const string& channel) const
+bool signal::emit(const string& chan) const
{
- channel * chan = channel::find_channel(channel);
+ channel::ptr c = channel::find(chan);
- if (!chan)
+ if (!c)
return false;
/* Finally emit in channel */
- chan->emit(*this);
+ c->emit(*this);
return true;
}
-
/* listener_s class */
listener::listener( callback_t m_callback,
const initializer_list<string>& filters)
- : m_callback(m_callback), filters(filters), parent(0)
+ : m_callback(m_callback), filters(filters)
{
}
listener::~listener()
{
- if (parent != 0)
- parent->disconnect(this);
}
bool listener::check_in_filters(const string& filter) const
@@ -150,32 +172,28 @@ void listener::remove_filter(const string& f)
bool listener::connect(const string& chan)
{
- channel * c = channel::find_channel(chan);
+ channel::ptr c = channel::find(chan);
if (!c)
c->connect(this);
- parent = c;
-
- return c != 0;
+ return c;
}
-bool listener_s::disconnect(const string& chan)
+bool listener::disconnect(const string& chan)
{
- channel * c = channel::find_channel(chan);
+ channel::ptr c = channel::find_channel(chan);
if (!c)
- c->connect(this);
-
- parent = 0;
+ c->disconnect(this);
- return c != 0;
+ return c;
}
-void listener::invoke(const signal&)
+void listener::invoke(const signal& sig)
{
- if ( (!sig.get_id().empty() && check_in_filters(sig.get_id())) ||
- (sig.get_id().empty() && filters.empty()))
- m_callback(sig.sender);
+ if ( (!sig.label.empty() && check_in_filters(sig.label)) ||
+ (sig.label.empty() && filters.empty()))
+ m_callback(sig.sender, sig.m_package);
}