diff options
author | Mike Buland <eichlan@xagasoft.com> | 2009-12-16 21:22:39 +0000 |
---|---|---|
committer | Mike Buland <eichlan@xagasoft.com> | 2009-12-16 21:22:39 +0000 |
commit | afac5804b069e5eb76c799e9edd2eaeff0d99b94 (patch) | |
tree | d2b3a51f899c7ad1bb828885ff8178613f9ebd63 | |
parent | f72c6e4b97afeb69d9ea4d743c0c302d647ea424 (diff) | |
download | libbu++-afac5804b069e5eb76c799e9edd2eaeff0d99b94.tar.gz libbu++-afac5804b069e5eb76c799e9edd2eaeff0d99b94.tar.bz2 libbu++-afac5804b069e5eb76c799e9edd2eaeff0d99b94.tar.xz libbu++-afac5804b069e5eb76c799e9edd2eaeff0d99b94.zip |
Signals are now not only typesafe, but also will throw an exception if you try
to construct a slot with a null pointer, or call a signal that has not been set
yet. Also, signals can be checked for being set, and assigned to one another.
-rw-r--r-- | src/signals.cpp | 3 | ||||
-rw-r--r-- | src/signals.h | 75 |
2 files changed, 78 insertions, 0 deletions
diff --git a/src/signals.cpp b/src/signals.cpp new file mode 100644 index 0000000..7952053 --- /dev/null +++ b/src/signals.cpp | |||
@@ -0,0 +1,3 @@ | |||
1 | #include "bu/signals.h" | ||
2 | |||
3 | namespace Bu { subExceptionDef( SignalException ) } | ||
diff --git a/src/signals.h b/src/signals.h index 722f928..3f892b8 100644 --- a/src/signals.h +++ b/src/signals.h | |||
@@ -2,9 +2,11 @@ | |||
2 | #define BU_OBJECT_SIGNALS_H | 2 | #define BU_OBJECT_SIGNALS_H |
3 | 3 | ||
4 | #include "bu/util.h" | 4 | #include "bu/util.h" |
5 | #include "bu/exceptionbase.h" | ||
5 | 6 | ||
6 | namespace Bu | 7 | namespace Bu |
7 | { | 8 | { |
9 | subExceptionDecl( SignalException ); | ||
8 | // | 10 | // |
9 | // 0 Parameters | 11 | // 0 Parameters |
10 | // | 12 | // |
@@ -31,6 +33,7 @@ namespace Bu | |||
31 | 33 | ||
32 | virtual ret operator()() | 34 | virtual ret operator()() |
33 | { | 35 | { |
36 | |||
34 | return (pCls->*pFnc)(); | 37 | return (pCls->*pFnc)(); |
35 | } | 38 | } |
36 | 39 | ||
@@ -79,9 +82,19 @@ namespace Bu | |||
79 | 82 | ||
80 | ret operator()() | 83 | ret operator()() |
81 | { | 84 | { |
85 | if( !pCb ) throw SignalException("Uninitialized signal used."); | ||
82 | return (*pCb)(); | 86 | return (*pCb)(); |
83 | } | 87 | } |
84 | 88 | ||
89 | bool isSet() const { return pCb != NULL; } | ||
90 | operator bool() const { return isSet(); } | ||
91 | |||
92 | Signal0 &operator=( const Signal0 &rhs ) | ||
93 | { | ||
94 | pCb = rhs.pCb->clone(); | ||
95 | return *this; | ||
96 | } | ||
97 | |||
85 | private: | 98 | private: |
86 | _Slot0<ret> *pCb; | 99 | _Slot0<ret> *pCb; |
87 | }; | 100 | }; |
@@ -89,6 +102,7 @@ namespace Bu | |||
89 | template<typename cls, typename ret> | 102 | template<typename cls, typename ret> |
90 | Signal0<ret> slot( cls *pCls, ret (cls::*pFnc)() ) | 103 | Signal0<ret> slot( cls *pCls, ret (cls::*pFnc)() ) |
91 | { | 104 | { |
105 | if( !pCls || !pFnc ) throw SignalException("NULL pointer in slot()."); | ||
92 | return Signal0<ret>( | 106 | return Signal0<ret>( |
93 | new __Slot0<cls, ret>( pCls, pFnc ) | 107 | new __Slot0<cls, ret>( pCls, pFnc ) |
94 | ); | 108 | ); |
@@ -97,6 +111,7 @@ namespace Bu | |||
97 | template<typename ret> | 111 | template<typename ret> |
98 | Signal0<ret> slot( ret (*pFnc)() ) | 112 | Signal0<ret> slot( ret (*pFnc)() ) |
99 | { | 113 | { |
114 | if( !pFnc ) throw SignalException("NULL pointer in slot()."); | ||
100 | return Signal0<ret>( | 115 | return Signal0<ret>( |
101 | new __Slot0F<ret>( pFnc ) | 116 | new __Slot0F<ret>( pFnc ) |
102 | ); | 117 | ); |
@@ -176,9 +191,19 @@ namespace Bu | |||
176 | 191 | ||
177 | ret operator()( p1t p1 ) | 192 | ret operator()( p1t p1 ) |
178 | { | 193 | { |
194 | if( !pCb ) throw SignalException("Uninitialized signal used."); | ||
179 | return (*pCb)( p1 ); | 195 | return (*pCb)( p1 ); |
180 | } | 196 | } |
181 | 197 | ||
198 | bool isSet() const { return pCb != NULL; } | ||
199 | operator bool() const { return isSet(); } | ||
200 | |||
201 | Signal1 &operator=( const Signal1 &rhs ) | ||
202 | { | ||
203 | pCb = rhs.pCb->clone(); | ||
204 | return *this; | ||
205 | } | ||
206 | |||
182 | private: | 207 | private: |
183 | _Slot1<ret, p1t> *pCb; | 208 | _Slot1<ret, p1t> *pCb; |
184 | }; | 209 | }; |
@@ -186,6 +211,7 @@ namespace Bu | |||
186 | template<typename cls, typename ret, typename p1t> | 211 | template<typename cls, typename ret, typename p1t> |
187 | Signal1<ret, p1t> slot( cls *pCls, ret (cls::*pFnc)( p1t ) ) | 212 | Signal1<ret, p1t> slot( cls *pCls, ret (cls::*pFnc)( p1t ) ) |
188 | { | 213 | { |
214 | if( !pCls || !pFnc ) throw SignalException("NULL pointer in slot()."); | ||
189 | return Signal1<ret, p1t>( | 215 | return Signal1<ret, p1t>( |
190 | new __Slot1<cls, ret, p1t>( pCls, pFnc ) | 216 | new __Slot1<cls, ret, p1t>( pCls, pFnc ) |
191 | ); | 217 | ); |
@@ -194,6 +220,7 @@ namespace Bu | |||
194 | template<typename ret, typename p1t> | 220 | template<typename ret, typename p1t> |
195 | Signal1<ret, p1t> slot( ret (*pFnc)( p1t ) ) | 221 | Signal1<ret, p1t> slot( ret (*pFnc)( p1t ) ) |
196 | { | 222 | { |
223 | if( !pFnc ) throw SignalException("NULL pointer in slot()."); | ||
197 | return Signal1<ret, p1t>( | 224 | return Signal1<ret, p1t>( |
198 | new __Slot1F<ret, p1t>( pFnc ) | 225 | new __Slot1F<ret, p1t>( pFnc ) |
199 | ); | 226 | ); |
@@ -273,9 +300,19 @@ namespace Bu | |||
273 | 300 | ||
274 | ret operator()( p1t p1, p2t p2 ) | 301 | ret operator()( p1t p1, p2t p2 ) |
275 | { | 302 | { |
303 | if( !pCb ) throw SignalException("Uninitialized signal used."); | ||
276 | return (*pCb)( p1, p2 ); | 304 | return (*pCb)( p1, p2 ); |
277 | } | 305 | } |
278 | 306 | ||
307 | bool isSet() const { return pCb != NULL; } | ||
308 | operator bool() const { return isSet(); } | ||
309 | |||
310 | Signal2 &operator=( const Signal2 &rhs ) | ||
311 | { | ||
312 | pCb = rhs.pCb->clone(); | ||
313 | return *this; | ||
314 | } | ||
315 | |||
279 | private: | 316 | private: |
280 | _Slot2<ret, p1t, p2t> *pCb; | 317 | _Slot2<ret, p1t, p2t> *pCb; |
281 | }; | 318 | }; |
@@ -283,6 +320,7 @@ namespace Bu | |||
283 | template<typename cls, typename ret, typename p1t, typename p2t> | 320 | template<typename cls, typename ret, typename p1t, typename p2t> |
284 | Signal2<ret, p1t, p2t> slot( cls *pCls, ret (cls::*pFnc)( p1t, p2t ) ) | 321 | Signal2<ret, p1t, p2t> slot( cls *pCls, ret (cls::*pFnc)( p1t, p2t ) ) |
285 | { | 322 | { |
323 | if( !pCls || !pFnc ) throw SignalException("NULL pointer in slot()."); | ||
286 | return Signal2<ret, p1t, p2t>( | 324 | return Signal2<ret, p1t, p2t>( |
287 | new __Slot2<cls, ret, p1t, p2t>( pCls, pFnc ) | 325 | new __Slot2<cls, ret, p1t, p2t>( pCls, pFnc ) |
288 | ); | 326 | ); |
@@ -291,6 +329,7 @@ namespace Bu | |||
291 | template<typename ret, typename p1t, typename p2t> | 329 | template<typename ret, typename p1t, typename p2t> |
292 | Signal2<ret, p1t, p2t> slot( ret (*pFnc)( p1t, p2t ) ) | 330 | Signal2<ret, p1t, p2t> slot( ret (*pFnc)( p1t, p2t ) ) |
293 | { | 331 | { |
332 | if( !pFnc ) throw SignalException("NULL pointer in slot()."); | ||
294 | return Signal2<ret, p1t, p2t>( | 333 | return Signal2<ret, p1t, p2t>( |
295 | new __Slot2F<ret, p1t, p2t>( pFnc ) | 334 | new __Slot2F<ret, p1t, p2t>( pFnc ) |
296 | ); | 335 | ); |
@@ -370,9 +409,19 @@ namespace Bu | |||
370 | 409 | ||
371 | ret operator()( p1t p1, p2t p2, p3t p3 ) | 410 | ret operator()( p1t p1, p2t p2, p3t p3 ) |
372 | { | 411 | { |
412 | if( !pCb ) throw SignalException("Uninitialized signal used."); | ||
373 | return (*pCb)( p1, p2, p3 ); | 413 | return (*pCb)( p1, p2, p3 ); |
374 | } | 414 | } |
375 | 415 | ||
416 | bool isSet() const { return pCb != NULL; } | ||
417 | operator bool() const { return isSet(); } | ||
418 | |||
419 | Signal3 &operator=( const Signal3 &rhs ) | ||
420 | { | ||
421 | pCb = rhs.pCb->clone(); | ||
422 | return *this; | ||
423 | } | ||
424 | |||
376 | private: | 425 | private: |
377 | _Slot3<ret, p1t, p2t, p3t> *pCb; | 426 | _Slot3<ret, p1t, p2t, p3t> *pCb; |
378 | }; | 427 | }; |
@@ -380,6 +429,7 @@ namespace Bu | |||
380 | template<typename cls, typename ret, typename p1t, typename p2t, typename p3t> | 429 | template<typename cls, typename ret, typename p1t, typename p2t, typename p3t> |
381 | Signal3<ret, p1t, p2t, p3t> slot( cls *pCls, ret (cls::*pFnc)( p1t, p2t, p3t ) ) | 430 | Signal3<ret, p1t, p2t, p3t> slot( cls *pCls, ret (cls::*pFnc)( p1t, p2t, p3t ) ) |
382 | { | 431 | { |
432 | if( !pCls || !pFnc ) throw SignalException("NULL pointer in slot()."); | ||
383 | return Signal3<ret, p1t, p2t, p3t>( | 433 | return Signal3<ret, p1t, p2t, p3t>( |
384 | new __Slot3<cls, ret, p1t, p2t, p3t>( pCls, pFnc ) | 434 | new __Slot3<cls, ret, p1t, p2t, p3t>( pCls, pFnc ) |
385 | ); | 435 | ); |
@@ -388,6 +438,7 @@ namespace Bu | |||
388 | template<typename ret, typename p1t, typename p2t, typename p3t> | 438 | template<typename ret, typename p1t, typename p2t, typename p3t> |
389 | Signal3<ret, p1t, p2t, p3t> slot( ret (*pFnc)( p1t, p2t, p3t ) ) | 439 | Signal3<ret, p1t, p2t, p3t> slot( ret (*pFnc)( p1t, p2t, p3t ) ) |
390 | { | 440 | { |
441 | if( !pFnc ) throw SignalException("NULL pointer in slot()."); | ||
391 | return Signal3<ret, p1t, p2t, p3t>( | 442 | return Signal3<ret, p1t, p2t, p3t>( |
392 | new __Slot3F<ret, p1t, p2t, p3t>( pFnc ) | 443 | new __Slot3F<ret, p1t, p2t, p3t>( pFnc ) |
393 | ); | 444 | ); |
@@ -467,9 +518,19 @@ namespace Bu | |||
467 | 518 | ||
468 | ret operator()( p1t p1, p2t p2, p3t p3, p4t p4 ) | 519 | ret operator()( p1t p1, p2t p2, p3t p3, p4t p4 ) |
469 | { | 520 | { |
521 | if( !pCb ) throw SignalException("Uninitialized signal used."); | ||
470 | return (*pCb)( p1, p2, p3, p4 ); | 522 | return (*pCb)( p1, p2, p3, p4 ); |
471 | } | 523 | } |
472 | 524 | ||
525 | bool isSet() const { return pCb != NULL; } | ||
526 | operator bool() const { return isSet(); } | ||
527 | |||
528 | Signal4 &operator=( const Signal4 &rhs ) | ||
529 | { | ||
530 | pCb = rhs.pCb->clone(); | ||
531 | return *this; | ||
532 | } | ||
533 | |||
473 | private: | 534 | private: |
474 | _Slot4<ret, p1t, p2t, p3t, p4t> *pCb; | 535 | _Slot4<ret, p1t, p2t, p3t, p4t> *pCb; |
475 | }; | 536 | }; |
@@ -477,6 +538,7 @@ namespace Bu | |||
477 | template<typename cls, typename ret, typename p1t, typename p2t, typename p3t, typename p4t> | 538 | template<typename cls, typename ret, typename p1t, typename p2t, typename p3t, typename p4t> |
478 | Signal4<ret, p1t, p2t, p3t, p4t> slot( cls *pCls, ret (cls::*pFnc)( p1t, p2t, p3t, p4t ) ) | 539 | Signal4<ret, p1t, p2t, p3t, p4t> slot( cls *pCls, ret (cls::*pFnc)( p1t, p2t, p3t, p4t ) ) |
479 | { | 540 | { |
541 | if( !pCls || !pFnc ) throw SignalException("NULL pointer in slot()."); | ||
480 | return Signal4<ret, p1t, p2t, p3t, p4t>( | 542 | return Signal4<ret, p1t, p2t, p3t, p4t>( |
481 | new __Slot4<cls, ret, p1t, p2t, p3t, p4t>( pCls, pFnc ) | 543 | new __Slot4<cls, ret, p1t, p2t, p3t, p4t>( pCls, pFnc ) |
482 | ); | 544 | ); |
@@ -485,6 +547,7 @@ namespace Bu | |||
485 | template<typename ret, typename p1t, typename p2t, typename p3t, typename p4t> | 547 | template<typename ret, typename p1t, typename p2t, typename p3t, typename p4t> |
486 | Signal4<ret, p1t, p2t, p3t, p4t> slot( ret (*pFnc)( p1t, p2t, p3t, p4t ) ) | 548 | Signal4<ret, p1t, p2t, p3t, p4t> slot( ret (*pFnc)( p1t, p2t, p3t, p4t ) ) |
487 | { | 549 | { |
550 | if( !pFnc ) throw SignalException("NULL pointer in slot()."); | ||
488 | return Signal4<ret, p1t, p2t, p3t, p4t>( | 551 | return Signal4<ret, p1t, p2t, p3t, p4t>( |
489 | new __Slot4F<ret, p1t, p2t, p3t, p4t>( pFnc ) | 552 | new __Slot4F<ret, p1t, p2t, p3t, p4t>( pFnc ) |
490 | ); | 553 | ); |
@@ -564,9 +627,19 @@ namespace Bu | |||
564 | 627 | ||
565 | ret operator()( p1t p1, p2t p2, p3t p3, p4t p4, p5t p5 ) | 628 | ret operator()( p1t p1, p2t p2, p3t p3, p4t p4, p5t p5 ) |
566 | { | 629 | { |
630 | if( !pCb ) throw SignalException("Uninitialized signal used."); | ||
567 | return (*pCb)( p1, p2, p3, p4, p5 ); | 631 | return (*pCb)( p1, p2, p3, p4, p5 ); |
568 | } | 632 | } |
569 | 633 | ||
634 | bool isSet() const { return pCb != NULL; } | ||
635 | operator bool() const { return isSet(); } | ||
636 | |||
637 | Signal5 &operator=( const Signal5 &rhs ) | ||
638 | { | ||
639 | pCb = rhs.pCb->clone(); | ||
640 | return *this; | ||
641 | } | ||
642 | |||
570 | private: | 643 | private: |
571 | _Slot5<ret, p1t, p2t, p3t, p4t, p5t> *pCb; | 644 | _Slot5<ret, p1t, p2t, p3t, p4t, p5t> *pCb; |
572 | }; | 645 | }; |
@@ -574,6 +647,7 @@ namespace Bu | |||
574 | template<typename cls, typename ret, typename p1t, typename p2t, typename p3t, typename p4t, typename p5t> | 647 | template<typename cls, typename ret, typename p1t, typename p2t, typename p3t, typename p4t, typename p5t> |
575 | Signal5<ret, p1t, p2t, p3t, p4t, p5t> slot( cls *pCls, ret (cls::*pFnc)( p1t, p2t, p3t, p4t, p5t ) ) | 648 | Signal5<ret, p1t, p2t, p3t, p4t, p5t> slot( cls *pCls, ret (cls::*pFnc)( p1t, p2t, p3t, p4t, p5t ) ) |
576 | { | 649 | { |
650 | if( !pCls || !pFnc ) throw SignalException("NULL pointer in slot()."); | ||
577 | return Signal5<ret, p1t, p2t, p3t, p4t, p5t>( | 651 | return Signal5<ret, p1t, p2t, p3t, p4t, p5t>( |
578 | new __Slot5<cls, ret, p1t, p2t, p3t, p4t, p5t>( pCls, pFnc ) | 652 | new __Slot5<cls, ret, p1t, p2t, p3t, p4t, p5t>( pCls, pFnc ) |
579 | ); | 653 | ); |
@@ -582,6 +656,7 @@ namespace Bu | |||
582 | template<typename ret, typename p1t, typename p2t, typename p3t, typename p4t, typename p5t> | 656 | template<typename ret, typename p1t, typename p2t, typename p3t, typename p4t, typename p5t> |
583 | Signal5<ret, p1t, p2t, p3t, p4t, p5t> slot( ret (*pFnc)( p1t, p2t, p3t, p4t, p5t ) ) | 657 | Signal5<ret, p1t, p2t, p3t, p4t, p5t> slot( ret (*pFnc)( p1t, p2t, p3t, p4t, p5t ) ) |
584 | { | 658 | { |
659 | if( !pFnc ) throw SignalException("NULL pointer in slot()."); | ||
585 | return Signal5<ret, p1t, p2t, p3t, p4t, p5t>( | 660 | return Signal5<ret, p1t, p2t, p3t, p4t, p5t>( |
586 | new __Slot5F<ret, p1t, p2t, p3t, p4t, p5t>( pFnc ) | 661 | new __Slot5F<ret, p1t, p2t, p3t, p4t, p5t>( pFnc ) |
587 | ); | 662 | ); |