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

libcamera v0.7.1 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{
40public:
41 ~Signal()
42 {
43 disconnect();
44 }
45
46#ifndef __DOXYGEN__
47 template<typename T, typename R, std::enable_if_t<std::is_base_of<Object, T>::value> * = nullptr>
48 void connect(T *obj, R (T::*func)(Args...),
49 ConnectionType type = ConnectionTypeAuto)
50 {
51 Object *object = static_cast<Object *>(obj);
52 SignalBase::connect(new BoundMethodMember<T, R, Args...>(obj, object, func, type));
53 }
54
55 template<typename T, typename R, std::enable_if_t<!std::is_base_of<Object, T>::value> * = nullptr>
56#else
57 template<typename T, typename R>
58#endif
59 void connect(T *obj, R (T::*func)(Args...))
60 {
61 SignalBase::connect(new BoundMethodMember<T, R, Args...>(obj, nullptr, func));
62 }
63
64#ifndef __DOXYGEN__
65 template<typename T, typename Func,
66 std::enable_if_t<std::is_base_of<Object, T>::value &&
67 std::is_invocable_v<Func, Args...>> * = nullptr>
68 void connect(T *obj, Func func, ConnectionType type = ConnectionTypeAuto)
69 {
70 Object *object = static_cast<Object *>(obj);
71 SignalBase::connect(new BoundMethodFunctor<T, void, Func, Args...>(obj, object, func, type));
72 }
73
74 template<typename T, typename Func,
75 std::enable_if_t<!std::is_base_of<Object, T>::value &&
76 std::is_invocable_v<Func, Args...>> * = nullptr>
77#else
78 template<typename T, typename Func>
79#endif
80 void connect(T *obj, Func func)
81 {
82 SignalBase::connect(new BoundMethodFunctor<T, void, Func, Args...>(obj, nullptr, func));
83 }
84
85 template<typename R>
86 void connect(R (*func)(Args...))
87 {
88 SignalBase::connect(new BoundMethodStatic<R, Args...>(func));
89 }
90
91 void disconnect()
92 {
93 SignalBase::disconnect([]([[maybe_unused]] SlotList::iterator &iter) {
94 return true;
95 });
96 }
97
98 template<typename T>
99 void disconnect(T *obj)
100 {
101 SignalBase::disconnect([obj](SlotList::iterator &iter) {
102 return (*iter)->match(obj);
103 });
104 }
105
106 template<typename T, typename R>
107 void disconnect(T *obj, R (T::*func)(Args...))
108 {
109 SignalBase::disconnect([obj, func](SlotList::iterator &iter) {
110 BoundMethodArgs<R, Args...> *slot =
111 static_cast<BoundMethodArgs<R, Args...> *>(*iter);
112
113 if (!slot->match(obj))
114 return false;
115
116 /*
117 * If the object matches the slot, the slot is
118 * guaranteed to be a member slot, so we can safely
119 * cast it to BoundMethodMember<T, Args...> to match
120 * func.
121 */
122 return static_cast<BoundMethodMember<T, R, Args...> *>(slot)->match(func);
123 });
124 }
125
126 template<typename R>
127 void disconnect(R (*func)(Args...))
128 {
129 SignalBase::disconnect([func](SlotList::iterator &iter) {
130 BoundMethodArgs<R, Args...> *slot =
131 static_cast<BoundMethodArgs<R, Args...> *>(*iter);
132
133 if (!slot->match(nullptr))
134 return false;
135
136 return static_cast<BoundMethodStatic<R, Args...> *>(slot)->match(func);
137 });
138 }
139
140 void emit(Args... args)
141 {
142 /*
143 * Make a copy of the slots list as the slot could call the
144 * disconnect operation, invalidating the iterator.
145 */
146 for (BoundMethodBase *slot : slots())
147 static_cast<BoundMethodArgs<void, Args...> *>(slot)->activate(args...);
148 }
149};
150
151} /* 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:91
libcamera::Signal::emit
void emit(Args... args)
Emit the signal and call all connected slots.
Definition signal.h:140
libcamera::Signal::connect
void connect(T *obj, R(T::*func)(Args...))
Connect the signal to a member function slot.
Definition signal.h:59
libcamera::Signal::connect
void connect(R(*func)(Args...))
Connect the signal to a static function slot.
Definition signal.h:86
libcamera::Signal::connect
void connect(T *obj, Func func)
Connect the signal to a function object slot.
Definition signal.h:80
libcamera::Signal::disconnect
void disconnect(T *obj)
Disconnect the signal from all slots of the object.
Definition signal.h:99
libcamera::Signal::disconnect
void disconnect(R(*func)(Args...))
Disconnect the signal from the slot static function func.
Definition signal.h:127
libcamera::Signal::disconnect
void disconnect(T *obj, R(T::*func)(Args...))
Disconnect the signal from the object slot member function func.
Definition signal.h:107
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