diff --git a/include/libcamera/object.h b/include/libcamera/object.h index d61dfb1e..5c251a82 100644 --- a/include/libcamera/object.h +++ b/include/libcamera/object.h @@ -13,9 +13,10 @@ namespace libcamera { class Message; -class SignalBase; template class Signal; +class SignalBase; +class SlotBase; class Thread; class Object @@ -33,6 +34,7 @@ public: private: template friend class Signal; + friend class SlotBase; friend class Thread; void connect(SignalBase *signal); diff --git a/include/libcamera/signal.h b/include/libcamera/signal.h index 11ffb857..d3be3626 100644 --- a/include/libcamera/signal.h +++ b/include/libcamera/signal.h @@ -18,23 +18,28 @@ namespace libcamera { template class Signal; +class SignalBase; class SlotBase { public: - SlotBase(void *obj, bool isObject) - : obj_(obj), isObject_(isObject) {} + SlotBase(void *obj, Object *object) + : obj_(obj), object_(object) {} virtual ~SlotBase() {} - void *obj() { return obj_; } - bool isObject() const { return isObject_; } + template + bool match(T *obj) { return obj == obj_; } + template<> + bool match(Object *object) { return object == object_; } + + void disconnect(SignalBase *signal); void activatePack(void *pack); virtual void invokePack(void *pack) = 0; protected: void *obj_; - bool isObject_; + Object *object_; }; template @@ -71,8 +76,8 @@ private: } public: - SlotArgs(void *obj, bool isObject) - : SlotBase(obj, isObject) {} + SlotArgs(void *obj, Object *object) + : SlotBase(obj, object) {} void invokePack(void *pack) override { @@ -89,12 +94,12 @@ class SlotMember : public SlotArgs public: using PackType = std::tuple::type...>; - SlotMember(T *obj, bool isObject, void (T::*func)(Args...)) - : SlotArgs(obj, isObject), func_(func) {} + SlotMember(T *obj, Object *object, void (T::*func)(Args...)) + : SlotArgs(obj, object), func_(func) {} void activate(Args... args) { - if (this->isObject_) + if (this->object_) SlotBase::activatePack(new PackType{ args... }); else (static_cast(this->obj_)->*func_)(args...); @@ -115,7 +120,7 @@ class SlotStatic : public SlotArgs { public: SlotStatic(void (*func)(Args...)) - : SlotArgs(nullptr, false), func_(func) {} + : SlotArgs(nullptr, nullptr), func_(func) {} void activate(Args... args) { (*func_)(args...); } void invoke(Args... args) {} @@ -129,11 +134,11 @@ class SignalBase { public: template - void disconnect(T *object) + void disconnect(T *obj) { for (auto iter = slots_.begin(); iter != slots_.end(); ) { SlotBase *slot = *iter; - if (slot->obj() == object) { + if (slot->match(obj)) { iter = slots_.erase(iter); delete slot; } else { @@ -155,27 +160,27 @@ public: ~Signal() { for (SlotBase *slot : slots_) { - if (slot->isObject()) - static_cast(slot->obj())->disconnect(this); + slot->disconnect(this); delete slot; } } #ifndef __DOXYGEN__ template::value>::type * = nullptr> - void connect(T *object, void (T::*func)(Args...)) + void connect(T *obj, void (T::*func)(Args...)) { + Object *object = static_cast(obj); object->connect(this); - slots_.push_back(new SlotMember(object, true, func)); + slots_.push_back(new SlotMember(obj, object, func)); } template::value>::type * = nullptr> #else template #endif - void connect(T *object, void (T::*func)(Args...)) + void connect(T *obj, void (T::*func)(Args...)) { - slots_.push_back(new SlotMember(object, false, func)); + slots_.push_back(new SlotMember(obj, nullptr, func)); } void connect(void (*func)(Args...)) @@ -191,23 +196,23 @@ public: } template - void disconnect(T *object) + void disconnect(T *obj) { - SignalBase::disconnect(object); + SignalBase::disconnect(obj); } template - void disconnect(T *object, void (T::*func)(Args...)) + void disconnect(T *obj, void (T::*func)(Args...)) { for (auto iter = slots_.begin(); iter != slots_.end(); ) { SlotArgs *slot = static_cast *>(*iter); /* - * If the obj() pointer matches the object, the slot is + * If the object matches the slot, the slot is * guaranteed to be a member slot, so we can safely * cast it to SlotMember and access its * func_ member. */ - if (slot->obj() == object && + if (slot->match(obj) && static_cast *>(slot)->func_ == func) { iter = slots_.erase(iter); delete slot; @@ -221,7 +226,7 @@ public: { for (auto iter = slots_.begin(); iter != slots_.end(); ) { SlotArgs *slot = *iter; - if (slot->obj() == nullptr && + if (slot->match(nullptr) && static_cast *>(slot)->func_ == func) { iter = slots_.erase(iter); delete slot; diff --git a/src/libcamera/signal.cpp b/src/libcamera/signal.cpp index 53c18535..ab7dba50 100644 --- a/src/libcamera/signal.cpp +++ b/src/libcamera/signal.cpp @@ -57,9 +57,15 @@ namespace libcamera { * passed through the signal will remain valid after the signal is emitted. */ +void SlotBase::disconnect(SignalBase *signal) +{ + if (object_) + object_->disconnect(signal); +} + void SlotBase::activatePack(void *pack) { - Object *obj = static_cast(obj_); + Object *obj = static_cast(object_); if (Thread::current() == obj->thread()) { invokePack(pack);