Skip to content

Instantly share code, notes, and snippets.

@cjxgm
Last active August 29, 2015 14:03
Show Gist options
  • Save cjxgm/2bca34030ea9ecdd1054 to your computer and use it in GitHub Desktop.
Save cjxgm/2bca34030ea9ecdd1054 to your computer and use it in GitHub Desktop.
a simple and clean implementation of a signal system in C++11
#pragma once
#include <functional>
#include <list>
// tue == std + 1
namespace tue
{
template <class ...Args>
struct Signal
{
using Result = bool;
using Signature = Result(Args...);
using Callback = std::function<Signature>;
using Unlisten = std::function<void()>;
using List = std::list<Callback>;
Unlisten listen(Callback&& cb)
{
auto it = callbacks.insert(callbacks.end(), std::move(cb));
return [this, it]() { callbacks.erase(it); };
}
void emit(Args ...args)
{
for (auto& cb: callbacks)
if (cb(args...))
break;
}
void operator()(Args ...args) { emit(args...); }
private:
List callbacks;
};
};
#include "signal.hh"
#include <iostream>
using namespace std;
tue::Signal<int> hello; // the callback/listener takes 1 int as argument and returns bool.
bool d_cb(int x)
{
cerr << "called D " << x << endl;
return false;
}
struct E
{
E(int id) : id{id} { cerr << "E{" << id << "}@" << this << "::(ctor)" << endl; }
~E() { cerr << "E{" << id << "}@" << this << "::(dtor)" << endl; }
E(const E& e) { id = e.id; cerr << "E{" << id << "}@" << this << "::(copy)" << endl; }
E( E&& e) { id = e.id; e.id = 0; cerr << "E{" << id << "}@" << this << "::(move)" << endl; }
bool operator()(int x)
{
cerr << "called E " << x << endl;
return false;
}
private:
int id;
};
int main()
{
hello.listen([](int x) {
cerr << "called A " << x << endl;
return false;
});
auto unlisten_b = hello.listen([](int x) {
cerr << "called B " << x << endl;
return true;
});
hello.listen([](int x) {
cerr << "called C " << x << endl;
return false;
});
hello(1);
cerr << endl;
unlisten_b();
hello(2);
cerr << endl;
hello.listen(d_cb);
hello(3);
cerr << endl;
{
E e_cb{1};
hello.listen(std::move(e_cb));
}
hello(4);
cerr << endl;
hello = decltype(hello){}; // reset the signal
hello(5);
cerr << endl;
hello.listen(d_cb);
hello(6);
cerr << endl;
hello.listen(E{2});
hello(7);
cerr << endl;
}
called A 1
called B 1
called A 2
called C 2
called A 3
called C 3
called D 3
E{1}@0x7fff3a1f0218::(ctor)
E{1}@0x7fff3a1f01e8::(move)
E{1}@0x1105070::(move)
E{0}@0x7fff3a1f01e8::(dtor)
E{0}@0x7fff3a1f0218::(dtor)
called A 4
called C 4
called D 4
called E 4
E{1}@0x1105070::(dtor)
called D 6
E{2}@0x7fff3a1f0188::(ctor)
E{2}@0x1105070::(move)
E{0}@0x7fff3a1f0188::(dtor)
called D 7
called E 7
E{2}@0x1105070::(dtor)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment