Skip to content

Commit

Permalink
Allow lambda handlers for signals with data
Browse files Browse the repository at this point in the history
  • Loading branch information
CendioOssman committed Feb 25, 2025
1 parent 6149e82 commit b497ccb
Show file tree
Hide file tree
Showing 2 changed files with 98 additions and 3 deletions.
32 changes: 32 additions & 0 deletions common/core/Object.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,9 +71,14 @@ namespace core {
// lambda has a capture list, then an object must also be specified
// to control the lifetime.
Connection connectSignal(const char* name, void (*callback)());
template<typename I>
Connection connectSignal(const char* name, void (*callback)(I));

Connection connectSignal(const char* name, Object* obj,
const std::function<void()>& callback);
template<typename I>
Connection connectSignal(const char* name, Object* obj,
const std::function<void(I)>& callback);

// disconnectSignal() unregisters a method that was previously
// registered using connectSignal().
Expand Down Expand Up @@ -226,6 +231,33 @@ namespace core {
typeid(I).hash_code());
}

template<typename I>
Connection Object::connectSignal(const char* name,
void (*callback)(I))
{
emitter_t emitter = [callback](const any& info) {
assert(info.has_value());
using I_d = typename std::decay<I>::type;
callback(any_cast<I_d>(info));
};
return connectSignal(name, nullptr, callback, emitter,
typeid(I).hash_code());
}

template<typename I>
Connection Object::connectSignal(const char* name, Object* obj,
const std::function<void(I)>& callback)
{
emitter_t emitter = [callback](const any& info) {
assert(info.has_value());
using I_d = typename std::decay<I>::type;
callback(any_cast<I_d>(info));
};
assert(obj);
return connectSignal(name, obj, &callback, emitter,
typeid(I).hash_code());
}

template<class T>
void Object::disconnectSignal(const char* name, T* obj,
void (T::*callback)())
Expand Down
69 changes: 66 additions & 3 deletions tests/unit/signals.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -346,6 +346,34 @@ static void testConnectLambda()
printf("OK\n");
}

static void testConnectLambdaArgs()
{
Sender s;
Receiver r;

printf("%s: ", __func__);

/* Simple lambda */
count = 0;
s.registerSignal<const char*>("signal");
s.connectSignal<const char*>("signal", [](const char*) { count++; });
s.emitSignal("signal", "data");
ASSERT_EQ(count, 1);

/* Lambda with captures */
count = 0;
s.registerSignal<const char*>("csignal");
s.connectSignal<const char*>("csignal", &r, [&s, &r](const char*) {
(void)s;
(void)r;
count++;
});
s.emitSignal("csignal", "data");
ASSERT_EQ(count, 1);

printf("OK\n");
}

static void testDisconnect()
{
Sender s;
Expand Down Expand Up @@ -412,6 +440,15 @@ static void testDisconnect()
s.emitSignal("lsignal");
ASSERT_EQ(count, 0);

/* Simple lambda with args */
count = 0;
s.registerSignal<const char*>("lasignal");
c = s.connectSignal<const char*>("lasignal",
[](const char*) { count++; });
s.disconnectSignal(c);
s.emitSignal("lasignal", "data");
ASSERT_EQ(count, 0);

/* Lambda with captures */
count = 0;
s.registerSignal("lcsignal");
Expand All @@ -421,6 +458,18 @@ static void testDisconnect()
s.emitSignal("lcsignal");
ASSERT_EQ(count, 0);

/* Lambda with captures and args */
count = 0;
s.registerSignal<const char*>("lcasignal");
c = s.connectSignal<const char*>("lcasignal", &r,
[&s, &r](const char*) {
(void)s; (void)r;
count++;
});
s.disconnectSignal(c);
s.emitSignal("lcasignal", "data");
ASSERT_EQ(count, 0);

/* Double remove */
ok = true;
s.registerSignal("dblsignal");
Expand Down Expand Up @@ -584,6 +633,8 @@ static void testDisconnectAll()
s.connectSignal("signal2", &r, &Receiver::genericHandler);
s.connectSignal("signal3", &r, &Receiver::simpleStringHandler);
s.connectSignal("signal3", &r, &Receiver::genericStringHandler);
s.connectSignal<const char*>("signal3", &r,
[](const char*) { count++; });
s.connectSignal("signal1", &r2, &Receiver::genericHandler);
s.disconnectSignals(&r);
s.emitSignal("signal1");
Expand Down Expand Up @@ -643,25 +694,36 @@ static void testEmitConversion()
s.registerSignal<int>("refhandler");
s.connectSignal("refhandler", &r, &Receiver::simpleConstRefHandler);
s.connectSignal("refhandler", &r, &Receiver::genericConstRefHandler);
s.connectSignal<const int&>("refhandler",
[](const int&) { count++; });
s.connectSignal<const int&>("refhandler", &r,
[&r](const int&) { (void)r; count++; });
s.emitSignal("refhandler", 123);
ASSERT_EQ(count, 2);
ASSERT_EQ(count, 4);

/* Sender adds reference */
count = 0;
s.registerSignal<const int&>("refemitter");
s.connectSignal("refemitter", &r, &Receiver::simpleConstRefHandler);
s.connectSignal("refemitter", &r, &Receiver::genericConstRefHandler);
s.connectSignal<int>("refemitter", [](int) { count++; });
s.connectSignal<int>("refemitter", &r,
[&r](int) { (void)r; count++; });
s.emitSignal("refemitter", 123);
ASSERT_EQ(count, 2);
ASSERT_EQ(count, 4);

/* Receiver adds pointer const qualifier */
#if 0 /* FIXME: Currently broken*/
count = 0;
s.registerSignal<int*>("constemitter");
s.connectSignal("constemitter", &r, &Receiver::simpleConstPtrHandler);
s.connectSignal("constemitter", &r, &Receiver::genericConstPtrHandler);
s.connectSignal<const int*>("constemitter",
[](const int*) { count++; });
s.connectSignal<const int*>("constemitter", &r,
[&r](const int*) { (void)r; count++; });
s.emitSignal("constemitter", &count);
ASSERT_EQ(count, 2);
ASSERT_EQ(count, 4);
#endif

printf("OK\n");
Expand All @@ -676,6 +738,7 @@ int main(int /*argc*/, char** /*argv*/)
testConnect();
testConnectArg();
testConnectLambda();
testConnectLambdaArgs();
testDisconnect();
testDisconnectHelper();
testDisconnectHelperArg();
Expand Down

0 comments on commit b497ccb

Please sign in to comment.