Embedded Template Library 1.0
Loading...
Searching...
No Matches
signal.h
Go to the documentation of this file.
1
2
3/******************************************************************************
4The MIT License(MIT)
5
6Embedded Template Library.
7https://github.com/ETLCPP/etl
8https://www.etlcpp.com
9
10Copyright(c) 2025 John Wellbelove, Mark Kitson
11
12Permission is hereby granted, free of charge, to any person obtaining a copy
13of this software and associated documentation files(the "Software"), to deal
14in the Software without restriction, including without limitation the rights
15to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
16copies of the Software, and to permit persons to whom the Software is
17furnished to do so, subject to the following conditions :
18
19The above copyright notice and this permission notice shall be included in all
20copies or substantial portions of the Software.
21
22THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
25AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
28SOFTWARE.
29******************************************************************************/
30
31#ifndef ETL_SIGNAL_INCLUDED
32#define ETL_SIGNAL_INCLUDED
33
34#include <cstddef>
35
36#include "platform.h"
37
38#if ETL_USING_CPP11
39
40 #include "algorithm.h"
41 #include "delegate.h"
42 #include "error_handler.h"
43 #include "exception.h"
44 #include "file_error_numbers.h"
45 #include "initializer_list.h"
46 #include "iterator.h"
47 #include "span.h"
48 #include "type_traits.h"
49
50//*****************************************************************************
54//*****************************************************************************
55
56namespace etl
57{
58 //***************************************************************************
61 //***************************************************************************
62 class signal_exception : public exception
63 {
64 public:
65
66 signal_exception(string_type reason_, string_type file_name_, numeric_type line_number_)
67 : exception{reason_, file_name_, line_number_}
68 {
69 }
70 };
71
72 //***************************************************************************
75 //***************************************************************************
76 class signal_full : public signal_exception
77 {
78 public:
79
80 signal_full(string_type file_name_, numeric_type line_number_)
81 : signal_exception{ETL_ERROR_TEXT("signal:full", ETL_SIGNAL_FILE_ID"A"), file_name_, line_number_}
82 {
83 }
84 };
85
86 //***************************************************************************
97 //***************************************************************************
98 template <typename TFunction, size_t Size, typename TSlot = etl::delegate<TFunction>>
99 class signal
100 {
101 public:
102
103 using slot_type = TSlot;
104 using size_type = size_t;
105 using span_type = etl::span<const slot_type>;
106
107 //*************************************************************************
111 //*************************************************************************
112 template <typename... TSlots>
113 ETL_CONSTEXPR14 explicit signal(TSlots&&... slots) ETL_NOEXCEPT
114 : slot_list{etl::forward<TSlots>(slots)...}
115 , slot_list_end{slot_list + sizeof...(slots)}
116 {
117 static_assert((etl::are_all_same<slot_type, etl::decay_t<TSlots>...>::value), "All slots must be slot_type");
118 static_assert(sizeof...(slots) <= Size, "Number of slots exceeds capacity");
119 }
120
121 //*************************************************************************
125 //*************************************************************************
126 signal(const signal& other) ETL_NOEXCEPT
127 : slot_list{}
128 , slot_list_end{slot_list + other.size()}
129 {
130 etl::copy(other.begin(), other.end(), slot_list);
131 }
132
133 //*************************************************************************
138 //*************************************************************************
139 signal& operator=(const signal& other) ETL_NOEXCEPT
140 {
141 if (this != &other)
142 {
143 etl::copy(other.begin(), other.end(), slot_list);
144 slot_list_end = slot_list + other.size();
145 }
146 return *this;
147 }
148
149 //*************************************************************************
154 //*************************************************************************
155 signal(signal&& other) ETL_NOEXCEPT
156 : slot_list{}
157 , slot_list_end{slot_list + other.size()}
158 {
159 etl::move(other.begin(), other.end(), slot_list);
160 other.slot_list_end = other.slot_list;
161 }
162
163 //*************************************************************************
169 //*************************************************************************
170 signal& operator=(signal&& other) ETL_NOEXCEPT
171 {
172 if (this != &other)
173 {
174 etl::move(other.begin(), other.end(), slot_list);
175 slot_list_end = slot_list + other.size();
176 other.slot_list_end = other.slot_list;
177 }
178 return *this;
179 }
180
181 //*************************************************************************
187 //*************************************************************************
188 bool connect(const slot_type& slot) ETL_NOEXCEPT_EXPR(ETL_NOT_USING_EXCEPTIONS)
189 {
190 if (!connected(slot))
191 {
192 ETL_ASSERT_OR_RETURN_VALUE(!full(), ETL_ERROR(signal_full), false);
193 append_slot(slot);
194 }
195
196 return true;
197 }
198
199 #if ETL_HAS_INITIALIZER_LIST && ETL_USING_CPP17
200 //*************************************************************************
206 //*************************************************************************
207 bool connect(std::initializer_list<const slot_type> slots) ETL_NOEXCEPT_EXPR(ETL_NOT_USING_EXCEPTIONS)
208 {
209 for (const slot_type& slot : slots)
210 {
211 if (!connected(slot))
212 {
213 ETL_ASSERT_OR_RETURN_VALUE(!full(), ETL_ERROR(signal_full), false);
214 append_slot(slot);
215 }
216 }
217
218 return true;
219 }
220 #endif
221
222 //*************************************************************************
228 //*************************************************************************
229 bool connect(const span_type slots) ETL_NOEXCEPT_EXPR(ETL_NOT_USING_EXCEPTIONS)
230 {
231 for (const slot_type& slot : slots)
232 {
233 if (!connected(slot))
234 {
235 ETL_ASSERT_OR_RETURN_VALUE(!full(), ETL_ERROR(signal_full), false);
236 append_slot(slot);
237 }
238 }
239
240 return true;
241 }
242
243 //*************************************************************************
247 //*************************************************************************
248 void disconnect(const slot_type& slot) ETL_NOEXCEPT
249 {
250 const auto end_itr = end();
251 const auto itr = etl::find(begin(), end_itr, slot);
252
253 if (itr != end_itr)
254 {
255 // Shifts all elements after 'itr' one position to the left.
256 etl::copy(etl::next(itr), end_itr, itr);
257 slot_list_end = etl::prev(slot_list_end);
258 }
259 }
260
261 #if ETL_HAS_INITIALIZER_LIST && ETL_USING_CPP17
262 //*************************************************************************
266 //*************************************************************************
267 void disconnect(std::initializer_list<const slot_type> slots) ETL_NOEXCEPT
268 {
269 for (const slot_type& slot : slots)
270 {
271 disconnect(slot);
272 }
273 }
274 #endif
275
276 //*************************************************************************
280 //*************************************************************************
281 void disconnect(const span_type slots) ETL_NOEXCEPT
282 {
283 for (const slot_type& slot : slots)
284 {
285 disconnect(slot);
286 }
287 }
288
289 //*************************************************************************
291 //*************************************************************************
292 void disconnect_all() ETL_NOEXCEPT
293 {
294 slot_list_end = begin();
295 }
296
297 //*************************************************************************
302 //*************************************************************************
303 ETL_CONSTEXPR14 bool connected(const slot_type& slot) const ETL_NOEXCEPT
304 {
305 return etl::any_of(begin(), end(), [&slot](const slot_type& s) { return s == slot; });
306 }
307
308 //*************************************************************************
310 //*************************************************************************
311 ETL_CONSTEXPR14 bool empty() const ETL_NOEXCEPT
312 {
313 return begin() == end();
314 }
315
316 //*************************************************************************
319 //*************************************************************************
320 ETL_CONSTEXPR14 bool full() const ETL_NOEXCEPT
321 {
322 return size() == max_size();
323 }
324
325 //*************************************************************************
327 //*************************************************************************
328 ETL_CONSTEXPR14 size_type max_size() const ETL_NOEXCEPT
329 {
330 return Size;
331 }
332
333 //*************************************************************************
335 //*************************************************************************
336 ETL_CONSTEXPR14 size_type size() const ETL_NOEXCEPT
337 {
338 return static_cast<size_type>(etl::distance(begin(), end()));
339 }
340
341 //*************************************************************************
343 //*************************************************************************
344 ETL_CONSTEXPR14 size_type available() const ETL_NOEXCEPT
345 {
346 return max_size() - size();
347 }
348
349 //*************************************************************************
354 //*************************************************************************
355 template <typename... TArgs>
356 void operator()(TArgs&&... args) const ETL_NOEXCEPT
357 {
358 for (const slot_type& slot : *this)
359 {
360 if (slot_is_valid(slot))
361 {
362 slot(etl::forward<TArgs>(args)...);
363 }
364 }
365 }
366
367 private:
368
369 using iterator = slot_type*;
370 using const_iterator = const slot_type*;
371
372 slot_type slot_list[Size];
373 iterator slot_list_end;
374
375 //*************************************************************************
377 //*************************************************************************
378 void append_slot(const slot_type& slot) ETL_NOEXCEPT
379 {
380 (*slot_list_end) = slot;
381 slot_list_end = etl::next(slot_list_end);
382 }
383
384 //*************************************************************************
386 //*************************************************************************
387 template <typename TSlotType, typename... TArgs>
388 static typename etl::enable_if_t<etl::is_delegate<TSlotType>::value, bool> slot_is_valid(const TSlotType& s) ETL_NOEXCEPT
389 {
390 return s.is_valid();
391 }
392
393 //*************************************************************************
395 //*************************************************************************
396 template <typename TSlotType, typename... TArgs>
397 static typename etl::enable_if_t<!etl::is_delegate<TSlotType>::value, bool> slot_is_valid(const TSlotType&) ETL_NOEXCEPT
398 {
399 return true;
400 }
401
402 //*************************************************************************
404 //*************************************************************************
405 ETL_CONSTEXPR14 iterator begin() ETL_NOEXCEPT
406 {
407 return slot_list;
408 }
409
410 //*************************************************************************
412 //*************************************************************************
413 ETL_CONSTEXPR14 const_iterator begin() const ETL_NOEXCEPT
414 {
415 return slot_list;
416 }
417
418 //*************************************************************************
420 //*************************************************************************
421 ETL_CONSTEXPR14 iterator end() ETL_NOEXCEPT
422 {
423 return slot_list_end;
424 }
425
426 //*************************************************************************
428 //*************************************************************************
429 ETL_CONSTEXPR14 const_iterator end() const ETL_NOEXCEPT
430 {
431 return slot_list_end;
432 }
433 };
434} // namespace etl
435
436#endif
437#endif
ETL_NODISCARD ETL_CONSTEXPR14 bool any_of(TIterator begin, TIterator end, TUnaryPredicate predicate)
Definition algorithm.h:2210
Definition exception.h:59
Definition absolute.h:40
ETL_CONSTEXPR TContainer::size_type size(const TContainer &container)
Definition iterator.h:1434
TContainer::iterator end(TContainer &container)
Definition iterator.h:1166
TContainer::iterator begin(TContainer &container)
Definition iterator.h:1136