summaryrefslogtreecommitdiffstats
path: root/engine/include/core/signal.hpp
diff options
context:
space:
mode:
authorNao Pross <naopross@thearcway.org>2019-02-02 22:49:46 +0100
committerNao Pross <naopross@thearcway.org>2019-02-02 22:49:46 +0100
commit02acb58b46192660b9a1ba337c037770801e847e (patch)
tree2a6e63da483498d63aaeab1e0b62b86daee002e8 /engine/include/core/signal.hpp
parentFix all template errors, it compiles! (but doesn't work yet) (diff)
downloadflatland-02acb58b46192660b9a1ba337c037770801e847e.tar.gz
flatland-02acb58b46192660b9a1ba337c037770801e847e.zip
Finish signal, it compiles signal_test and works(!!)
But the whole library doesn't compile yet
Diffstat (limited to 'engine/include/core/signal.hpp')
-rw-r--r--engine/include/core/signal.hpp99
1 files changed, 61 insertions, 38 deletions
diff --git a/engine/include/core/signal.hpp b/engine/include/core/signal.hpp
index 7b5ac3b..a820880 100644
--- a/engine/include/core/signal.hpp
+++ b/engine/include/core/signal.hpp
@@ -7,12 +7,11 @@
#include "debug.hpp"
#include <map>
-#include <list>
#include <tuple>
+#include <list>
#include <functional>
#include <memory>
#include <cstddef>
-#include <type_traits>
namespace flat::core
@@ -41,7 +40,7 @@ namespace flat::core
/* class signal<...Args>
*
- * is a specialized tuple that contains function arguments (...Args)
+ * is a tuple wrapper that contains function arguments (...Args)
* that are later used to call a callback stored in a listener.
*/
template <typename ...Args>
@@ -49,8 +48,18 @@ namespace flat::core
{
const std::tuple<Args...> args;
- explicit constexpr signal(Args... _args)
- : args(std::move(_args)...) {}
+ /// copy constructor
+ explicit constexpr signal(const Args&... _args)
+ : args(_args...) {}
+
+ /// move constructor
+ explicit constexpr signal(Args&&... _args)
+ : args(std::forward<Args>(_args)...) {}
+
+ // TODO: if needed add copy constructor and move constructor
+ // not needed yet
+ // explicit constexpr signal(const signal<Args...>& other)
+ // : helper::signal(), args(other.args) {}
};
@@ -62,7 +71,7 @@ namespace flat::core
* pointer type. To make anything with it must be first downcasted to a
* core::listener<Args...>
*/
- class listener
+ class listener : public std::enable_shared_from_this<listener>
{
protected:
explicit listener() {}
@@ -83,21 +92,31 @@ namespace flat::core
{
public:
using callback = typename std::function<void(Args...)>;
- using ptr = typename std::shared_ptr<listener<Args...>>;
explicit listener(callback f) : m_callback(f) {}
+
+ // TODO: remove
+ ~listener() {
+ npdebug("deleted listener ", this);
+ }
// 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) const override
{
+ // TODO: shared dynamic pointer cast
const signal<Args...> *p = dynamic_cast<const signal<Args...> *>(s.get());
- if (p != nullptr)
- std::apply(m_callback, p->args);
+ // if dynamic cast fails
+ if (p == nullptr) {
+ npdebug("invoked listener ", this, " with non-matching signal ", s);
+ return false;
+ }
+
+ npdebug("invoked listener ", this, " with signal ", p);
+ std::apply(m_callback, p->args);
- // return true if p was called
- return (p != nullptr);
+ return true;
}
private:
@@ -119,6 +138,25 @@ namespace flat::core
/// task to call
std::shared_ptr<task> m_broadcast;
+
+ /// connect a closure / lambda (this is a helper), see others below
+ 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 pointer
+ m_listeners.push_front(
+ // decay shared_ptr to weak_ptr
+ // TODO: static weak
+ static_cast<std::weak_ptr<helper::listener>>(
+ // decay listener to helper::listener
+ std::static_pointer_cast<helper::listener>(lis_ptr)
+ )
+ );
+
+ return lis_ptr;
+ }
public:
using ptr = std::shared_ptr<channel>;
@@ -128,30 +166,24 @@ namespace flat::core
/// 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_shared<helper::signal>(sig));
- }
+ // create a shared_ptr
+ auto p = std::make_shared<signal<Args...>>(sig)
- /// for each signal accumulated, call each listener
- void broadcast();
+ npdebug("emitted signal ", p);
- /// connect a standalone function
- 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.push_back(
- static_cast<std::weak_ptr<helper::listener>>(lis_ptr)
+ // insert pointer
+ m_signals.insert(
+ // decay signal to helper::signal
+ std::static_pointer_cast<helper::signal>(p)
);
-
- return lis_ptr;
}
+ /// for each signal accumulated, call each listener
+ void broadcast();
+
+ /// connect a function
template<typename R, typename ...Args>
std::shared_ptr<listener<Args...>> connect(R (*f)(Args...))
{
@@ -175,12 +207,3 @@ namespace flat::core
};
}
-
-namespace std
-{
- template<typename... Args>
- struct tuple_size<flat::core::signal<Args...>>
- {
- constexpr static std::size_t value = (0 + ... + sizeof(Args));
- };
-}