diff options
author | Kieran Bingham <kieran.bingham@ideasonboard.com> | 2021-06-15 16:15:12 +0100 |
---|---|---|
committer | Kieran Bingham <kieran.bingham@ideasonboard.com> | 2021-06-25 16:11:08 +0100 |
commit | 27aff949fbc1b9aabfc594bbfd6f94be55a086ec (patch) | |
tree | 9ddbc2462a685a6db3ed33f09ed7a493376439d6 /include/libcamera/base/signal.h | |
parent | 6410d1d37c1ea9d1d168840a7ba063facb0bc9d6 (diff) |
libcamera/base: Move extended base functionality
Move the functionality for the following components to the new
base support library:
- BoundMethod
- EventDispatcher
- EventDispatcherPoll
- Log
- Message
- Object
- Signal
- Semaphore
- Thread
- Timer
While it would be preferable to see these split to move one component
per commit, these components are all interdependent upon each other,
which leaves us with one big change performing the move for all of them.
Reviewed-by: Hirokazu Honda <hiroh@chromium.org>
Reviewed-by: Paul Elder <paul.elder@ideasonboard.com>
Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
Diffstat (limited to 'include/libcamera/base/signal.h')
-rw-r--r-- | include/libcamera/base/signal.h | 132 |
1 files changed, 132 insertions, 0 deletions
diff --git a/include/libcamera/base/signal.h b/include/libcamera/base/signal.h new file mode 100644 index 00000000..c2521769 --- /dev/null +++ b/include/libcamera/base/signal.h @@ -0,0 +1,132 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * Copyright (C) 2019, Google Inc. + * + * signal.h - Signal & slot implementation + */ +#ifndef __LIBCAMERA_BASE_SIGNAL_H__ +#define __LIBCAMERA_BASE_SIGNAL_H__ + +#include <functional> +#include <list> +#include <type_traits> +#include <vector> + +#include <libcamera/base/bound_method.h> +#include <libcamera/base/object.h> + +namespace libcamera { + +class SignalBase +{ +public: + void disconnect(Object *object); + +protected: + using SlotList = std::list<BoundMethodBase *>; + + void connect(BoundMethodBase *slot); + void disconnect(std::function<bool(SlotList::iterator &)> match); + + SlotList slots(); + +private: + SlotList slots_; +}; + +template<typename... Args> +class Signal : public SignalBase +{ +public: + ~Signal() + { + disconnect(); + } + +#ifndef __DOXYGEN__ + template<typename T, typename R, typename std::enable_if_t<std::is_base_of<Object, T>::value> * = nullptr> + void connect(T *obj, R (T::*func)(Args...), + ConnectionType type = ConnectionTypeAuto) + { + Object *object = static_cast<Object *>(obj); + SignalBase::connect(new BoundMethodMember<T, R, Args...>(obj, object, func, type)); + } + + template<typename T, typename R, typename std::enable_if_t<!std::is_base_of<Object, T>::value> * = nullptr> +#else + template<typename T, typename R> +#endif + void connect(T *obj, R (T::*func)(Args...)) + { + SignalBase::connect(new BoundMethodMember<T, R, Args...>(obj, nullptr, func)); + } + + template<typename R> + void connect(R (*func)(Args...)) + { + SignalBase::connect(new BoundMethodStatic<R, Args...>(func)); + } + + void disconnect() + { + SignalBase::disconnect([]([[maybe_unused]] SlotList::iterator &iter) { + return true; + }); + } + + template<typename T> + void disconnect(T *obj) + { + SignalBase::disconnect([obj](SlotList::iterator &iter) { + return (*iter)->match(obj); + }); + } + + template<typename T, typename R> + void disconnect(T *obj, R (T::*func)(Args...)) + { + SignalBase::disconnect([obj, func](SlotList::iterator &iter) { + BoundMethodArgs<R, Args...> *slot = + static_cast<BoundMethodArgs<R, Args...> *>(*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<T, Args...> to match + * func. + */ + return static_cast<BoundMethodMember<T, R, Args...> *>(slot)->match(func); + }); + } + + template<typename R> + void disconnect(R (*func)(Args...)) + { + SignalBase::disconnect([func](SlotList::iterator &iter) { + BoundMethodArgs<R, Args...> *slot = + static_cast<BoundMethodArgs<R, Args...> *>(*iter); + + if (!slot->match(nullptr)) + return false; + + return static_cast<BoundMethodStatic<R, Args...> *>(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<BoundMethodArgs<void, Args...> *>(slot)->activate(args...); + } +}; + +} /* namespace libcamera */ + +#endif /* __LIBCAMERA_BASE_SIGNAL_H__ */ |