/* SPDX-License-Identifier: LGPL-2.1-or-later */ /* * Copyright (C) 2019, Google Inc. * * signal.h - Signal & slot implementation */ #ifndef __LIBCAMERA_SIGNAL_H__ #define __LIBCAMERA_SIGNAL_H__ #include #include #include #include #include #include namespace libcamera { class SignalBase { public: void disconnect(Object *object); protected: using SlotList = std::list; void connect(BoundMethodBase *slot); void disconnect(std::function match); SlotList slots(); private: SlotList slots_; }; template class Signal : public SignalBase { public: ~Signal() { disconnect(); } #ifndef __DOXYGEN__ template::value> * = nullptr> void connect(T *obj, R (T::*func)(Args...), ConnectionType type = ConnectionTypeAuto) { Object *object = static_cast(obj); SignalBase::connect(new BoundMethodMember(obj, object, func, type)); } template::value> * = nullptr> #else template #endif void connect(T *obj, R (T::*func)(Args...)) { SignalBase::connect(new BoundMethodMember(obj, nullptr, func)); } template void connect(R (*func)(Args...)) { SignalBase::connect(new BoundMethodStatic(func)); } void disconnect() { SignalBase::disconnect([]([[maybe_unused]] SlotList::iterator &iter) { return true; }); } template void disconnect(T *obj) { SignalBase::disconnect([obj](SlotList::iterator &iter) { return (*iter)->match(obj); }); } template void disconnect(T *obj, R (T::*func)(Args...)) { SignalBase::disconnect([obj, func](SlotList::iterator &iter) { BoundMethodArgs *slot = static_cast *>(*iter); if (!slot->match(obj)) return false; /* * If the object matches the slot, the slot is * guaranteed to be a member slot, so we can safely * cast it to BoundMethodMember to match * func. */ return static_cast *>(slot)->match(func); }); } template void disconnect(R (*func)(Args...)) { SignalBase::disconnect([func](SlotList::iterator &iter) { BoundMethodArgs *slot = static_cast *>(*iter); if (!slot->match(nullptr)) return false; return static_cast *>(slot)->match(func); }); } void emit(Args... args) { /* * Make a copy of the slots list as the slot could call the * disconnect operation, invalidating the iterator. */ for (BoundMethodBase *slot : slots()) static_cast *>(slot)->activate(args...); } }; } /* namespace libcamera */ #endif /* __LIBCAMERA_SIGNAL_H__ */