LibrePCB Developers Documentation
signalslot.h
Go to the documentation of this file.
1 /*
2  * LibrePCB - Professional EDA for everyone!
3  * Copyright (C) 2013 LibrePCB Developers, see AUTHORS.md for contributors.
4  * https://librepcb.org/
5  *
6  * This program is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program. If not, see <http://www.gnu.org/licenses/>.
18  */
19 
20 #ifndef LIBREPCB_CORE_SIGNALSLOT_H
21 #define LIBREPCB_CORE_SIGNALSLOT_H
22 
23 /*******************************************************************************
24  * Includes
25  ******************************************************************************/
26 #include <QtCore>
27 
28 #include <functional>
29 
30 /*******************************************************************************
31  * Namespace / Forward Declarations
32  ******************************************************************************/
33 namespace librepcb {
34 
35 template <typename Tsender, typename... Args>
36 class Slot;
37 
38 /*******************************************************************************
39  * Class Signal
40  ******************************************************************************/
41 
64 template <typename Tsender, typename... Args>
65 class Signal {
66  friend class Slot<Tsender, Args...>;
67 
68 public:
69  // Constructors / Destructor
70  Signal() = delete;
71  Signal(const Signal& other) = delete;
72 
78  explicit Signal(const Tsender& sender) noexcept : mSender(sender) {}
79 
85  ~Signal() noexcept {
86  for (auto slot : mSlots) {
87  slot->mSignals.remove(this);
88  }
89  }
90 
96  int getSlotCount() const noexcept { return mSlots.count(); }
97 
103  void attach(Slot<Tsender, Args...>& slot) const noexcept {
104  slot.mSignals.insert(this);
105  mSlots.insert(&slot);
106  }
107 
113  void detach(Slot<Tsender, Args...>& slot) const noexcept {
114  slot.mSignals.remove(this);
115  mSlots.remove(&slot);
116  }
117 
123  void notify(Args... args) noexcept {
124  // Note: A "foreach" loop with a Qt container first creates an implicitly
125  // shared copy of the container (see
126  // https://doc.qt.io/qt-5/containers.html#foreach). This is very important
127  // since the callback might modify the container while iterating over it!
128  // With std containers this would be much more complicated (or less
129  // efficient).
130  foreach (const auto& slot, mSlots) {
131  // Check existence of the slot again because we must not call it if it
132  // was detached (i.e. removed from the container) in the meantime.
133  if (mSlots.contains(slot)) {
134  slot->mCallback(mSender, args...);
135  }
136  }
137  }
138 
139  // Operator Overloadings
140  Signal& operator=(Signal const& other) = delete;
141 
142 private:
143  const Tsender& mSender;
144  mutable QSet<Slot<Tsender, Args...>*> mSlots;
145 };
146 
147 /*******************************************************************************
148  * Class Slot
149  ******************************************************************************/
150 
169 template <typename Tsender, typename... Args>
170 class Slot {
171  friend class Signal<Tsender, Args...>;
172 
173 public:
174  // Constructors / Destructor
175  Slot() = delete;
176  Slot(const Slot& other) = delete;
177 
185  explicit Slot(
186  const std::function<void(const Tsender&, Args...)>& callback) noexcept
187  : mCallback(callback) {}
188 
197  template <typename T>
198  explicit Slot(T& obj, void (T::*func)(const Tsender&, Args...)) noexcept
199  : mCallback([=, &obj](const Tsender& s, Args... args) {
200  (obj.*func)(s, args...);
201  }) {}
202 
208  ~Slot() noexcept { detachAll(); }
209 
215  int getSignalCount() const noexcept { return mSignals.count(); }
216 
220  void detachAll() noexcept {
221  for (auto signal : mSignals) {
222  signal->mSlots.remove(this);
223  }
224  mSignals.clear();
225  }
226 
227  // Operator Overloadings
228  Slot& operator=(Slot const& other) = delete;
229 
230 private:
232  QSet<const Signal<Tsender, Args...>*> mSignals;
233 
235  std::function<void(const Tsender&, Args...)> mCallback;
236 };
237 
238 /*******************************************************************************
239  * End of File
240  ******************************************************************************/
241 
242 } // namespace librepcb
243 
244 #endif
Slot(const std::function< void(const Tsender &, Args...)> &callback) noexcept
Constructor.
Definition: signalslot.h:185
std::function< void(const Tsender &, Args...)> mCallback
The registered callback function.
Definition: signalslot.h:235
~Signal() noexcept
Destructor.
Definition: signalslot.h:85
int getSlotCount() const noexcept
Get the count of registered slots.
Definition: signalslot.h:96
Slot(T &obj, void(T::*func)(const Tsender &, Args...)) noexcept
Constructor.
Definition: signalslot.h:198
Definition: occmodel.cpp:77
void detachAll() noexcept
Detach from all signals.
Definition: signalslot.h:220
void detach(Slot< Tsender, Args... > &slot) const noexcept
Detach a slot.
Definition: signalslot.h:113
QSet< const Signal< Tsender, Args... > * > mSignals
All signals this slot is attached to.
Definition: signalslot.h:232
void attach(Slot< Tsender, Args... > &slot) const noexcept
Attach a slot.
Definition: signalslot.h:103
QSet< Slot< Tsender, Args... > * > mSlots
All attached slots.
Definition: signalslot.h:144
void notify(Args... args) noexcept
Notify all attached slots.
Definition: signalslot.h:123
Signal & operator=(Signal const &other)=delete
~Slot() noexcept
Destructor.
Definition: signalslot.h:208
The Signal class is used to emit signals on non-QObject derived classes.
Definition: signalslot.h:65
int getSignalCount() const noexcept
Get the count of registered signals.
Definition: signalslot.h:215
const Tsender & mSender
Reference to the sender object.
Definition: signalslot.h:143
The Slot class is used to receive signals from non-QObject derived classes.
Definition: signalslot.h:36
Signal(const Tsender &sender) noexcept
Constructor.
Definition: signalslot.h:78