#ifndef SIGNAL_SLOT_H
#define SIGNAL_SLOT_H
// compile with:
// g++ -std=c++11 SignalSlot.cpp Test.cpp Variant.cpp main.cpp -o test
#include <vector>
#include <cstdio>
#include <functional>
#include <memory>
#include <utility>
#include <tuple>
#include "Variant.h"
#include "Pointer.h"
//#include "Containers.h"
#include "Namespace.h"
BEGIN_NAMESPACE
//#define slot_ptr shared_ptr // weak_ptr // shared_ptr
//#define signal_ptr shared_ptr // weak_ptr
#define slot_ptr shared_ptr
#define signal_ptr weak_ptr
template <typename ... Params>
class TSlot
{
public:
template <typename Function, typename ... Ts>
//TSlot(Function a_func, Ts... args)
// : m_callback(a_func), m_args(args...)
TSlot(Function a_func, Variant a_v = Variant())
: m_callback(a_func), m_variant(a_v), m_args(a_v)
{
}
// Objects need to be passed by shared_ptr to properly manage the references to them
template <class Class, typename Method>
TSlot(std::slot_ptr<Class> object, Method a_method, Variant a_v = Variant())
: m_callback(std::bind(a_method, object, std::placeholders::_1)), m_variant(a_v), m_args(a_v)
{
}
void operator()()
{
m_callback(m_variant);
}
void operator()(Variant& a_params)
{
if (m_variant.isValid())
m_callback(m_variant);
else
m_callback(a_params);
}
template <typename T>
void operator()(const T& a_params)
{
Variant v(a_params);
(*this)(v);
}
/*
template <typename ...Ts>
void operator()(Ts ...args) {
m_callback(args...);
}
*/
private:
std::function<void(Params...)> m_callback;
// std::tuple<Params...> m_args;
std::tuple<Variant> m_args;
Variant m_variant;
};
template <typename ... Params>
class TSignal
{
public:
TSignal() : m_insideInvokation(false) {}
void addConnection(std::signal_ptr<TSlot<Params...> > a_delegate) { m_connectionList.push_back(a_delegate); }
void disconnectAll() { m_connectionList.clear(); }
template <typename ...Ts>
void operator()(Ts ... args)
{
if (!m_insideInvokation) // prevent recursion
{
m_insideInvokation = true;
for (auto s : m_connectionList) {
if (auto slot = s.lock())
(*slot)(args...);
else
printf("couldn't get weak ptr\n");
}
m_insideInvokation = false;
}
}
private:
TSignal(TSignal const& a_other) = delete;
TSignal& operator=(TSignal const & a_other) = delete;
bool m_insideInvokation;
std::vector<std::signal_ptr<TSlot<Params... > > > m_connectionList; // weak_ptr needed here
};
typedef TSignal<Variant&> Signal;
typedef TSlot<Variant&> Slot;
// These names may be more familiar to others
typedef Signal Event;
typedef Slot Delegate;
template <class Class, typename Method, typename ... Params>
static inline void connect(TSignal<Params...> & a_signal, std::slot_ptr<Class> a_object, Method a_method, Variant a_v = Variant())
{
a_signal.addConnection(std::make_shared<TSlot<Params...> >(a_object, a_method, a_v));
}
template <typename ... Params>
static inline void connect(TSignal<Params...> & a_signal, TSlot<Params...>& a_slot)
{
a_signal.addConnection(std::make_shared<TSlot<Params...> >(a_slot));
}
END_NAMESPACE
#endif // SIGNAL_SLOT_H