diff options
Diffstat (limited to 'include/libcamera/signal.h')
-rw-r--r-- | include/libcamera/signal.h | 145 |
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...); } }; |