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_NOT_USING_CPP11 && !defined(ETL_IN_UNIT_TEST)
39#error NOT SUPPORTED FOR C++03 OR BELOW
40#endif
41
42#if ETL_USING_CPP11
43
44#include "exception.h"
45#include "error_handler.h"
46#include "delegate.h"
47#include "algorithm.h"
48#include "iterator.h"
49#include "type_traits.h"
50#include "initializer_list.h"
51#include "span.h"
52#include "file_error_numbers.h"
53
54//*****************************************************************************
58//*****************************************************************************
59
60namespace etl
61{
62 //***************************************************************************
65 //***************************************************************************
66 class signal_exception : public exception
67 {
68 public:
69 signal_exception(string_type reason_, string_type file_name_, numeric_type line_number_)
70 : exception{reason_, file_name_, line_number_}
71 {
72 }
73 };
74
75 //***************************************************************************
78 //***************************************************************************
79 class signal_full : public signal_exception
80 {
81 public:
82 signal_full(string_type file_name_, numeric_type line_number_)
83 : signal_exception{ETL_ERROR_TEXT("signal:full", ETL_SIGNAL_FILE_ID"A"), file_name_, line_number_}
84 {
85 }
86 };
87
88 //***************************************************************************
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 //*************************************************************************
127 //*************************************************************************
128 bool connect(const slot_type& slot) ETL_NOEXCEPT_EXPR(ETL_NOT_USING_EXCEPTIONS)
129 {
130 if (!connected(slot))
131 {
132 ETL_ASSERT_OR_RETURN_VALUE(!full(), ETL_ERROR(signal_full), false);
133 append_slot(slot);
134 }
135
136 return true;
137 }
138
139#if ETL_HAS_INITIALIZER_LIST && ETL_USING_CPP17
140 //*************************************************************************
146 //*************************************************************************
147 bool connect(std::initializer_list<const slot_type> slots) ETL_NOEXCEPT_EXPR(ETL_NOT_USING_EXCEPTIONS)
148 {
149 for (const slot_type& slot : slots)
150 {
151 if (!connected(slot))
152 {
153 ETL_ASSERT_OR_RETURN_VALUE(!full(), ETL_ERROR(signal_full), false);
154 append_slot(slot);
155 }
156 }
157
158 return true;
159 }
160#endif
161
162 //*************************************************************************
168 //*************************************************************************
169 bool connect(const span_type slots) ETL_NOEXCEPT_EXPR(ETL_NOT_USING_EXCEPTIONS)
170 {
171 for (const slot_type& slot : slots)
172 {
173 if (!connected(slot))
174 {
175 ETL_ASSERT_OR_RETURN_VALUE(!full(), ETL_ERROR(signal_full), false);
176 append_slot(slot);
177 }
178 }
179
180 return true;
181 }
182
183 //*************************************************************************
187 //*************************************************************************
188 void disconnect(const slot_type& slot) ETL_NOEXCEPT
189 {
190 const auto end_itr = end();
191 const auto itr = etl::find(begin(), end_itr, slot);
192
193 if (itr != end_itr)
194 {
195 // Shifts all elements after 'itr' one position to the left.
196 etl::copy(etl::next(itr), end_itr, itr);
197 slot_list_end = etl::prev(slot_list_end);
198 }
199 }
200
201#if ETL_HAS_INITIALIZER_LIST && ETL_USING_CPP17
202 //*************************************************************************
206 //*************************************************************************
207 void disconnect(std::initializer_list<const slot_type> slots) ETL_NOEXCEPT
208 {
209 for (const slot_type& slot : slots)
210 {
211 disconnect(slot);
212 }
213 }
214#endif
215
216 //*************************************************************************
220 //*************************************************************************
221 void disconnect(const span_type slots) ETL_NOEXCEPT
222 {
223 for (const slot_type& slot : slots)
224 {
225 disconnect(slot);
226 }
227 }
228
229 //*************************************************************************
231 //*************************************************************************
232 void disconnect_all() ETL_NOEXCEPT
233 {
234 slot_list_end = begin();
235 }
236
237 //*************************************************************************
242 //*************************************************************************
243 ETL_CONSTEXPR14 bool connected(const slot_type& slot) const ETL_NOEXCEPT
244 {
245 return etl::any_of(begin(), end(), [&slot](const slot_type& s) { return s == slot; });
246 }
247
248 //*************************************************************************
250 //*************************************************************************
251 ETL_CONSTEXPR14 bool empty() const ETL_NOEXCEPT
252 {
253 return begin() == end();
254 }
255
256 //*************************************************************************
258 //*************************************************************************
259 ETL_CONSTEXPR14 bool full() const ETL_NOEXCEPT
260 {
261 return size() == max_size();
262 }
263
264 //*************************************************************************
266 //*************************************************************************
267 ETL_CONSTEXPR14 size_type max_size() const ETL_NOEXCEPT
268 {
269 return Size;
270 }
271
272 //*************************************************************************
274 //*************************************************************************
275 ETL_CONSTEXPR14 size_type size() const ETL_NOEXCEPT
276 {
277 return etl::distance(begin(), end());
278 }
279
280 //*************************************************************************
282 //*************************************************************************
283 ETL_CONSTEXPR14 size_type available() const ETL_NOEXCEPT
284 {
285 return max_size() - size();
286 }
287
288 //*************************************************************************
293 //*************************************************************************
294 template <typename... TArgs>
295 void operator()(TArgs&&... args) const ETL_NOEXCEPT
296 {
297 for (const slot_type& slot : *this)
298 {
299 if (slot_is_valid(slot))
300 {
301 slot(etl::forward<TArgs>(args)...);
302 }
303 }
304 }
305
306 private:
307
308 using iterator = slot_type*;
309 using const_iterator = const slot_type*;
310
311 slot_type slot_list[Size];
312 iterator slot_list_end;
313
314 //*************************************************************************
316 //*************************************************************************
317 void append_slot(const slot_type& slot) ETL_NOEXCEPT
318 {
319 (*slot_list_end) = slot;
320 slot_list_end = etl::next(slot_list_end);
321 }
322
323 //*************************************************************************
325 //*************************************************************************
326 template <typename TSlotType, typename... TArgs>
327 static
328 typename etl::enable_if_t<etl::is_delegate<TSlotType>::value, bool>
329 slot_is_valid(const TSlotType& s) ETL_NOEXCEPT
330 {
331 return s.is_valid();
332 }
333
334 //*************************************************************************
336 //*************************************************************************
337 template <typename TSlotType, typename... TArgs>
338 static
339 typename etl::enable_if_t<!etl::is_delegate<TSlotType>::value, bool>
340 slot_is_valid(const TSlotType&) ETL_NOEXCEPT
341 {
342 return true;
343 }
344
345 //*************************************************************************
347 //*************************************************************************
348 ETL_CONSTEXPR14 iterator begin() ETL_NOEXCEPT
349 {
350 return slot_list;
351 }
352
353 //*************************************************************************
355 //*************************************************************************
356 ETL_CONSTEXPR14 const_iterator begin() const ETL_NOEXCEPT
357 {
358 return slot_list;
359 }
360
361 //*************************************************************************
363 //*************************************************************************
364 ETL_CONSTEXPR14 iterator end() ETL_NOEXCEPT
365 {
366 return slot_list_end;
367 }
368
369 //*************************************************************************
371 //*************************************************************************
372 ETL_CONSTEXPR14 const_iterator end() const ETL_NOEXCEPT
373 {
374 return slot_list_end;
375 }
376 };
377}
378
379#endif
380#endif
ETL_NODISCARD ETL_CONSTEXPR14 bool any_of(TIterator begin, TIterator end, TUnaryPredicate predicate)
Definition algorithm.h:2116
Definition exception.h:47
bitset_ext
Definition absolute.h:39
size_t max_size() const
Returns the maximum number of items in the variant_pool.
Definition variant_pool_generator.h:395
ETL_CONSTEXPR TContainer::size_type size(const TContainer &container)
Definition iterator.h:1187
ETL_CONSTEXPR TContainer::iterator begin(TContainer &container)
Definition iterator.h:962
ETL_CONSTEXPR TContainer::iterator end(TContainer &container)
Definition iterator.h:992