libcamera  v0.0.0
Supporting cameras in Linux since 2019
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 #ifndef __LIBCAMERA_SIGNAL_H__
8 #define __LIBCAMERA_SIGNAL_H__
9 
10 #include <functional>
11 #include <list>
12 #include <type_traits>
13 #include <vector>
14 
15 #include <libcamera/bound_method.h>
16 #include <libcamera/object.h>
17 
18 namespace libcamera {
19 
20 class SignalBase
21 {
22 public:
23  void disconnect(Object *object);
24 
25 protected:
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 
33 private:
34  SlotList slots_;
35 };
36 
37 template<typename... Args>
38 class Signal : public SignalBase
39 {
40 public:
41  Signal() {}
42  ~Signal()
43  {
44  disconnect();
45  }
46 
47 #ifndef __DOXYGEN__
48  template<typename T, typename R, typename std::enable_if_t<std::is_base_of<Object, T>::value> * = nullptr>
49  void connect(T *obj, R (T::*func)(Args...),
51  {
52  Object *object = static_cast<Object *>(obj);
53  SignalBase::connect(new BoundMethodMember<T, void, Args...>(obj, object, func, type));
54  }
55 
56  template<typename T, typename R, typename 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  template<typename R>
66  void connect(R (*func)(Args...))
67  {
68  SignalBase::connect(new BoundMethodStatic<R, Args...>(func));
69  }
70 
71  void disconnect()
72  {
73  SignalBase::disconnect([](SlotList::iterator &iter) {
74  return true;
75  });
76  }
77 
78  template<typename T>
79  void disconnect(T *obj)
80  {
81  SignalBase::disconnect([obj](SlotList::iterator &iter) {
82  return (*iter)->match(obj);
83  });
84  }
85 
86  template<typename T, typename R>
87  void disconnect(T *obj, R (T::*func)(Args...))
88  {
89  SignalBase::disconnect([obj, func](SlotList::iterator &iter) {
90  BoundMethodArgs<R, Args...> *slot =
91  static_cast<BoundMethodArgs<R, Args...> *>(*iter);
92 
93  if (!slot->match(obj))
94  return false;
95 
96  /*
97  * If the object matches the slot, the slot is
98  * guaranteed to be a member slot, so we can safely
99  * cast it to BoundMethodMember<T, Args...> to match
100  * func.
101  */
102  return static_cast<BoundMethodMember<T, R, Args...> *>(slot)->match(func);
103  });
104  }
105 
106  template<typename R>
107  void disconnect(R (*func)(Args...))
108  {
109  SignalBase::disconnect([func](SlotList::iterator &iter) {
110  BoundMethodArgs<R, Args...> *slot =
111  static_cast<BoundMethodArgs<R, Args...> *>(*iter);
112 
113  if (!slot->match(nullptr))
114  return false;
115 
116  return static_cast<BoundMethodStatic<R, Args...> *>(slot)->match(func);
117  });
118  }
119 
120  void emit(Args... args)
121  {
122  /*
123  * Make a copy of the slots list as the slot could call the
124  * disconnect operation, invalidating the iterator.
125  */
126  for (BoundMethodBase *slot : slots())
127  static_cast<BoundMethodArgs<void, Args...> *>(slot)->activate(args...);
128  }
129 };
130 
131 } /* namespace libcamera */
132 
133 #endif /* __LIBCAMERA_SIGNAL_H__ */
Method bind and invocation.
ConnectionType
Connection type for asynchronous communication.
Definition: bound_method.h:19
@ ConnectionTypeAuto
If the sender and the receiver live in the same thread, ConnectionTypeDirect is used....
Definition: bound_method.h:20
Base object to support automatic signal disconnection.
Definition: object.h:25
Generic signal and slot communication mechanism.
Definition: signal.h:39
void disconnect(R(*func)(Args...))
Disconnect the signal from the slot static function func.
Definition: signal.h:107
void disconnect(T *obj)
Disconnect the signal from all slots of the object.
Definition: signal.h:79
void disconnect()
Disconnect the signal from all slots.
Definition: signal.h:71
void connect(T *obj, R(T::*func)(Args...))
Connect the signal to a member function slot.
Definition: signal.h:60
void connect(R(*func)(Args...))
Connect the signal to a static function slot.
Definition: signal.h:66
void disconnect(T *obj, R(T::*func)(Args...))
Disconnect the signal from the object slot member function func.
Definition: signal.h:87
void emit(Args... args)
Emit the signal and call all connected slots.
Definition: signal.h:120
Base object to support automatic signal disconnection.