feat: fix signaling and implement a ping-pong signal/slot test

This commit is contained in:
AndreaRigoni
2026-02-28 08:58:04 +00:00
parent d56758d0b3
commit 07915295cb
5 changed files with 112 additions and 91 deletions

View File

@@ -116,16 +116,15 @@ public:
connect(typename FunctionPointer<Func1>::Object *sender, Func1 sigf, connect(typename FunctionPointer<Func1>::Object *sender, Func1 sigf,
typename FunctionPointer<Func2>::Object *receiver, Func2 slof) { typename FunctionPointer<Func2>::Object *receiver, Func2 slof) {
SignalBase *sigb = sender->findOrAddSignal(sigf); SignalBase *sigb = sender->findOrAddSignal(sigf);
typedef boost::signals2::signal< ConnectSignal<typename FunctionPointer<Func1>::SignalSignature>(sigb, slof,
typename FunctionPointer<Func2>::SignalSignature> receiver);
SigT;
ConnectSignal(sigb, slof, receiver);
return true; return true;
} }
template <typename FuncT> template <typename FuncT>
static inline bool connect(SignalBase *sigb, FuncT slof, Object *receiver) { static inline bool connect(SignalBase *sigb, FuncT slof, Object *receiver) {
ConnectSignal(sigb, slof, receiver); ConnectSignal<typename FunctionPointer<FuncT>::SignalSignature>(sigb, slof,
receiver);
return true; return true;
} }

View File

@@ -50,8 +50,11 @@ using namespace boost::placeholders;
#define SIGNAL(a) BOOST_STRINGIZE(a) #define SIGNAL(a) BOOST_STRINGIZE(a)
#define _ULIB_DETAIL_SIGNAL_EMIT(_name, ...) \ #define _ULIB_DETAIL_SIGNAL_EMIT(_name, ...) \
static BOOST_AUTO(sig, this->findOrAddSignal(&_name)); \ do { \
sig->operator()(__VA_ARGS__); BOOST_AUTO(sig, this->findOrAddSignal(&_name)); \
if (sig) \
sig->operator()(__VA_ARGS__); \
} while (0)
/** /**
* Utility macro to implement signal emission implementa una delle seguenti: * Utility macro to implement signal emission implementa una delle seguenti:
@@ -84,66 +87,61 @@ template <typename T> struct Signal {
namespace detail { namespace detail {
template <typename FuncT, int arity> struct ConnectSignal {}; template <typename FuncT, typename SigSignature, int arity>
struct ConnectSignal {};
template <typename FuncT> struct ConnectSignal<FuncT, 0> { template <typename FuncT, typename SigSignature>
struct ConnectSignal<FuncT, SigSignature, 0> {
static void connect(SignalBase *sigb, FuncT slof, static void connect(SignalBase *sigb, FuncT slof,
typename FunctionPointer<FuncT>::Object *receiver) { typename FunctionPointer<FuncT>::Object *receiver) {
typedef typedef typename Signal<SigSignature>::type SigT;
typename Signal<typename FunctionPointer<FuncT>::SignalSignature>::type
SigT;
reinterpret_cast<SigT *>(sigb)->connect(slof); reinterpret_cast<SigT *>(sigb)->connect(slof);
} }
}; };
template <typename FuncT> struct ConnectSignal<FuncT, 1> { template <typename FuncT, typename SigSignature>
struct ConnectSignal<FuncT, SigSignature, 1> {
static void connect(SignalBase *sigb, FuncT slof, static void connect(SignalBase *sigb, FuncT slof,
typename FunctionPointer<FuncT>::Object *receiver) { typename FunctionPointer<FuncT>::Object *receiver) {
typedef typedef typename Signal<SigSignature>::type SigT;
typename Signal<typename FunctionPointer<FuncT>::SignalSignature>::type
SigT;
reinterpret_cast<SigT *>(sigb)->connect(boost::bind(slof, receiver)); reinterpret_cast<SigT *>(sigb)->connect(boost::bind(slof, receiver));
} }
}; };
template <typename FuncT> struct ConnectSignal<FuncT, 2> { template <typename FuncT, typename SigSignature>
struct ConnectSignal<FuncT, SigSignature, 2> {
static void connect(SignalBase *sigb, FuncT slof, static void connect(SignalBase *sigb, FuncT slof,
typename FunctionPointer<FuncT>::Object *receiver) { typename FunctionPointer<FuncT>::Object *receiver) {
typedef typedef typename Signal<SigSignature>::type SigT;
typename Signal<typename FunctionPointer<FuncT>::SignalSignature>::type
SigT;
reinterpret_cast<SigT *>(sigb)->connect(boost::bind(slof, receiver, _1)); reinterpret_cast<SigT *>(sigb)->connect(boost::bind(slof, receiver, _1));
} }
}; };
template <typename FuncT> struct ConnectSignal<FuncT, 3> { template <typename FuncT, typename SigSignature>
struct ConnectSignal<FuncT, SigSignature, 3> {
static void connect(SignalBase *sigb, FuncT slof, static void connect(SignalBase *sigb, FuncT slof,
typename FunctionPointer<FuncT>::Object *receiver) { typename FunctionPointer<FuncT>::Object *receiver) {
typedef typedef typename Signal<SigSignature>::type SigT;
typename Signal<typename FunctionPointer<FuncT>::SignalSignature>::type
SigT;
reinterpret_cast<SigT *>(sigb)->connect( reinterpret_cast<SigT *>(sigb)->connect(
boost::bind(slof, receiver, _1, _2)); boost::bind(slof, receiver, _1, _2));
} }
}; };
template <typename FuncT> struct ConnectSignal<FuncT, 4> { template <typename FuncT, typename SigSignature>
struct ConnectSignal<FuncT, SigSignature, 4> {
static void connect(SignalBase *sigb, FuncT slof, static void connect(SignalBase *sigb, FuncT slof,
typename FunctionPointer<FuncT>::Object *receiver) { typename FunctionPointer<FuncT>::Object *receiver) {
typedef typedef typename Signal<SigSignature>::type SigT;
typename Signal<typename FunctionPointer<FuncT>::SignalSignature>::type
SigT;
reinterpret_cast<SigT *>(sigb)->connect( reinterpret_cast<SigT *>(sigb)->connect(
boost::bind(slof, receiver, _1, _2, _3)); boost::bind(slof, receiver, _1, _2, _3));
} }
}; };
template <typename FuncT> struct ConnectSignal<FuncT, 5> { template <typename FuncT, typename SigSignature>
struct ConnectSignal<FuncT, SigSignature, 5> {
static void connect(SignalBase *sigb, FuncT slof, static void connect(SignalBase *sigb, FuncT slof,
typename FunctionPointer<FuncT>::Object *receiver) { typename FunctionPointer<FuncT>::Object *receiver) {
typedef typedef typename Signal<SigSignature>::type SigT;
typename Signal<typename FunctionPointer<FuncT>::SignalSignature>::type
SigT;
reinterpret_cast<SigT *>(sigb)->connect( reinterpret_cast<SigT *>(sigb)->connect(
boost::bind(slof, receiver, _1, _2, _3, _4)); boost::bind(slof, receiver, _1, _2, _3, _4));
} }
@@ -152,15 +150,16 @@ template <typename FuncT> struct ConnectSignal<FuncT, 5> {
} // namespace detail } // namespace detail
template <typename FuncT> SignalBase *NewSignal(FuncT f) { template <typename FuncT> SignalBase *NewSignal(FuncT f) {
// seems to work wow ! return new
return new Signal<void()>::type; typename Signal<typename FunctionPointer<FuncT>::SignalSignature>::type;
} }
template <typename FuncT> template <typename SigSignature, typename FuncT>
void ConnectSignal(SignalBase *sigb, FuncT slof, void ConnectSignal(SignalBase *sigb, FuncT slof,
typename FunctionPointer<FuncT>::Object *receiver) { typename FunctionPointer<FuncT>::Object *receiver) {
detail::ConnectSignal<FuncT, FunctionPointer<FuncT>::arity>::connect( detail::ConnectSignal<FuncT, SigSignature,
sigb, slof, receiver); FunctionPointer<FuncT>::arity>::connect(sigb, slof,
receiver);
} }
} // namespace uLib } // namespace uLib

View File

@@ -19,6 +19,7 @@ set( TESTS
UuidTest UuidTest
TypeIntrospectionTraversal TypeIntrospectionTraversal
OptionsTest OptionsTest
PingPongTest
) )
set(LIBRARIES set(LIBRARIES

View File

@@ -0,0 +1,52 @@
#include "Core/Object.h"
#include "Core/Signal.h"
#include "testing-prototype.h"
#include <iostream>
using namespace uLib;
class Ping : public Object {
public:
signals:
void PingSignal(int count);
public slots:
void OnPong(int count) {
std::cout << "Ping received Pong " << count << std::endl;
if (count > 0)
ULIB_SIGNAL_EMIT(Ping::PingSignal, count - 1);
}
};
void Ping::PingSignal(int count) { ULIB_SIGNAL_EMIT(Ping::PingSignal, count); }
class Pong : public Object {
public:
signals:
void PongSignal(int count);
public slots:
void OnPing(int count) {
std::cout << "Pong received Ping " << count << std::endl;
if (count > 0)
ULIB_SIGNAL_EMIT(Pong::PongSignal, count - 1);
}
};
void Pong::PongSignal(int count) { ULIB_SIGNAL_EMIT(Pong::PongSignal, count); }
int main() {
BEGIN_TESTING(PingPong);
Ping ping;
Pong pong;
std::cout << "Connecting ping to pong" << std::endl;
Object::connect(&ping, &Ping::PingSignal, &pong, &Pong::OnPing);
std::cout << "Connecting pong to ping" << std::endl;
Object::connect(&pong, &Pong::PongSignal, &ping, &Ping::OnPong);
std::cout << "Emitting PingSignal(5)" << std::endl;
ping.PingSignal(5);
END_TESTING;
return 0;
}

View File

@@ -23,73 +23,45 @@
//////////////////////////////////////////////////////////////////////////////*/ //////////////////////////////////////////////////////////////////////////////*/
#include <iostream> #include <iostream>
#include <typeinfo> #include <typeinfo>
#include "testing-prototype.h"
#include "Core/Types.h"
#include "Core/Object.h" #include "Core/Object.h"
#include "Core/Signal.h" #include "Core/Signal.h"
#include "Core/Types.h"
#include "testing-prototype.h"
using namespace uLib; using namespace uLib;
class Ob1 : public Object { class Ob1 : public Object {
public: public:
signals: signals:
void V0(); void V0();
int V1(int a); void V1(int a);
}; };
// should be done by moc // // should be done by moc //
void Ob1::V0() { void Ob1::V0() { ULIB_SIGNAL_EMIT(Ob1::V0); }
ULIB_SIGNAL_EMIT(Ob1::V0);
}
int Ob1::V1(int a) {
ULIB_SIGNAL_EMIT(Ob1::V1,a);
}
void Ob1::V1(int a) { ULIB_SIGNAL_EMIT(Ob1::V1, a); }
class Ob2 : public Object { class Ob2 : public Object {
public slots: public slots:
void PrintV0() { void PrintV0() { std::cout << "Ob2 prints V0\n" << std::flush; }
std::cout << "Ob2 prints V0\n" << std::flush;
}
}; };
class Ob3 : public Object { class Ob3 : public Object {
public slots: public slots:
void PrintV0() { void PrintV0() { std::cout << "Ob3 prints V0\n" << std::flush; }
std::cout << "Ob3 prints V0\n" << std::flush;
}
void PrintNumber(int n) { void PrintNumber(int n) {
std::cout << "Ob3 is printing number: " << n << "\n"; std::cout << "Ob3 is printing number: " << n << "\n";
} }
}; };
int main() { int main() {
BEGIN_TESTING(Signals); BEGIN_TESTING(Signals);
@@ -97,9 +69,9 @@ int main() {
Ob2 ob2; Ob2 ob2;
Ob3 ob3; Ob3 ob3;
Object::connect(&ob1,&Ob1::V0,&ob2,&Ob2::PrintV0); Object::connect(&ob1, &Ob1::V0, &ob2, &Ob2::PrintV0);
Object::connect(&ob1,&Ob1::V0,&ob3,&Ob3::PrintV0); Object::connect(&ob1, &Ob1::V0, &ob3, &Ob3::PrintV0);
Object::connect(&ob1,&Ob1::V1,&ob3,&Ob3::PrintNumber); Object::connect(&ob1, &Ob1::V1, &ob3, &Ob3::PrintNumber);
// not working yet // not working yet
// Object::connect(&ob1,SIGNAL(V0(),&ob2,SLOT(PrintV0()) // Object::connect(&ob1,SIGNAL(V0(),&ob2,SLOT(PrintV0())
@@ -111,5 +83,3 @@ int main() {
END_TESTING; END_TESTING;
} }