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 "algorithm.h"
45 #include "delegate.h"
46 #include "error_handler.h"
47 #include "exception.h"
48 #include "file_error_numbers.h"
49 #include "initializer_list.h"
50 #include "iterator.h"
51 #include "span.h"
52 #include "type_traits.h"
53
54//*****************************************************************************
58//*****************************************************************************
59
60namespace etl
61{
62 //***************************************************************************
65 //***************************************************************************
66 class signal_exception : public exception
67 {
68 public:
69
70 signal_exception(string_type reason_, string_type file_name_, numeric_type line_number_)
71 : exception{reason_, file_name_, line_number_}
72 {
73 }
74 };
75
76 //***************************************************************************
79 //***************************************************************************
80 class signal_full : public signal_exception
81 {
82 public:
83
84 signal_full(string_type file_name_, numeric_type line_number_)
85 : signal_exception{ETL_ERROR_TEXT("signal:full", ETL_SIGNAL_FILE_ID"A"), file_name_, line_number_}
86 {
87 }
88 };
89
90 //***************************************************************************
100 //***************************************************************************
101 template <typename TFunction, size_t Size, typename TSlot = etl::delegate<TFunction>>
102 class signal
103 {
104 public:
105
106 using slot_type = TSlot;
107 using size_type = size_t;
108 using span_type = etl::span<const slot_type>;
109
110 //*************************************************************************
114 //*************************************************************************
115 template <typename... TSlots>
116 ETL_CONSTEXPR14 explicit signal(TSlots&&... slots) ETL_NOEXCEPT
117 : slot_list{etl::forward<TSlots>(slots)...}
118 , slot_list_end{slot_list + sizeof...(slots)}
119 {
120 static_assert((etl::are_all_same<slot_type, etl::decay_t<TSlots>...>::value), "All slots must be slot_type");
121 static_assert(sizeof...(slots) <= Size, "Number of slots exceeds capacity");
122 }
123
124 //*************************************************************************
130 //*************************************************************************
131 bool connect(const slot_type& slot) ETL_NOEXCEPT_EXPR(ETL_NOT_USING_EXCEPTIONS)
132 {
133 if (!connected(slot))
134 {
135 ETL_ASSERT_OR_RETURN_VALUE(!full(), ETL_ERROR(signal_full), false);
136 append_slot(slot);
137 }
138
139 return true;
140 }
141
142 #if ETL_HAS_INITIALIZER_LIST && ETL_USING_CPP17
143 //*************************************************************************
149 //*************************************************************************
150 bool connect(std::initializer_list<const slot_type> slots) ETL_NOEXCEPT_EXPR(ETL_NOT_USING_EXCEPTIONS)
151 {
152 for (const slot_type& slot : slots)
153 {
154 if (!connected(slot))
155 {
156 ETL_ASSERT_OR_RETURN_VALUE(!full(), ETL_ERROR(signal_full), false);
157 append_slot(slot);
158 }
159 }
160
161 return true;
162 }
163 #endif
164
165 //*************************************************************************
171 //*************************************************************************
172 bool connect(const span_type slots) ETL_NOEXCEPT_EXPR(ETL_NOT_USING_EXCEPTIONS)
173 {
174 for (const slot_type& slot : slots)
175 {
176 if (!connected(slot))
177 {
178 ETL_ASSERT_OR_RETURN_VALUE(!full(), ETL_ERROR(signal_full), false);
179 append_slot(slot);
180 }
181 }
182
183 return true;
184 }
185
186 //*************************************************************************
190 //*************************************************************************
191 void disconnect(const slot_type& slot) ETL_NOEXCEPT
192 {
193 const auto end_itr = end();
194 const auto itr = etl::find(begin(), end_itr, slot);
195
196 if (itr != end_itr)
197 {
198 // Shifts all elements after 'itr' one position to the left.
199 etl::copy(etl::next(itr), end_itr, itr);
200 slot_list_end = etl::prev(slot_list_end);
201 }
202 }
203
204 #if ETL_HAS_INITIALIZER_LIST && ETL_USING_CPP17
205 //*************************************************************************
209 //*************************************************************************
210 void disconnect(std::initializer_list<const slot_type> slots) ETL_NOEXCEPT
211 {
212 for (const slot_type& slot : slots)
213 {
214 disconnect(slot);
215 }
216 }
217 #endif
218
219 //*************************************************************************
223 //*************************************************************************
224 void disconnect(const span_type slots) ETL_NOEXCEPT
225 {
226 for (const slot_type& slot : slots)
227 {
228 disconnect(slot);
229 }
230 }
231
232 //*************************************************************************
234 //*************************************************************************
235 void disconnect_all() ETL_NOEXCEPT
236 {
237 slot_list_end = begin();
238 }
239
240 //*************************************************************************
245 //*************************************************************************
246 ETL_CONSTEXPR14 bool connected(const slot_type& slot) const ETL_NOEXCEPT
247 {
248 return etl::any_of(begin(), end(), [&slot](const slot_type& s) { return s == slot; });
249 }
250
251 //*************************************************************************
253 //*************************************************************************
254 ETL_CONSTEXPR14 bool empty() const ETL_NOEXCEPT
255 {
256 return begin() == end();
257 }
258
259 //*************************************************************************
262 //*************************************************************************
263 ETL_CONSTEXPR14 bool full() const ETL_NOEXCEPT
264 {
265 return size() == max_size();
266 }
267
268 //*************************************************************************
270 //*************************************************************************
271 ETL_CONSTEXPR14 size_type max_size() const ETL_NOEXCEPT
272 {
273 return Size;
274 }
275
276 //*************************************************************************
278 //*************************************************************************
279 ETL_CONSTEXPR14 size_type size() const ETL_NOEXCEPT
280 {
281 return static_cast<size_type>(etl::distance(begin(), end()));
282 }
283
284 //*************************************************************************
286 //*************************************************************************
287 ETL_CONSTEXPR14 size_type available() const ETL_NOEXCEPT
288 {
289 return max_size() - size();
290 }
291
292 //*************************************************************************
297 //*************************************************************************
298 template <typename... TArgs>
299 void operator()(TArgs&&... args) const ETL_NOEXCEPT
300 {
301 for (const slot_type& slot : *this)
302 {
303 if (slot_is_valid(slot))
304 {
305 slot(etl::forward<TArgs>(args)...);
306 }
307 }
308 }
309
310 private:
311
312 using iterator = slot_type*;
313 using const_iterator = const slot_type*;
314
315 slot_type slot_list[Size];
316 iterator slot_list_end;
317
318 //*************************************************************************
320 //*************************************************************************
321 void append_slot(const slot_type& slot) ETL_NOEXCEPT
322 {
323 (*slot_list_end) = slot;
324 slot_list_end = etl::next(slot_list_end);
325 }
326
327 //*************************************************************************
329 //*************************************************************************
330 template <typename TSlotType, typename... TArgs>
331 static typename etl::enable_if_t<etl::is_delegate<TSlotType>::value, bool> slot_is_valid(const TSlotType& s) ETL_NOEXCEPT
332 {
333 return s.is_valid();
334 }
335
336 //*************************************************************************
338 //*************************************************************************
339 template <typename TSlotType, typename... TArgs>
340 static typename etl::enable_if_t<!etl::is_delegate<TSlotType>::value, bool> 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} // namespace etl
378
379#endif
380#endif
ETL_NODISCARD ETL_CONSTEXPR14 bool any_of(TIterator begin, TIterator end, TUnaryPredicate predicate)
Definition algorithm.h:2173
Definition exception.h:59
bitset_ext
Definition absolute.h:40
ETL_CONSTEXPR TContainer::size_type size(const TContainer &container)
Definition iterator.h:1192
ETL_CONSTEXPR TContainer::iterator begin(TContainer &container)
Definition iterator.h:967
ETL_CONSTEXPR TContainer::iterator end(TContainer &container)
Definition iterator.h:997