55 lines
1.3 KiB
C++
55 lines
1.3 KiB
C++
#ifndef CANVAS_SIGNAL_HPP
|
|
#define CANVAS_SIGNAL_HPP
|
|
|
|
#include "callable.hpp"
|
|
#include <cstdio>
|
|
#include <vector>
|
|
|
|
namespace ce {
|
|
/*! Observer-listener implementation
|
|
*/
|
|
template <class... Args>
|
|
class Signal {
|
|
std::vector<Callable<void, Args...>> listeners{};
|
|
public:
|
|
void connect(Callable<void, Args...> callable);
|
|
void disconnect(Callable<void, Args...> callable);
|
|
void invoke(Args...);
|
|
};
|
|
|
|
template <class... Args> void Signal<Args...>::connect(Callable<void, Args...> callable) {
|
|
this->listeners.push_back(callable);
|
|
}
|
|
|
|
template <class... Args> void Signal<Args...>::disconnect(Callable<void, Args...> callable) {
|
|
std::erase_if(this->listeners,
|
|
[&callable](Callable<void, Args...> &listener) -> bool {
|
|
return listener == callable;
|
|
});
|
|
}
|
|
|
|
template <class... Args> void Signal<Args...>::invoke(Args... args) {
|
|
for(Callable<void, Args...> &listener : this->listeners) {
|
|
listener.call(args...);
|
|
}
|
|
}
|
|
|
|
#if DEBUG
|
|
static inline
|
|
void TEST_signals() {
|
|
struct A {inline void f(int val) {
|
|
std::printf("%d\n", val);
|
|
}};
|
|
Signal<int> signal;
|
|
A object;
|
|
Callable<void, int> callable{Callable<void, int>::make(&object, &A::f)};
|
|
signal.connect(callable);
|
|
signal.invoke(5);
|
|
signal.disconnect(callable);
|
|
signal.invoke(10);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
#endif // !CANVAS_SIGNAL_HPP
|