summaryrefslogtreecommitdiff
path: root/include/libcamera/signal.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/libcamera/signal.h')
-rw-r--r--include/libcamera/signal.h145
1 files changed, 16 insertions, 129 deletions
diff --git a/include/libcamera/signal.h b/include/libcamera/signal.h
index 8f6db700..3b6de30f 100644
--- a/include/libcamera/signal.h
+++ b/include/libcamera/signal.h
@@ -8,127 +8,14 @@
#define __LIBCAMERA_SIGNAL_H__
#include <list>
-#include <tuple>
#include <type_traits>
#include <vector>
+#include <libcamera/bound_method.h>
#include <libcamera/object.h>
namespace libcamera {
-template<typename... Args>
-class Signal;
-class SignalBase;
-
-class SlotBase
-{
-public:
- SlotBase(void *obj, Object *object)
- : obj_(obj), object_(object) {}
- virtual ~SlotBase() {}
-
- template<typename T, typename std::enable_if<!std::is_same<Object, T>::value>::type * = nullptr>
- bool match(T *obj) { return obj == obj_; }
- bool match(Object *object) { return object == object_; }
-
- void disconnect(SignalBase *signal);
-
- void activatePack(void *pack);
- virtual void invokePack(void *pack) = 0;
-
-protected:
- void *obj_;
- Object *object_;
-};
-
-template<typename... Args>
-class SlotArgs : public SlotBase
-{
-private:
-#ifndef __DOXYGEN__
- /*
- * This is a cheap partial implementation of std::integer_sequence<>
- * from C++14.
- */
- template<int...>
- struct sequence {
- };
-
- template<int N, int... S>
- struct generator : generator<N-1, N-1, S...> {
- };
-
- template<int... S>
- struct generator<0, S...> {
- typedef sequence<S...> type;
- };
-#endif
-
- using PackType = std::tuple<typename std::remove_reference<Args>::type...>;
-
- template<int... S>
- void invokePack(void *pack, sequence<S...>)
- {
- PackType *args = static_cast<PackType *>(pack);
- invoke(std::get<S>(*args)...);
- delete args;
- }
-
-public:
- SlotArgs(void *obj, Object *object)
- : SlotBase(obj, object) {}
-
- void invokePack(void *pack) override
- {
- invokePack(pack, typename generator<sizeof...(Args)>::type());
- }
-
- virtual void activate(Args... args) = 0;
- virtual void invoke(Args... args) = 0;
-};
-
-template<typename T, typename... Args>
-class SlotMember : public SlotArgs<Args...>
-{
-public:
- using PackType = std::tuple<typename std::remove_reference<Args>::type...>;
-
- SlotMember(T *obj, Object *object, void (T::*func)(Args...))
- : SlotArgs<Args...>(obj, object), func_(func) {}
-
- void activate(Args... args)
- {
- if (this->object_)
- SlotBase::activatePack(new PackType{ args... });
- else
- (static_cast<T *>(this->obj_)->*func_)(args...);
- }
-
- void invoke(Args... args)
- {
- (static_cast<T *>(this->obj_)->*func_)(args...);
- }
-
-private:
- friend class Signal<Args...>;
- void (T::*func_)(Args...);
-};
-
-template<typename... Args>
-class SlotStatic : public SlotArgs<Args...>
-{
-public:
- SlotStatic(void (*func)(Args...))
- : SlotArgs<Args...>(nullptr, nullptr), func_(func) {}
-
- void activate(Args... args) { (*func_)(args...); }
- void invoke(Args... args) {}
-
-private:
- friend class Signal<Args...>;
- void (*func_)(Args...);
-};
-
class SignalBase
{
public:
@@ -136,7 +23,7 @@ public:
void disconnect(T *obj)
{
for (auto iter = slots_.begin(); iter != slots_.end(); ) {
- SlotBase *slot = *iter;
+ BoundMethodBase *slot = *iter;
if (slot->match(obj)) {
iter = slots_.erase(iter);
delete slot;
@@ -148,7 +35,7 @@ public:
protected:
friend class Object;
- std::list<SlotBase *> slots_;
+ std::list<BoundMethodBase *> slots_;
};
template<typename... Args>
@@ -158,7 +45,7 @@ public:
Signal() {}
~Signal()
{
- for (SlotBase *slot : slots_) {
+ for (BoundMethodBase *slot : slots_) {
slot->disconnect(this);
delete slot;
}
@@ -170,7 +57,7 @@ public:
{
Object *object = static_cast<Object *>(obj);
object->connect(this);
- slots_.push_back(new SlotMember<T, Args...>(obj, object, func));
+ slots_.push_back(new BoundMemberMethod<T, Args...>(obj, object, func));
}
template<typename T, typename std::enable_if<!std::is_base_of<Object, T>::value>::type * = nullptr>
@@ -179,17 +66,17 @@ public:
#endif
void connect(T *obj, void (T::*func)(Args...))
{
- slots_.push_back(new SlotMember<T, Args...>(obj, nullptr, func));
+ slots_.push_back(new BoundMemberMethod<T, Args...>(obj, nullptr, func));
}
void connect(void (*func)(Args...))
{
- slots_.push_back(new SlotStatic<Args...>(func));
+ slots_.push_back(new BoundStaticMethod<Args...>(func));
}
void disconnect()
{
- for (SlotBase *slot : slots_)
+ for (BoundMethodBase *slot : slots_)
delete slot;
slots_.clear();
}
@@ -204,15 +91,15 @@ public:
void disconnect(T *obj, void (T::*func)(Args...))
{
for (auto iter = slots_.begin(); iter != slots_.end(); ) {
- SlotArgs<Args...> *slot = static_cast<SlotArgs<Args...> *>(*iter);
+ BoundMethodArgs<Args...> *slot = static_cast<BoundMethodArgs<Args...> *>(*iter);
/*
* If the object matches the slot, the slot is
* guaranteed to be a member slot, so we can safely
- * cast it to SlotMember<T, Args...> and access its
+ * cast it to BoundMemberMethod<T, Args...> and access its
* func_ member.
*/
if (slot->match(obj) &&
- static_cast<SlotMember<T, Args...> *>(slot)->func_ == func) {
+ static_cast<BoundMemberMethod<T, Args...> *>(slot)->func_ == func) {
iter = slots_.erase(iter);
delete slot;
} else {
@@ -224,9 +111,9 @@ public:
void disconnect(void (*func)(Args...))
{
for (auto iter = slots_.begin(); iter != slots_.end(); ) {
- SlotArgs<Args...> *slot = *iter;
+ BoundMethodArgs<Args...> *slot = *iter;
if (slot->match(nullptr) &&
- static_cast<SlotStatic<Args...> *>(slot)->func_ == func) {
+ static_cast<BoundStaticMethod<Args...> *>(slot)->func_ == func) {
iter = slots_.erase(iter);
delete slot;
} else {
@@ -241,9 +128,9 @@ public:
* Make a copy of the slots list as the slot could call the
* disconnect operation, invalidating the iterator.
*/
- std::vector<SlotBase *> slots{ slots_.begin(), slots_.end() };
- for (SlotBase *slot : slots)
- static_cast<SlotArgs<Args...> *>(slot)->activate(args...);
+ std::vector<BoundMethodBase *> slots{ slots_.begin(), slots_.end() };
+ for (BoundMethodBase *slot : slots)
+ static_cast<BoundMethodArgs<Args...> *>(slot)->activate(args...);
}
};