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