00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 #if !defined(_XRB_SIGNALHANDLER_HPP_)
00012 #define _XRB_SIGNALHANDLER_HPP_
00013
00014 #include "xrb.hpp"
00015
00016 #include <algorithm>
00017 #include <list>
00018
00025 namespace Xrb
00026 {
00027
00028 class SignalHandler;
00029
00030 class SignalSenderBase;
00031 template <typename ReceiverAnalog, typename TransformationSet> class SignalSender;
00032 class SignalSender0;
00033 template <typename T> class SignalSender1;
00034 template <typename T, typename U> class SignalSender2;
00035
00036 class SignalReceiverBase;
00037 template <typename SenderAnalog> class SignalReceiver;
00038 class SignalReceiver0;
00039 template <typename T> class SignalReceiver1;
00040 template <typename T, typename U> class SignalReceiver2;
00041
00059 class SignalSenderBase
00060 {
00061 public:
00062
00065 virtual ~SignalSenderBase () { }
00066
00070 inline bool IsBlocking () const
00071 {
00072 return m_is_blocking;
00073 }
00079 inline SignalHandler *Owner () const
00080 {
00081 return m_owner;
00082 }
00083
00090 inline void SetIsBlocking (bool is_blocking)
00091 {
00092 m_is_blocking = is_blocking;
00093 }
00094
00098 virtual void DetachAll () const = 0;
00099
00100 protected:
00101
00110 SignalSenderBase (SignalHandler *owner);
00111
00112 private:
00113
00115 bool m_is_blocking;
00117 SignalHandler *m_owner;
00118 };
00119
00120 template <typename ReceiverAnalog, typename TransformationSet>
00121 struct Attachment
00122 {
00123 ReceiverAnalog *m_receiver;
00124 TransformationSet m_transformation_set;
00125
00126 inline Attachment (
00127 ReceiverAnalog *receiver,
00128 TransformationSet transformation_set)
00129 :
00130 m_receiver(receiver),
00131 m_transformation_set(transformation_set)
00132 { }
00133 inline Attachment (Attachment const &attachment)
00134 :
00135 m_receiver(attachment.m_receiver),
00136 m_transformation_set(attachment.m_transformation_set)
00137 { }
00138
00139 inline bool operator == (ReceiverAnalog const *receiver) const
00140 {
00141 return m_receiver == receiver;
00142 }
00143 };
00144
00145 template <typename ReceiverAnalog, typename TransformationSet>
00146 class SignalSender : public SignalSenderBase
00147 {
00148 public:
00149
00150 virtual ~SignalSender ()
00151 {
00152
00153 SignalSender<ReceiverAnalog, TransformationSet>::DetachAll();
00154 }
00155
00156 inline Attachment<ReceiverAnalog, TransformationSet> const &IteratorAttachment () const
00157 {
00158 ASSERT1(m_iterator != m_iterator_end);
00159 return *m_iterator;
00160 }
00161 inline bool IsIteratorAttachmentValid () const
00162 {
00163 return m_iterator != m_iterator_end;
00164 }
00165 inline void FetchFirstIteratorAttachment () const
00166 {
00167 m_iterator = m_attachment_list.begin();
00168 m_iterator_end = m_attachment_list.end();
00169 }
00170 inline void FetchNextIteratorAttachment () const
00171 {
00172 ASSERT1(m_iterator != m_iterator_end);
00173 ++m_iterator;
00174 }
00175
00176 inline void Detach (ReceiverAnalog const *receiver) const
00177 {
00178 DetachPrivate(receiver, true);
00179 }
00180
00181 virtual void DetachAll () const
00182 {
00183 for (typename AttachmentList::iterator
00184 it = m_attachment_list.begin(),
00185 it_end = m_attachment_list.end();
00186 it != it_end;
00187 ++it)
00188 {
00189 ASSERT1(it->m_receiver != NULL);
00190 it->m_receiver->DetachPrivate(this, false);
00191 }
00192 m_attachment_list.clear();
00193 }
00194
00195 protected:
00196
00197 SignalSender (SignalHandler *owner)
00198 :
00199 SignalSenderBase(owner)
00200 { }
00201
00202 private:
00203
00204 inline void Attach (
00205 TransformationSet transformation_set,
00206 ReceiverAnalog const *receiver) const
00207 {
00208 AttachPrivate(transformation_set, receiver, true);
00209 }
00210
00211 template <typename SenderAnalog>
00212 void AttachPrivate (
00213 TransformationSet transformation_set,
00214 SignalReceiver<SenderAnalog> const *receiver,
00215 bool reciprocate) const
00216 {
00217 ASSERT1(receiver != NULL);
00218
00219
00220 ReceiverAnalog const *real_receiver =
00221 static_cast<ReceiverAnalog const *>(receiver);
00222
00223 typename AttachmentList::iterator it =
00224 std::find(
00225 m_attachment_list.begin(),
00226 m_attachment_list.end(),
00227 real_receiver);
00228 ASSERT1(it == m_attachment_list.end() && "receiver is already attached");
00229
00230
00231 m_attachment_list.push_back(
00232 Attachment<ReceiverAnalog, TransformationSet>(
00233 const_cast<ReceiverAnalog *>(real_receiver),
00234 transformation_set));
00235
00236 if (reciprocate)
00237 receiver->AttachPrivate(this);
00238 }
00239
00240 template <typename SenderAnalog>
00241 void DetachPrivate (
00242 SignalReceiver<SenderAnalog> const *receiver,
00243 bool reciprocate) const
00244 {
00245 ASSERT1(receiver != NULL);
00246
00247
00248 ReceiverAnalog const *real_receiver =
00249 static_cast<ReceiverAnalog const *>(receiver);
00250
00251 typename AttachmentList::iterator it =
00252 std::find(
00253 m_attachment_list.begin(),
00254 m_attachment_list.end(),
00255 real_receiver);
00256 ASSERT1(it != m_attachment_list.end() && "non-existent receiver");
00257
00258 m_attachment_list.erase(it);
00259
00260 if (reciprocate)
00261 receiver->DetachPrivate(this, false);
00262 }
00263
00264 typedef std::list<Attachment<ReceiverAnalog, TransformationSet> > AttachmentList;
00265
00266 mutable typename AttachmentList::iterator m_iterator;
00267 mutable typename AttachmentList::iterator m_iterator_end;
00268 mutable AttachmentList m_attachment_list;
00269
00270 template <typename SenderAnalog> friend class SignalReceiver;
00271 friend class SignalHandler;
00272 };
00273
00274 struct TransformationSet0
00275 {
00276 };
00277
00278 class SignalSender0 : public SignalSender<SignalReceiver0, TransformationSet0>
00279 {
00280 public:
00281
00282 SignalSender0 (SignalHandler *owner)
00283 :
00284 SignalSender<SignalReceiver0, TransformationSet0>(owner)
00285 { }
00286 virtual ~SignalSender0 () { }
00287
00297 void Signal ();
00298 };
00299
00300 template <typename T>
00301 struct TransformationSet1
00302 {
00303 typedef T (*TransformationFunction)(T);
00304
00305 TransformationFunction m_transformation_function;
00306
00307 inline TransformationSet1 (TransformationFunction transformation_function)
00308 :
00309 m_transformation_function(transformation_function)
00310 { }
00311 };
00312
00313 template <typename T>
00314 class SignalSender1 : public SignalSender<SignalReceiver1<T>, TransformationSet1<T> >
00315 {
00316 public:
00317
00318 SignalSender1 (SignalHandler *owner)
00319 :
00320 SignalSender<SignalReceiver1<T>, TransformationSet1<T> >(owner)
00321 { }
00322 virtual ~SignalSender1 () { }
00323
00333 void Signal (T param)
00334 {
00335
00336
00337
00338 if (this->Owner()->IsBlockingSenders() || this->IsBlocking())
00339 return;
00340
00341
00342
00343 this->FetchFirstIteratorAttachment();
00344 while (this->IsIteratorAttachmentValid())
00345 {
00346 Attachment<SignalReceiver1<T>, TransformationSet1<T> > const &attachment =
00347 this->IteratorAttachment();
00348
00349 ASSERT1(attachment.m_receiver != NULL);
00350
00351
00352
00353
00354 if (!this->Owner()->IsBlockingSenders() && !this->IsBlocking())
00355 {
00356
00357
00358 if (!attachment.m_receiver->Owner()->IsBlockingReceivers() &&
00359 !attachment.m_receiver->IsBlocking())
00360 {
00361 (attachment.m_receiver->Owner()->*attachment.m_receiver->m_callback)(
00362 (attachment.m_transformation_set.m_transformation_function != NULL) ?
00363 attachment.m_transformation_set.m_transformation_function(param) :
00364 param);
00365 }
00366 }
00367
00368 else
00369 return;
00370
00371 this->FetchNextIteratorAttachment();
00372 }
00373 }
00374 };
00375
00376 template <typename T, typename U>
00377 struct TransformationSet2
00378 {
00379 typedef T (*TransformationFunction1)(T);
00380 typedef U (*TransformationFunction2)(U);
00381
00382 TransformationFunction1 m_transformation_function_1;
00383 TransformationFunction2 m_transformation_function_2;
00384
00385 inline TransformationSet2 (
00386 TransformationFunction1 transformation_function_1,
00387 TransformationFunction2 transformation_function_2)
00388 :
00389 m_transformation_function_1(transformation_function_1),
00390 m_transformation_function_2(transformation_function_2)
00391 { }
00392 };
00393
00394 template <typename T, typename U>
00395 class SignalSender2 : public SignalSender<SignalReceiver2<T, U>, TransformationSet2<T, U> >
00396 {
00397 public:
00398
00399 SignalSender2 (SignalHandler *owner)
00400 :
00401 SignalSender<SignalReceiver2<T, U>, TransformationSet2<T, U> >(owner)
00402 { }
00403 virtual ~SignalSender2 () { }
00404
00414 void Signal (T param_1, U param_2)
00415 {
00416
00417
00418
00419 if (this->Owner()->IsBlockingSenders() || this->IsBlocking())
00420 return;
00421
00422
00423
00424 this->FetchFirstIteratorAttachment();
00425 while (this->IsIteratorAttachmentValid())
00426 {
00427 Attachment<SignalReceiver2<T, U>, TransformationSet2<T, U> > const &attachment =
00428 this->IteratorAttachment();
00429
00430 ASSERT1(attachment.m_receiver != NULL);
00431
00432
00433
00434
00435 if (!this->Owner()->IsBlockingSenders() && !this->IsBlocking())
00436 {
00437
00438
00439 if (!attachment.m_receiver->Owner()->IsBlockingReceivers() &&
00440 !attachment.m_receiver->IsBlocking())
00441 {
00442 (attachment.m_receiver->Owner()->*attachment.m_receiver->m_callback)(
00443 (attachment.m_transformation_set.m_transformation_function_1 != NULL) ?
00444 attachment.m_transformation_set.m_transformation_function_1(param_1) :
00445 param_1,
00446 (attachment.m_transformation_set.m_transformation_function_2 != NULL) ?
00447 attachment.m_transformation_set.m_transformation_function_2(param_2) :
00448 param_2
00449 );
00450 }
00451 }
00452
00453 else
00454 return;
00455
00456 this->FetchNextIteratorAttachment();
00457 }
00458 }
00459 };
00460
00461
00462
00463
00464
00482 class SignalReceiverBase
00483 {
00484 public:
00485
00488 virtual ~SignalReceiverBase () { }
00489
00494 inline bool IsBlocking () const
00495 {
00496 return m_is_blocking;
00497 }
00503 inline SignalHandler *Owner () const
00504 {
00505 return m_owner;
00506 }
00507
00514 inline void SetIsBlocking (bool is_blocking)
00515 {
00516 m_is_blocking = is_blocking;
00517 }
00518
00522 virtual void DetachAll () const = 0;
00523
00524 protected:
00525
00534 SignalReceiverBase (SignalHandler *owner);
00535
00536 private:
00537
00539 bool m_is_blocking;
00541 SignalHandler *m_owner;
00542 };
00543
00544 template <typename SenderAnalog>
00545 class SignalReceiver : public SignalReceiverBase
00546 {
00547 public:
00548
00549 virtual ~SignalReceiver ()
00550 {
00551
00552 SignalReceiver<SenderAnalog>::DetachAll();
00553 }
00554
00555 inline void Detach (SenderAnalog const *sender) const
00556 {
00557 DetachPrivate(sender, true);
00558 }
00559
00560 virtual void DetachAll () const
00561 {
00562 for (typename AttachmentList::iterator
00563 it = m_attachment_list.begin(),
00564 it_end = m_attachment_list.end();
00565 it != it_end;
00566 ++it)
00567 {
00568 SenderAnalog const *sender = *it;
00569 ASSERT1(sender != NULL);
00570 sender->DetachPrivate(this, false);
00571 }
00572 m_attachment_list.clear();
00573 }
00574
00575 protected:
00576
00577 SignalReceiver (SignalHandler *owner)
00578 :
00579 SignalReceiverBase(owner)
00580 { }
00581
00582 private:
00583
00584 template <typename ReceiverAnalog, typename TransformationSet>
00585 void AttachPrivate (
00586 SignalSender<ReceiverAnalog, TransformationSet> const *sender) const
00587 {
00588 ASSERT1(sender != NULL);
00589
00590
00591 SenderAnalog const *real_sender =
00592 static_cast<SenderAnalog const *>(sender);
00593
00594 typename AttachmentList::iterator it =
00595 std::find(
00596 m_attachment_list.begin(),
00597 m_attachment_list.end(),
00598 real_sender);
00599 ASSERT1(it == m_attachment_list.end() && "sender is already attached");
00600
00601 m_attachment_list.push_back(real_sender);
00602 }
00603
00604 template <typename ReceiverAnalog, typename TransformationSet>
00605 void DetachPrivate (
00606 SignalSender<ReceiverAnalog, TransformationSet> const *sender,
00607 bool reciprocate) const
00608 {
00609 ASSERT1(sender != NULL);
00610
00611
00612 SenderAnalog const *real_sender =
00613 static_cast<SenderAnalog const *>(sender);
00614
00615 typename AttachmentList::iterator it =
00616 std::find(
00617 m_attachment_list.begin(),
00618 m_attachment_list.end(),
00619 real_sender);
00620 ASSERT1(it != m_attachment_list.end() && "non-existent sender");
00621
00622 m_attachment_list.erase(it);
00623
00624 if (reciprocate)
00625 sender->DetachPrivate(this, false);
00626 }
00627
00628 typedef std::list<SenderAnalog const *> AttachmentList;
00629
00630 mutable AttachmentList m_attachment_list;
00631
00632 template <typename ReceiverAnalog, typename TransformationSet> friend class SignalSender;
00633 };
00634
00635 class SignalReceiver0 : public SignalReceiver<SignalSender0>
00636 {
00637 public:
00638
00639 typedef void (SignalHandler::*CallbackType)();
00640
00641 template <typename SignalHandlerSubclass>
00642 SignalReceiver0 (
00643 void (SignalHandlerSubclass::*callback)(),
00644 SignalHandler *owner)
00645 :
00646 SignalReceiver<SignalSender0>(owner)
00647 {
00648 ASSERT1(callback != NULL);
00649 m_callback = static_cast<CallbackType>(callback);
00650 }
00651
00652 private:
00653
00654 CallbackType m_callback;
00655
00657 friend class SignalSender0;
00658 };
00659
00660 template <typename T>
00661 class SignalReceiver1 : public SignalReceiver<SignalSender1<T> >
00662 {
00663 public:
00664
00665 typedef void (SignalHandler::*CallbackType)(T);
00666
00667 template <typename SignalHandlerSubclass>
00668 SignalReceiver1 (
00669 void (SignalHandlerSubclass::*callback)(T),
00670 SignalHandler *owner)
00671 :
00672 SignalReceiver<SignalSender1<T> >(owner)
00673 {
00674 ASSERT1(callback != NULL);
00675 m_callback = static_cast<CallbackType>(callback);
00676 }
00677
00678 private:
00679
00680 CallbackType m_callback;
00681
00683 friend class SignalSender1<T>;
00684 };
00685
00686 template <typename T, typename U>
00687 class SignalReceiver2 : public SignalReceiver<SignalSender2<T, U> >
00688 {
00689 public:
00690
00691 typedef void (SignalHandler::*CallbackType)(T, U);
00692
00693 template <typename SignalHandlerSubclass>
00694 SignalReceiver2 (
00695 void (SignalHandlerSubclass::*callback)(T, U),
00696 SignalHandler *owner)
00697 :
00698 SignalReceiver<SignalSender2<T, U> >(owner)
00699 {
00700 ASSERT1(callback != NULL);
00701 m_callback = static_cast<CallbackType>(callback);
00702 }
00703
00704 private:
00705
00706 CallbackType m_callback;
00707
00709 friend class SignalSender2<T, U>;
00710 };
00711
00731 class SignalHandler
00732 {
00733 public:
00734
00736 SignalHandler ();
00743 virtual ~SignalHandler ();
00744
00750 bool IsBlockingSenders () const
00751 {
00752 return m_is_blocking_senders;
00753 }
00759 bool IsBlockingReceivers () const
00760 {
00761 return m_is_blocking_receivers;
00762 }
00763
00768 void SetIsBlockingSenders (bool const is_blocking_senders)
00769 {
00770 m_is_blocking_senders = is_blocking_senders;
00771 }
00776 void SetIsBlockingReceivers (bool const is_blocking_receivers)
00777 {
00778 m_is_blocking_receivers = is_blocking_receivers;
00779 }
00780
00784 void DetachAll ();
00785
00791 static inline void Connect0 (
00792 SignalSender0 const *sender,
00793 SignalReceiver0 const *receiver)
00794 {
00795 ASSERT1(sender != NULL);
00796 ASSERT1(receiver != NULL);
00797 sender->Attach(TransformationSet0(), receiver);
00798 }
00799
00805 template <typename T>
00806 static inline void Connect1 (
00807 SignalSender1<T> const *sender,
00808 SignalReceiver1<T> const *receiver)
00809 {
00810 ASSERT1(sender != NULL);
00811 ASSERT1(receiver != NULL);
00812 sender->Attach(TransformationSet1<T>(NULL), receiver);
00813 }
00823 template <typename T>
00824 static inline void Connect1 (
00825 SignalSender1<T> const *sender,
00826 T (*transformation_function)(T),
00827 SignalReceiver1<T> const *receiver)
00828 {
00829 ASSERT1(sender != NULL);
00830 ASSERT1(receiver != NULL);
00831 sender->Attach(TransformationSet1<T>(transformation_function), receiver);
00832 }
00833
00839 template <typename T, typename U>
00840 static inline void Connect2 (
00841 SignalSender2<T, U> const *sender,
00842 SignalReceiver2<T, U> const *receiver)
00843 {
00844 ASSERT1(sender != NULL);
00845 ASSERT1(receiver != NULL);
00846 sender->Attach(
00847 TransformationSet2<T, U>(NULL, NULL),
00848 receiver);
00849 }
00863 template <typename T, typename U>
00864 static inline void Connect2 (
00865 SignalSender2<T, U> const *sender,
00866 T (*transformation_function_1)(T),
00867 U (*transformation_function_2)(U),
00868 SignalReceiver2<T, U> const *receiver)
00869 {
00870 ASSERT1(sender != NULL);
00871 ASSERT1(receiver != NULL);
00872 sender->Attach(
00873 TransformationSet2<T, U>(transformation_function_1, transformation_function_2),
00874 receiver);
00875 }
00876
00877 private:
00878
00885 void AddSender (SignalSenderBase const *sender);
00893 void AddReceiver (SignalReceiverBase const *receiver);
00894
00899 typedef std::list<SignalSenderBase const *> SignalSenderList;
00900
00905 typedef std::list<SignalReceiverBase const *> SignalReceiverList;
00906
00910 bool m_is_blocking_senders;
00914 bool m_is_blocking_receivers;
00916 SignalSenderList m_sender_list;
00918 SignalReceiverList m_receiver_list;
00919
00921 friend class SignalSenderBase;
00923 friend class SignalReceiverBase;
00924 };
00925
00926 }
00927
00928 #endif // !defined(_XRB_SIGNALHANDLER_HPP_)
00929