libcamera: include/libcamera/base/signal.h Source File

libcamera v0.7.2 Supporting cameras in Linux since 2019

Loading...
Searching...
No Matches
signal.h
Go to the documentation of this file.
1/* SPDX-License-Identifier: LGPL-2.1-or-later */
2/*
3 * Copyright (C) 2019, Google Inc.
4 *
5 * Signal & slot implementation
6 */
7
8#pragma once
9
10#include <functional>
11#include <list>
12#include <type_traits>
13
14#include <libcamera/base/bound_method.h>
15
16namespace libcamera {
17
18class Object;
19
20class SignalBase
21{
22public:
23 void disconnect(Object *object);
24
25protected:
26 using SlotList = std::list<BoundMethodBase *>;
27
28 void connect(BoundMethodBase *slot);
29 void disconnect(std::function<bool(SlotList::iterator &)> match);
30
31 SlotList slots();
32
33private:
34 SlotList slots_;
35};
36
37template<typename... Args>
38 class Signal : public SignalBase
39{
40 static_assert((!std::is_rvalue_reference_v<Args> && ...));
41
42public:
43 ~Signal()
44 {
45 disconnect();
46 }
47
48#ifndef __DOXYGEN__
49 template<typename T, typename R, std::enable_if_t<std::is_base_of<Object, T>::value> * = nullptr>
50 void connect(T *obj, R (T::*func)(Args...),
51 ConnectionType type = ConnectionTypeAuto)
52 {
53 Object *object = static_cast<Object *>(obj);
54 SignalBase::connect(new BoundMethodMember<T, R, Args...>(obj, object, func, type));
55 }
56
57 template<typename T, typename R, std::enable_if_t<!std::is_base_of<Object, T>::value> * = nullptr>
58#else
59 template<typename T, typename R>
60#endif
61 void connect(T *obj, R (T::*func)(Args...))
62 {
63 SignalBase::connect(new BoundMethodMember<T, R, Args...>(obj, nullptr, func));
64 }
65
66#ifndef __DOXYGEN__
67 template<typename T, typename Func,
68 std::enable_if_t<std::is_base_of<Object, T>::value &&
69 std::is_invocable_v<Func, Args...>> * = nullptr>
70 void connect(T *obj, Func func, ConnectionType type = ConnectionTypeAuto)
71 {
72 Object *object = static_cast<Object *>(obj);
73 SignalBase::connect(new BoundMethodFunctor<T, void, Func, Args...>(obj, object, func, type));
74 }
75
76 template<typename T, typename Func,
77 std::enable_if_t<!std::is_base_of<Object, T>::value &&
78 std::is_invocable_v<Func, Args...>> * = nullptr>
79#else
80 template<typename T, typename Func>
81#endif
82 void connect(T *obj, Func func)
83 {
84 SignalBase::connect(new BoundMethodFunctor<T, void, Func, Args...>(obj, nullptr, func));
85 }
86
87 template<typename R>
88 void connect(R (*func)(Args...))
89 {
90 SignalBase::connect(new BoundMethodStatic<R, Args...>(func));
91 }
92
93 void disconnect()
94 {
95 SignalBase::disconnect([]([[maybe_unused]] SlotList::iterator &iter) {
96 return true;
97 });
98 }
99
100 template<typename T>
101 void disconnect(T *obj)
102 {
103 SignalBase::disconnect([obj](SlotList::iterator &iter) {
104 return (*iter)->match(obj);
105 });
106 }
107
108 template<typename T, typename R>
109 void disconnect(T *obj, R (T::*func)(Args...))
110 {
111 SignalBase::disconnect([obj, func](SlotList::iterator &iter) {
112 BoundMethodArgs<R, Args...> *slot =
113 static_cast<BoundMethodArgs<R, Args...> *>(*iter);
114
115 if (!slot->match(obj))
116 return false;
117
118 /*
119 * If the object matches the slot, the slot is
120 * guaranteed to be a member slot, so we can safely
121 * cast it to BoundMethodMember<T, Args...> to match
122 * func.
123 */
124 return static_cast<BoundMethodMember<T, R, Args...> *>(slot)->match(func);
125 });
126 }
127
128 template<typename R>
129 void disconnect(R (*func)(Args...))
130 {
131 SignalBase::disconnect([func](SlotList::iterator &iter) {
132 BoundMethodArgs<R, Args...> *slot =
133 static_cast<BoundMethodArgs<R, Args...> *>(*iter);
134
135 if (!slot->match(nullptr))
136 return false;
137
138 return static_cast<BoundMethodStatic<R, Args...> *>(slot)->match(func);
139 });
140 }
141
142 void emit(Args... args)
143 {
144 /*
145 * Make a copy of the slots list as the slot could call the
146 * disconnect operation, invalidating the iterator.
147 */
148 for (BoundMethodBase *slot : slots())
149 static_cast<BoundMethodArgs<void, Args...> *>(slot)->activate(args...);
150 }
151};
152
153} /* namespace libcamera */
bound_method.h
Method bind and invocation.
libcamera::Object
Base object to support automatic signal disconnection.
Definition object.h:27
libcamera::Signal
Generic signal and slot communication mechanism.
Definition signal.h:39
libcamera::Signal::disconnect
void disconnect()
Disconnect the signal from all slots.
Definition signal.h:93
libcamera::Signal::emit
void emit(Args... args)
Emit the signal and call all connected slots.
Definition signal.h:142
libcamera::Signal::connect
void connect(T *obj, R(T::*func)(Args...))
Connect the signal to a member function slot.
Definition signal.h:61
libcamera::Signal::connect
void connect(R(*func)(Args...))
Connect the signal to a static function slot.
Definition signal.h:88
libcamera::Signal::connect
void connect(T *obj, Func func)
Connect the signal to a function object slot.
Definition signal.h:82
libcamera::Signal::disconnect
void disconnect(T *obj)
Disconnect the signal from all slots of the object.
Definition signal.h:101
libcamera::Signal::disconnect
void disconnect(R(*func)(Args...))
Disconnect the signal from the slot static function func.
Definition signal.h:129
libcamera::Signal::disconnect
void disconnect(T *obj, R(T::*func)(Args...))
Disconnect the signal from the object slot member function func.
Definition signal.h:109
libcamera
Top-level libcamera namespace.
Definition backtrace.h:17
libcamera::ConnectionType
ConnectionType
Connection type for asynchronous communication.
Definition bound_method.h:19
libcamera::ConnectionTypeAuto
@ ConnectionTypeAuto
If the sender and the receiver live in the same thread, ConnectionTypeDirect is used....
Definition bound_method.h:20