summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNao Pross <naopross@thearcway.org>2019-02-02 16:24:04 +0100
committerNao Pross <naopross@thearcway.org>2019-02-02 16:24:04 +0100
commitbdba377cfd20ba7a2971053a527823e84644e243 (patch)
tree48c7c599ff0eb6ae98c8d64dfd1c05c8372d8fba
parentMerge branch 'master' into signal-exp (diff)
downloadflatland-bdba377cfd20ba7a2971053a527823e84644e243.tar.gz
flatland-bdba377cfd20ba7a2971053a527823e84644e243.zip
Update signal_test, fix a few bugs (but doesn't compile yet)
Change: signal_test is now a specific test for signal.cpp instead of a general test.
-rwxr-xr-xconfigure.py6
-rw-r--r--engine/include/core/priority.hpp2
-rw-r--r--engine/include/core/signal.hpp77
-rw-r--r--engine/signal.cpp19
-rw-r--r--test/signal_test.cpp138
5 files changed, 109 insertions, 133 deletions
diff --git a/configure.py b/configure.py
index f0d34f5..0a489bb 100755
--- a/configure.py
+++ b/configure.py
@@ -107,7 +107,11 @@ with open("build.ninja", "w") as bf:
# add tests
add_specific_test(bf, "task_test.cpp", ["engine/task.cpp"])
- add_test(bf, "signal_test.cpp", "build/libflatland.so")
+ add_specific_test(bf, "signal_test.cpp", [
+ "engine/task.cpp",
+ "engine/labelled.cpp",
+ "engine/signal.cpp",
+ ])
print("default build/test/signal_test", file=bf)
diff --git a/engine/include/core/priority.hpp b/engine/include/core/priority.hpp
index 5519327..071b23c 100644
--- a/engine/include/core/priority.hpp
+++ b/engine/include/core/priority.hpp
@@ -45,7 +45,7 @@ namespace flat {
if (auto r = rhs.lock()) {
// if both valid, check their priority
// in case they are the same, left is prioritized
- operator()(l.get(), r.get());
+ return operator()(l.get(), r.get());
} else {
// if right is expired, left is prioritized
return true;
diff --git a/engine/include/core/signal.hpp b/engine/include/core/signal.hpp
index fd7d575..865b48b 100644
--- a/engine/include/core/signal.hpp
+++ b/engine/include/core/signal.hpp
@@ -2,15 +2,13 @@
#include "task.hpp"
#include "types.hpp"
-#include "object.hpp"
#include "priority.hpp"
#include "labelled.hpp"
#include "debug.hpp"
#include <map>
#include <list>
-#include <set>
-#include <initializer_list>
+#include <tuple>
#include <functional>
#include <memory>
#include <cstddef>
@@ -23,7 +21,7 @@
namespace flat::core
{
/* forward decls */
- template<typename F, typename ...Args>
+ template<typename ...Args>
class listener;
namespace helper
@@ -37,8 +35,9 @@ namespace flat::core
class signal : public prioritized
{
public:
- signal(const signal& other) = delete;
+ // signal(const signal& other) = delete;
signal& operator=(const signal& other) = delete;
+ virtual ~signal() {}
protected:
signal(priority_t p) : prioritized(p) {}
@@ -58,9 +57,13 @@ namespace flat::core
friend class listener<Args...>;
public:
- signal(Args&&... args, priority_t p = priority_t::none)
- : std::tuple<Args...>(std::forward<Args>(args)...),
- helper::signal(p) {}
+ constexpr signal(Args& ...args)
+ : std::tuple<Args...>((args)...),
+ helper::signal(priority_t::none) {}
+
+ constexpr signal(Args&& ...args)
+ : std::tuple<Args...>(std::move(args)...),
+ helper::signal(priority_t::none) {}
};
@@ -80,9 +83,10 @@ namespace flat::core
protected:
listener() {}
+ virtual ~listener() {}
public:
- virtual bool invoke(std::shared_ptr<const helper::signal> s) = 0;
+ virtual bool invoke(std::shared_ptr<const helper::signal> s) const = 0;
};
}
@@ -91,19 +95,28 @@ namespace flat::core
* is an object holding a callback, that can be only called by passing
* a signal<...Args> object, which contains the arguments for the callback.
*/
- template <typename F, typename ...Args>
- class listener : public helper::listener
+ template <typename ...Args>
+ class listener : public helper::listener
{
public:
using callback = typename std::function<void(Args...)>;
using ptr = typename std::shared_ptr<listener<Args...>>;
listener() = delete;
- listener(F&& f) : m_callback(std::move(f)) {}
+ listener(callback f) : m_callback(f) {}
// attempt to call m_callback with s as argument
// m_callback is called only if the signature matches
- bool invoke(std::shared_ptr<const helper::signal> s) override;
+ bool invoke(std::shared_ptr<const helper::signal> s) const override
+ {
+ const signal<Args...> *p = dynamic_cast<const signal<Args...> *>(s.get());
+
+ if (p != nullptr)
+ std::apply(m_callback, *p);
+
+ // return true if p was called
+ return (p != nullptr);
+ }
private:
callback m_callback;
@@ -119,7 +132,7 @@ namespace flat::core
{
private:
// this is a set because sets do not allow identical elements
- std::set<std::weak_ptr<helper::listener>> m_listeners;
+ std::list<std::weak_ptr<helper::listener>> m_listeners;
queue<std::shared_ptr<helper::signal>> m_signals;
/// task to call
@@ -135,38 +148,52 @@ namespace flat::core
// it does not make sense to create a channel with the same name
channel(const channel&) = delete;
channel& operator=(const channel&) = delete;
-
+
/// add a signal to the queue/stack of signals (m_signals)
template<class ...Args>
- void emit(const signal<Args...>& sig)
+ void emit(const signal<Args...> sig)
{
// insert signal and decay it to a non-template
// unique_ptr<helper::signal>
- m_signals.insert(std::make_unique<helper::signal>(sig));
+ m_signals.insert(std::make_shared<helper::signal>(sig));
}
/// for each signal accumulated, call each listener
void broadcast();
/// connect a standalone function
- template<typename F, typename ...Args>
- std::shared_ptr<listener<F, Args...>> connect(listener<F, Args...>::callback f)
+ template<typename R, typename ...Args>
+ std::shared_ptr<listener<Args...>> _connect(std::function<R(Args...)> f)
{
auto lis_ptr = std::make_shared<listener<Args...>>(f);
// insert listener and decay it to a non-template
// weak_ptr<helper::listener>
- m_listeners.insert(lis_ptr);
+ m_listeners.push_back(
+ static_cast<std::weak_ptr<helper::listener>>(lis_ptr)
+ );
return lis_ptr;
}
+ template<typename R, typename ...Args>
+ std::shared_ptr<listener<Args...>> connect(R (*f)(Args...))
+ {
+ return _connect(static_cast<std::function<R(Args...)>>(
+ [=](Args ...args) -> R {
+ return f((args)...);
+ })
+ );
+ }
+
/// connect a member function
- template<typename R, typename T, typename F, typename ...Args>
- std::shared_ptr<listener<F, Args...>> connect(R T::*mf, T& obj)
+ template<typename R, typename T, typename ...Args>
+ std::shared_ptr<listener<Args...>> connect(R (T::*mf)(Args ...args), T* obj)
{
- return connect([mf](Args&& ...args) -> R {
- return (mf(args),...);
- });
+ return _connect(static_cast<std::function<R(Args...)>>(
+ [=](Args ...args) -> R {
+ return (obj->*mf)((args)...);
+ })
+ );
}
};
}
diff --git a/engine/signal.cpp b/engine/signal.cpp
index 362fbdf..86861d9 100644
--- a/engine/signal.cpp
+++ b/engine/signal.cpp
@@ -1,26 +1,11 @@
#include "core/signal.hpp"
#include "object.hpp"
-#include <functional>
#include "flatland.hpp"
-
#include "debug.hpp"
-using namespace flat::core;
-
-/* listener */
-
-template<typename F, typename ...Args>
-bool listener<F, Args ...>::invoke(std::shared_ptr<const helper::signal> s)
-{
- const signal<Args...> *p = dynamic_cast<const signal<Args...> *>(s.get());
-
- if (p != nullptr)
- std::apply(m_callback, *p);
-
- // return true if p was called
- return (p != nullptr);
-}
+#include <functional>
+using namespace flat::core;
/* channel */
diff --git a/test/signal_test.cpp b/test/signal_test.cpp
index 3b3fab2..b234672 100644
--- a/test/signal_test.cpp
+++ b/test/signal_test.cpp
@@ -1,126 +1,86 @@
#include "core/signal.hpp"
#include "core/task.hpp"
-#include "object.hpp"
-#include "window.hpp"
-#include "flatland.hpp"
-#include "exceptions/forcequit.hpp"
-
#include "debug.hpp"
-using namespace std;
-using namespace flat;
-using namespace flat::core;
-
+#include <iostream>
-class sender : public object
-{
- const char *m_message;
- channel::ptr m_chan;
-public:
-
- sender(const char * message, channel::ptr chan) : m_message(message), m_chan(chan)
- {
- }
+using namespace flat::core;
- void send()
- {
- signal<const char*> msg(m_message);
- m_chan->emit(m_msg);
- }
-};
-void function_listener(const char *msg)
-{
- cout << "Funzione: " << msg << endl;
+void got_signal(int x, double y) {
+ npdebug("got signal with x=", x, " and y=", y);
}
-class c_listener
+
+class test_emitter
{
- std::shared_ptr<listener<const char*>> lis;
+private:
+ channel& m_chan;
public:
+ test_emitter(channel& ch) : m_chan(ch) {}
- c_listener(channel::ptr chan)
- {
- m_lis = chan->connect(&c_listener::method_listener, this);
+ void send_str(const std::string& msg) {
+ m_chan.emit(signal(msg));
+ npdebug("emitted signal with msg=", msg);
}
- void method_listener(const char *msg)
- {
- cout << "Metodo: " << msg << endl;
+ void send_num(int n) {
+ m_chan.emit(signal(n));
+ npdebug("emitted signal with n=", n);
}
};
-/* Objects definition */
-
-channel::ptr alpha;
-sender * m_sender;
-c_listener * m_listener;
-std::shared_ptr<listener<const char*>> f_listener;
-int steps = 0;
-
-void lifeloop()
+class test_listener
{
- if (!(steps % 10))
- cout << "Step: " << steps << endl;
-
- if (!(steps % 40))
- m_sender->send();
+private:
+ template<typename T>
+ using listener_of = typename std::shared_ptr<listener<T>>;
- if (++steps > 200)
- {
- signal<const char*> quit("quit");
+ listener_of<const std::string&> str_lis;
+ listener_of<int> num_lis;
- // quit request
- flat::core_channel().emit(quit);
+public:
+ test_listener(channel& ch) {
+ str_lis = ch.connect(&test_listener::got_string, this);
+ num_lis = ch.connect(&test_listener::got_number, this);
}
- if (steps > 205)
- throw flat::ForceQuit("Too many steps");
-}
-
-int main()
-{
- FlatWindow win(600, 900, "Test 3");
- flat_status status;
-
- npdebug("Initializing channel alpha")
-
- alpha = channel::create("alpha");
-
- if (alpha == nullptr)
- {
- cout << "Could not create channel alpha" << endl;
- return -1;
+ void got_string(const std::string& msg) {
+ npdebug("got signal with msg=", msg);
}
- // create sender
- m_sender = new sender("Ciao", alpha);
- m_listener = new c_listener(alpha);
-
- // Connect listener to alpha channel
- f_listener = alpha->connect(&function_listener);
+ void got_number(int n) {
+ npdebug("got signal with n=", n);
+ }
+};
- // bind counter task
- task::ptr looptask = flat::main_job().delegate_task(lifeloop);
- init_flatland(&win, status, 60);
+int main() {
+ // create a job to propagate signals
+ job broadcaster;
+
+ // create a channel
+ channel chan(broadcaster);
- npdebug("Deleting m_sender")
- delete m_sender;
+ // test with a function
+ chan.connect(got_signal);
+ chan.emit(signal(100, 293.0));
- npdebug("Deleting m_listener")
- delete m_listener;
+ // call job to propagate signals
+ broadcaster();
- alpha = nullptr; // out of scope
- f_listener = nullptr;
+ // test with members
+ test_emitter e(chan);
+ test_listener l(chan);
- npdebug("alpha use count: ", alpha.use_count())
- npdebug("f_listener use count: ", f_listener.use_count())
+ e.send_str("hello world!");
+ e.send_num(42);
- npdebug("Exiting")
+ // call job to propagate signals
+ broadcaster();
return 0;
}