summaryrefslogtreecommitdiff
path: root/include/libcamera/base/signal.h
diff options
context:
space:
mode:
authorKieran Bingham <kieran.bingham@ideasonboard.com>2021-06-15 16:15:12 +0100
committerKieran Bingham <kieran.bingham@ideasonboard.com>2021-06-25 16:11:08 +0100
commit27aff949fbc1b9aabfc594bbfd6f94be55a086ec (patch)
tree9ddbc2462a685a6db3ed33f09ed7a493376439d6 /include/libcamera/base/signal.h
parent6410d1d37c1ea9d1d168840a7ba063facb0bc9d6 (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.h132
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__ */