Embedded Template Library 1.0
Loading...
Searching...
No Matches
observer.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) 2014 John Wellbelove
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_OBSERVER_INCLUDED
32#define ETL_OBSERVER_INCLUDED
33
34//*****************************************************************************
51//*****************************************************************************
52
53#include "platform.h"
54#include "algorithm.h"
55#include "error_handler.h"
56#include "exception.h"
57#include "type_list.h"
58#include "utility.h"
59#include "vector.h"
60
61namespace etl
62{
63 //***************************************************************************
66 //***************************************************************************
67 class observer_exception : public exception
68 {
69 public:
70
71 observer_exception(string_type reason_, string_type file_name_, numeric_type line_number_)
72 : exception(reason_, file_name_, line_number_)
73 {
74 }
75 };
76
77 //***************************************************************************
80 //***************************************************************************
81 class observer_list_full : public observer_exception
82 {
83 public:
84
85 observer_list_full(string_type file_name_, numeric_type line_number_)
86 : observer_exception(ETL_ERROR_TEXT("observer:full", ETL_OBSERVER_FILE_ID"A"), file_name_, line_number_)
87 {
88 }
89 };
90
91 //*********************************************************************
96 //*********************************************************************
97 template <typename TObserver, const size_t Max_Observers>
99 {
100 private:
101
102 //***********************************
103 // Item stored in the observer list.
104 //***********************************
105 struct observer_item
106 {
107 observer_item(TObserver& observer_)
108 : p_observer(&observer_)
109 , enabled(true)
110 {
111 }
112
113 TObserver* p_observer;
114 bool enabled;
115 };
116
117 //***********************************
118 // How to compare an observer with an observer list item.
119 //***********************************
120 struct compare_observers
121 {
122 compare_observers(TObserver& observer_)
123 : p_observer(&observer_)
124 {
125 }
126
127 bool operator()(const observer_item& item) const
128 {
129 return p_observer == item.p_observer;
130 }
131
132 TObserver* p_observer;
133 };
134
135 public:
136
137 typedef size_t size_type;
138
139 typedef etl::vector<observer_item, Max_Observers> Observer_List;
140
141 //*****************************************************************
147 //*****************************************************************
148 void add_observer(TObserver& observer)
149 {
150 // See if we already have it in our list.
151 typename Observer_List::iterator i_observer_item = find_observer(observer);
152
153 // Not there?
154 if (i_observer_item == observer_list.end())
155 {
156 // Is there enough room?
157 ETL_ASSERT_OR_RETURN(!observer_list.full(), ETL_ERROR(etl::observer_list_full));
158
159 // Add it.
160 observer_list.push_back(observer_item(observer));
161 }
162 }
163
164 //*****************************************************************
168 //*****************************************************************
169 bool remove_observer(TObserver& observer)
170 {
171 // See if we have it in our list.
172 typename Observer_List::iterator i_observer_item = find_observer(observer);
173
174 // Found it?
175 if (i_observer_item != observer_list.end())
176 {
177 // Erase it.
178 observer_list.erase(i_observer_item);
179 return true;
180 }
181 else
182 {
183 return false;
184 }
185 }
186
187 //*****************************************************************
192 //*****************************************************************
193 void enable_observer(TObserver& observer, bool state = true)
194 {
195 // See if we have it in our list.
196 typename Observer_List::iterator i_observer_item = find_observer(observer);
197
198 // Found it?
199 if (i_observer_item != observer_list.end())
200 {
201 i_observer_item->enabled = state;
202 }
203 }
204
205 //*****************************************************************
207 //*****************************************************************
208 void disable_observer(TObserver& observer)
209 {
210 // See if we have it in our list.
211 typename Observer_List::iterator i_observer_item = find_observer(observer);
212
213 // Found it?
214 if (i_observer_item != observer_list.end())
215 {
216 i_observer_item->enabled = false;
217 }
218 }
219
220 //*****************************************************************
222 //*****************************************************************
224 {
225 observer_list.clear();
226 }
227
228 //*****************************************************************
230 //*****************************************************************
231 size_type number_of_observers() const
232 {
233 return observer_list.size();
234 }
235
236 //*****************************************************************
240 //*****************************************************************
241 template <typename TNotification>
242 void notify_observers(TNotification n)
243 {
244 typename Observer_List::iterator i_observer_item = observer_list.begin();
245
246 while (i_observer_item != observer_list.end())
247 {
248 if (i_observer_item->enabled)
249 {
250 i_observer_item->p_observer->notification(n);
251 }
252
253 ++i_observer_item;
254 }
255 }
256
257 //*****************************************************************
259 //*****************************************************************
261 {
262 typename Observer_List::iterator i_observer_item = observer_list.begin();
263
264 while (i_observer_item != observer_list.end())
265 {
266 if (i_observer_item->enabled)
267 {
268 i_observer_item->p_observer->notification();
269 }
270
271 ++i_observer_item;
272 }
273 }
274
275 protected:
276
277 ~observable() {}
278
279 private:
280
281 //*****************************************************************
284 //*****************************************************************
285 typename Observer_List::iterator find_observer(TObserver& observer_)
286 {
287 return etl::find_if(observer_list.begin(), observer_list.end(), compare_observers(observer_));
288 }
289
291 Observer_List observer_list;
292 };
293
294#if ETL_USING_CPP11 && !defined(ETL_OBSERVER_FORCE_CPP03_IMPLEMENTATION)
295 template <typename... TTypes>
296 class observer;
297
298 //*****************************************************************
301 //*****************************************************************
302 template <typename T1, typename... TRest>
303 class observer<T1, TRest...>
304 : public observer<T1>
305 , public observer<TRest...>
306 {
307 public:
308
309 ETL_STATIC_ASSERT((!etl::has_duplicates<T1, TRest...>::value), "Observer has duplicate notification types");
310
311 using observer<T1>::notification;
312 using observer<TRest...>::notification;
313 using type_list = etl::type_list<T1, TRest...>;
314 };
315
316 //*****************************************************************
319 //*****************************************************************
320 template <typename T1>
321 class observer<T1>
322 {
323 public:
324
325 using type_list = etl::type_list<T1>;
326
327 virtual ~observer() = default;
328
329 virtual void notification(T1) = 0;
330 };
331
332 //*****************************************************************
335 //*****************************************************************
336 template <>
337 class observer<void>
338 {
339 public:
340
341 using type_list = etl::type_list<>;
342
343 virtual ~observer() = default;
344
345 virtual void notification() = 0;
346 };
347
348 //***************************************************************************
350 template <typename TList>
351 struct observer_from_type_list;
352
353 template <typename... TTypes>
354 struct observer_from_type_list<etl::type_list<TTypes...>>
355 {
356 using type = etl::observer<TTypes...>;
357 };
358
359 template <typename TTypeList>
360 using observer_from_type_list_t = typename observer_from_type_list<TTypeList>::type;
361
362#else
363
364 //*********************************************************************
367 //*********************************************************************
368 template <typename T1, typename T2 = void, typename T3 = void, typename T4 = void, typename T5 = void, typename T6 = void, typename T7 = void,
369 typename T8 = void>
371 : public observer<T1>
372 , public observer<T2>
373 , public observer<T3>
374 , public observer<T4>
375 , public observer<T5>
376 , public observer<T6>
377 , public observer<T7>
378 , public observer<T8>
379 {
380 public:
381
382 virtual ~observer() {}
383
384 using observer<T1>::notification;
385 using observer<T2>::notification;
386 using observer<T3>::notification;
387 using observer<T4>::notification;
388 using observer<T5>::notification;
389 using observer<T6>::notification;
390 using observer<T7>::notification;
391 using observer<T8>::notification;
392 };
393
394 //*********************************************************************
397 //*********************************************************************
398 template <typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7>
399 class observer<T1, T2, T3, T4, T5, T6, T7>
400 : public observer<T1>
401 , public observer<T2>
402 , public observer<T3>
403 , public observer<T4>
404 , public observer<T5>
405 , public observer<T6>
406 , public observer<T7>
407 {
408 public:
409
410 virtual ~observer() {}
411 using observer<T1>::notification;
412 using observer<T2>::notification;
413 using observer<T3>::notification;
414 using observer<T4>::notification;
415 using observer<T5>::notification;
416 using observer<T6>::notification;
417 using observer<T7>::notification;
418 };
419
420 //*********************************************************************
423 //*********************************************************************
424 template <typename T1, typename T2, typename T3, typename T4, typename T5, typename T6>
425 class observer<T1, T2, T3, T4, T5, T6>
426 : public observer<T1>
427 , public observer<T2>
428 , public observer<T3>
429 , public observer<T4>
430 , public observer<T5>
431 , public observer<T6>
432 {
433 public:
434
435 virtual ~observer() {}
436 using observer<T1>::notification;
437 using observer<T2>::notification;
438 using observer<T3>::notification;
439 using observer<T4>::notification;
440 using observer<T5>::notification;
441 using observer<T6>::notification;
442 };
443
444 //*********************************************************************
447 //*********************************************************************
448 template <typename T1, typename T2, typename T3, typename T4, typename T5>
449 class observer<T1, T2, T3, T4, T5>
450 : public observer<T1>
451 , public observer<T2>
452 , public observer<T3>
453 , public observer<T4>
454 , public observer<T5>
455 {
456 public:
457
458 virtual ~observer() {}
459 using observer<T1>::notification;
460 using observer<T2>::notification;
461 using observer<T3>::notification;
462 using observer<T4>::notification;
463 using observer<T5>::notification;
464 };
465
466 //*********************************************************************
469 //*********************************************************************
470 template <typename T1, typename T2, typename T3, typename T4>
471 class observer<T1, T2, T3, T4>
472 : public observer<T1>
473 , public observer<T2>
474 , public observer<T3>
475 , public observer<T4>
476 {
477 public:
478
479 virtual ~observer() {}
480 using observer<T1>::notification;
481 using observer<T2>::notification;
482 using observer<T3>::notification;
483 using observer<T4>::notification;
484 };
485
486 //*********************************************************************
489 //*********************************************************************
490 template <typename T1, typename T2, typename T3>
491 class observer<T1, T2, T3>
492 : public observer<T1>
493 , public observer<T2>
494 , public observer<T3>
495 {
496 public:
497
498 virtual ~observer() {}
499 using observer<T1>::notification;
500 using observer<T2>::notification;
501 using observer<T3>::notification;
502 };
503
504 //*********************************************************************
507 //*********************************************************************
508 template <typename T1, typename T2>
509 class observer<T1, T2>
510 : public observer<T1>
511 , public observer<T2>
512 {
513 public:
514
515 virtual ~observer() {}
516 using observer<T1>::notification;
517 using observer<T2>::notification;
518 };
519
520 //*********************************************************************
523 //*********************************************************************
524 template <typename T1>
525 class observer<T1>
526 {
527 public:
528
529 virtual ~observer() {}
530 virtual void notification(T1) = 0;
531 };
532
533 //*********************************************************************
536 //*********************************************************************
537 template <>
538 class observer<void>
539 {
540 public:
541
542 virtual ~observer() {}
543 virtual void notification() = 0;
544 };
545
546#endif
547} // namespace etl
548
549#endif
ETL_EXCEPTION_CONSTEXPR exception(string_type reason_, string_type, numeric_type)
Constructor.
Definition exception.h:81
void add_observer(TObserver &observer)
Definition observer.h:148
bool remove_observer(TObserver &observer)
Definition observer.h:169
void notify_observers(TNotification n)
Definition observer.h:242
void notify_observers()
Notify all of the observers, sending them the notification.
Definition observer.h:260
void disable_observer(TObserver &observer)
Disable an observer.
Definition observer.h:208
void enable_observer(TObserver &observer, bool state=true)
Definition observer.h:193
size_type number_of_observers() const
Returns the number of observers.
Definition observer.h:231
void clear_observers()
Clear all observers from the list.
Definition observer.h:223
Definition observer.h:99
Definition observer.h:379
Definition observer.h:82
iterator begin()
Definition vector.h:99
iterator end()
Definition vector.h:117
Definition vector.h:1277
bitset_ext
Definition absolute.h:40