Files
uLib/src/Core/Signal.h

168 lines
6.0 KiB
C++

/*//////////////////////////////////////////////////////////////////////////////
// CMT Cosmic Muon Tomography project //////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
Copyright (c) 2014, Universita' degli Studi di Padova, INFN sez. di Padova
All rights reserved
Authors: Andrea Rigoni Garola < andrea.rigoni@pd.infn.it >
------------------------------------------------------------------
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 3.0 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library.
//////////////////////////////////////////////////////////////////////////////*/
#ifndef U_CORE_SIGNAL_H
#define U_CORE_SIGNAL_H
#include <boost/typeof/typeof.hpp>
#include <boost/signals2/signal.hpp>
#include <boost/signals2/signal_type.hpp>
#include <boost/signals2/slot.hpp>
#include "Function.h"
#include <boost/bind/bind.hpp>
using namespace boost::placeholders;
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// Signals macro //
#define default(vlaue)
#define slots
#define signals /*virtual void init_signals();*/ public
#define emit
#define SLOT(a) BOOST_STRINGIZE(a)
#define SIGNAL(a) BOOST_STRINGIZE(a)
#define _ULIB_DETAIL_SIGNAL_EMIT(_name, ...) \
do { \
BOOST_AUTO(sig, this->findOrAddSignal(&_name)); \
if (sig) \
sig->operator()(__VA_ARGS__); \
} while (0)
/**
* Utility macro to implement signal emission implementa una delle seguenti:
*
* // metodo standard con cast //
* SignalBase * sig = this->findSignal((void (Ob1::*)(void))&Ob1::V0);
* typedef Signal<void()>::type SigT;
* if(sig) reinterpret_cast<SigT*>(sig)->operator()();
*
* // cast automatico //
* static BOOST_AUTO(sig,this->findOrAddSignal(&Ob1::V0));
* sig->operator()();
*/
#define ULIB_SIGNAL_EMIT(_name, ...) \
_ULIB_DETAIL_SIGNAL_EMIT(_name, __VA_ARGS__)
namespace uLib {
// A boost::signal wrapper structure ///////////////////////////////////////////
// TODO ...
typedef boost::signals2::signal_base SignalBase;
template <typename T> struct Signal {
typedef boost::signals2::signal<T> type;
};
////////////////////////////////////////////////////////////////////////////////
namespace detail {
template <typename FuncT, typename SigSignature, int arity>
struct ConnectSignal {};
template <typename FuncT, typename SigSignature>
struct ConnectSignal<FuncT, SigSignature, 0> {
static void connect(SignalBase *sigb, FuncT slof,
typename FunctionPointer<FuncT>::Object *receiver) {
typedef typename Signal<SigSignature>::type SigT;
reinterpret_cast<SigT *>(sigb)->connect(slof);
}
};
template <typename FuncT, typename SigSignature>
struct ConnectSignal<FuncT, SigSignature, 1> {
static void connect(SignalBase *sigb, FuncT slof,
typename FunctionPointer<FuncT>::Object *receiver) {
typedef typename Signal<SigSignature>::type SigT;
reinterpret_cast<SigT *>(sigb)->connect(boost::bind(slof, receiver));
}
};
template <typename FuncT, typename SigSignature>
struct ConnectSignal<FuncT, SigSignature, 2> {
static void connect(SignalBase *sigb, FuncT slof,
typename FunctionPointer<FuncT>::Object *receiver) {
typedef typename Signal<SigSignature>::type SigT;
reinterpret_cast<SigT *>(sigb)->connect(boost::bind(slof, receiver, _1));
}
};
template <typename FuncT, typename SigSignature>
struct ConnectSignal<FuncT, SigSignature, 3> {
static void connect(SignalBase *sigb, FuncT slof,
typename FunctionPointer<FuncT>::Object *receiver) {
typedef typename Signal<SigSignature>::type SigT;
reinterpret_cast<SigT *>(sigb)->connect(
boost::bind(slof, receiver, _1, _2));
}
};
template <typename FuncT, typename SigSignature>
struct ConnectSignal<FuncT, SigSignature, 4> {
static void connect(SignalBase *sigb, FuncT slof,
typename FunctionPointer<FuncT>::Object *receiver) {
typedef typename Signal<SigSignature>::type SigT;
reinterpret_cast<SigT *>(sigb)->connect(
boost::bind(slof, receiver, _1, _2, _3));
}
};
template <typename FuncT, typename SigSignature>
struct ConnectSignal<FuncT, SigSignature, 5> {
static void connect(SignalBase *sigb, FuncT slof,
typename FunctionPointer<FuncT>::Object *receiver) {
typedef typename Signal<SigSignature>::type SigT;
reinterpret_cast<SigT *>(sigb)->connect(
boost::bind(slof, receiver, _1, _2, _3, _4));
}
};
} // namespace detail
template <typename FuncT> SignalBase *NewSignal(FuncT f) {
return new
typename Signal<typename FunctionPointer<FuncT>::SignalSignature>::type;
}
template <typename SigSignature, typename FuncT>
void ConnectSignal(SignalBase *sigb, FuncT slof,
typename FunctionPointer<FuncT>::Object *receiver) {
detail::ConnectSignal<FuncT, SigSignature,
FunctionPointer<FuncT>::arity>::connect(sigb, slof,
receiver);
}
} // namespace uLib
#endif // SIGNAL_H