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

libcamera v0.0.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.h - 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#include <libcamera/base/object.h>
17
18namespace libcamera {
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#if __cplusplus >= 201703L
68 && std::is_invocable_v<Func, Args...>
69#endif
70 > * = nullptr>
71 void connect(T *obj, Func func, ConnectionType type = ConnectionTypeAuto)
72 {
73 Object *object = static_cast<Object *>(obj);
74 SignalBase::connect(new BoundMethodFunctor<T, void, Func, Args...>(obj, object, func, type));
75 }
76
77 template<typename T, typename Func,
78 std::enable_if_t<!std::is_base_of<Object, T>::value
79#if __cplusplus >= 201703L
80 && std::is_invocable_v<Func, Args...>
81#endif
82 > * = nullptr>
83#else
84 template<typename T, typename Func>
85#endif
86 void connect(T *obj, Func func)
87 {
88 SignalBase::connect(new BoundMethodFunctor<T, void, Func, Args...>(obj, nullptr, func));
89 }
90
91 template<typename R>
92 void connect(R (*func)(Args...))
93 {
94 SignalBase::connect(new BoundMethodStatic<R, Args...>(func));
95 }
96
97 void disconnect()
98 {
99 SignalBase::disconnect([]([[maybe_unused]] SlotList::iterator &iter) {
100 return true;
101 });
102 }
103
104 template<typename T>
105 void disconnect(T *obj)
106 {
107 SignalBase::disconnect([obj](SlotList::iterator &iter) {
108 return (*iter)->match(obj);
109 });
110 }
111
112 template<typename T, typename R>
113 void disconnect(T *obj, R (T::*func)(Args...))
114 {
115 SignalBase::disconnect([obj, func](SlotList::iterator &iter) {
116 BoundMethodArgs<R, Args...> *slot =
117 static_cast<BoundMethodArgs<R, Args...> *>(*iter);
118
119 if (!slot->match(obj))
120 return false;
121
122 /*
123 * If the object matches the slot, the slot is
124 * guaranteed to be a member slot, so we can safely
125 * cast it to BoundMethodMember<T, Args...> to match
126 * func.
127 */
128 return static_cast<BoundMethodMember<T, R, Args...> *>(slot)->match(func);
129 });
130 }
131
132 template<typename R>
133 void disconnect(R (*func)(Args...))
134 {
135 SignalBase::disconnect([func](SlotList::iterator &iter) {
136 BoundMethodArgs<R, Args...> *slot =
137 static_cast<BoundMethodArgs<R, Args...> *>(*iter);
138
139 if (!slot->match(nullptr))
140 return false;
141
142 return static_cast<BoundMethodStatic<R, Args...> *>(slot)->match(func);
143 });
144 }
145
146 void emit(Args... args)
147 {
148 /*
149 * Make a copy of the slots list as the slot could call the
150 * disconnect operation, invalidating the iterator.
151 */
152 for (BoundMethodBase *slot : slots())
153 static_cast<BoundMethodArgs<void, Args...> *>(slot)->activate(args...);
154 }
155};
156
157} /* 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:39
libcamera::Signal::disconnect
void disconnect(R(*func)(Args...))
Disconnect the signal from the slot static function func.
Definition: signal.h:133
libcamera::Signal::connect
void connect(T *obj, Func func)
Connect the signal to a function object slot.
Definition: signal.h:86
libcamera::Signal::disconnect
void disconnect(T *obj)
Disconnect the signal from all slots of the object.
Definition: signal.h:105
libcamera::Signal::disconnect
void disconnect()
Disconnect the signal from all slots.
Definition: signal.h:97
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:92
libcamera::Signal::disconnect
void disconnect(T *obj, R(T::*func)(Args...))
Disconnect the signal from the object slot member function func.
Definition: signal.h:113
libcamera::Signal::emit
void emit(Args... args)
Emit the signal and call all connected slots.
Definition: signal.h:146
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
object.h
Base object to support automatic signal disconnection.