Rapicorn - Experimental UI Toolkit - Source Code 10.08.1
rapicornsignal.hh
Go to the documentation of this file.
00001 /* RapicornSignal
00002  * Copyright (C) 2005-2006 Tim Janik
00003  *
00004  * This library is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU Lesser General Public
00006  * License as published by the Free Software Foundation; either
00007  * version 2.1 of the License, or (at your option) any later version.
00008  *
00009  * This library is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012  * Lesser General Public License for more details.
00013  *
00014  * A copy of the GNU Lesser General Public License should ship along
00015  * with this library; if not, see http://www.gnu.org/copyleft/.
00016  */
00017 #ifndef __RAPICORN_SIGNAL_HH__
00018 #define __RAPICORN_SIGNAL_HH__
00019 
00020 #include <rcore/utilities.hh>
00021 
00022 namespace Rapicorn {
00023 namespace Signals {
00024 
00025 /* --- EmissionBase --- */
00026 struct EmissionBase : protected NonCopyable 
00027 {
00028   bool restart_emission;
00029   bool stop_emission;
00030   EmissionBase() :
00031     restart_emission (true),
00032     stop_emission (false)
00033   {}
00034 };
00035 
00036 /* --- TrampolineLink --- */
00037 typedef ptrdiff_t ConId;
00039 class TrampolineLink : public ReferenceCountable, protected NonCopyable {
00040   friend    class SignalBase;
00041   TrampolineLink *next, *prev;
00042   uint            m_callable : 1;
00043   uint            m_with_emitter : 1;
00044   uint            m_linking_owner : 1;
00045   inline void     with_emitter  (bool b) { m_with_emitter = b; }
00046 protected:
00047   inline void     callable      (bool b) { m_callable = b; }
00048   inline ConId    con_id        () const { return (ptrdiff_t) this; }
00049 public:
00050   void            owner_ref     ();
00051   inline bool     callable      () { return m_callable; }
00052   inline bool     with_emitter  () { return m_with_emitter; }
00053   virtual bool    operator==    (const TrampolineLink &other) const = 0;
00054   virtual        ~TrampolineLink();
00055   void            unlink        ();
00056   TrampolineLink (uint allow_stack_magic = 0) :
00057     ReferenceCountable (allow_stack_magic),
00058     next (NULL), prev (NULL), m_callable (true), m_with_emitter (false), m_linking_owner (false)
00059   {}
00060 };
00061 
00062 /* --- SignalBase --- */
00063 class SignalBase : protected NonCopyable 
00064 {
00065   friend             class SignalProxyBase;
00066   class EmbeddedLink : public TrampolineLink 
00067   {
00068     virtual bool           operator==            (const TrampolineLink &other) const;
00069     virtual void           delete_this           (); // NOP for embedded link
00070   public:
00071     explicit               EmbeddedLink          () : TrampolineLink (0xbadbad) {}
00072     void                   check_last_ref        () const { RAPICORN_ASSERT (ref_count() == 1); }
00073   };
00074   EmbeddedLink             start;
00075 protected:
00076   template<class Emission> struct Iterator;
00077   inline TrampolineLink*   start_link            () { return &start; }
00078   ConId                    connect_link          (TrampolineLink       *link,
00079                                                   bool                  with_emitter = false);
00080   uint                     disconnect_equal_link (const TrampolineLink &link,
00081                                                   bool                  with_emitter = false);
00082   uint                     disconnect_link_id    (ConId                 id);
00083   virtual void             connections_changed   (bool                  hasconnections) {}
00084 public:
00085   virtual                 ~SignalBase            ();
00086   inline                   SignalBase            () { start.next = start.prev = &start; start.ref_sink(); }
00088   inline bool              has_connections       () { return start.next != &start; }
00089 };
00090 
00091 // === SignalProxyBase ===
00092 class SignalProxyBase 
00093 {
00094   SignalBase   *m_signal;
00095 protected:
00096   ConId         connect_link          (TrampolineLink *link, bool with_emitter = false);
00097   uint          disconnect_equal_link (const TrampolineLink &link, bool with_emitter = false);
00098   uint          disconnect_link_id    (ConId                 id);
00099   SignalProxyBase&    operator=       (const SignalProxyBase &other);
00100   explicit      SignalProxyBase       (const SignalProxyBase &other);
00101   explicit      SignalProxyBase       (SignalBase &signal);
00102   virtual      ~SignalProxyBase       () {}
00103 public:
00105   void          divorce               ();
00106 };
00107 
00108 /* --- Signal Iterator --- */
00109 template<class Emission>
00110 class SignalBase::Iterator : protected NonCopyable 
00111 {
00112   Iterator& operator= (const Iterator&);
00113 public:
00114   Emission &emission;
00115   TrampolineLink *current, *start;
00116   Iterator (Emission       &_emission,
00117             TrampolineLink *last) :
00118     emission (_emission),
00119     current (ref (last)),
00120     start (ref (last))
00121   {}
00122   Iterator (const Iterator &dup) :
00123     emission (dup.emission),
00124     current (ref (dup.current)),
00125     start (ref (dup.start))
00126   {}
00127   ~Iterator()
00128   {
00129     current->unref();
00130     current = NULL;
00131     start->unref();
00132     start = NULL;
00133   }
00134   Iterator& operator++ ()
00135   {
00136     if (emission.restart_emission)
00137       {
00138         current->unref();
00139         current = start->next;
00140         current->ref();
00141         emission.restart_emission = false;
00142       }
00143     else
00144       do
00145         {
00146           TrampolineLink *next = current->next;
00147           next->ref();
00148           current->unref();
00149           current = next;
00150         }
00151       while (!current->callable() && current != start);
00152     if (emission.stop_emission)
00153       {
00154         current->unref();
00155         current = start;
00156         current->ref();
00157       }
00158     return *this;
00159   }
00160   void operator++ (int)
00161   {
00162     /* not supporting iterator copies for post-increment */
00163     operator++();
00164   }
00165   bool operator!= (const Iterator &b) const
00166   {
00167     return current != b.current || &emission != &b.emission;
00168   }
00169   bool operator== (const Iterator &b) const
00170   {
00171     return !operator!= (b);
00172   }
00173 };
00174 
00175 // === Collectors ===
00176 template<typename Result>
00177 struct CollectorVector : protected NonCopyable 
00178 {
00179   typedef std::vector<Result> result_type;
00180   template<typename InputIterator>
00181   result_type operator() (InputIterator begin, InputIterator end)
00182   {
00183     result_type result = result_type();
00184     while (begin != end)
00185       {
00186         result.push_back (*begin);
00187         ++begin;
00188       }
00189     return result;
00190   }
00191 };
00192 template<typename Result>
00193 struct CollectorLast : protected NonCopyable 
00194 {
00195   typedef Result result_type;
00196   template<typename InputIterator>
00197   Result operator() (InputIterator begin, InputIterator end)
00198   {
00199     Result result = Result();
00200     while (begin != end)
00201       {
00202         result = *begin;
00203         ++begin;
00204       }
00205     return result;
00206   }
00207 };
00208 template<typename Result>
00209 struct CollectorDefault : CollectorLast<Result> 
00210 {};
00211 template<>
00212 struct CollectorDefault<void> : protected NonCopyable 
00213 {
00214   typedef void result_type;
00215   template<typename InputIterator>
00216   void operator() (InputIterator begin, InputIterator end)
00217   {
00218     while (begin != end)
00219       {
00220         *begin;
00221         ++begin;
00222       }
00223   }
00224 };
00225 template<typename Result>
00226 struct CollectorSum : protected NonCopyable 
00227 {
00228   typedef Result result_type;
00229   template<typename InputIterator>
00230   Result operator() (InputIterator begin, InputIterator end)
00231   {
00232     Result result = Result();
00233     while (begin != end)
00234       {
00235         result += *begin;
00236         ++begin;
00237       }
00238     return result;
00239   }
00240 };
00241 template<typename Result>
00242 struct CollectorWhile0 : protected NonCopyable 
00243 {
00244   typedef Result result_type;
00245   template<typename InputIterator>
00246   Result operator() (InputIterator begin, InputIterator end)
00247   {
00248     Result result = Result();   // result = 0
00249     while (begin != end)
00250       {
00251         result = *begin;
00252         if (result)             // result != 0
00253           break;
00254         ++begin;
00255       }
00256     return result;
00257   }
00258 };
00259 template<typename Result>
00260 struct CollectorUntil0 : protected NonCopyable 
00261 {
00262   typedef Result result_type;
00263   template<typename InputIterator>
00264   Result operator() (InputIterator begin, InputIterator end)
00265   {
00266     Result result = !Result();  // result = !0
00267     while (begin != end)
00268       {
00269         result = *begin;
00270         if (!result)            // result == 0
00271           break;
00272         ++begin;
00273       }
00274     return result;
00275   }
00276 };
00277 
00278 // === ScopeReference ===
00279 template<class Instance, typename Mark>
00280 class ScopeReference : protected NonCopyable 
00281 {
00282   Instance &m_instance;
00283 public:
00284   ScopeReference  (Instance &instance) : m_instance (instance) { ref (m_instance); }
00285   ~ScopeReference ()                                           { unref (m_instance); }
00286 };
00287 struct ScopeReferenceFinalizationMark : CollectorDefault<void> 
00288 {};
00289 template<class Instance>                
00290 class ScopeReference<Instance, ScopeReferenceFinalizationMark> : protected NonCopyable {
00291   Instance &m_instance;
00292 public:
00293   ScopeReference  (Instance &instance) : m_instance (instance) { RAPICORN_ASSERT (m_instance.finalizing() == true); }
00294   ~ScopeReference ()                                           { RAPICORN_ASSERT (m_instance.finalizing() == true); }
00295 };
00296 
00297 // === SignalConnectionRelay ===
00298 template <class Listener>
00299 class SignalConnectionRelay : public Signals::SignalBase 
00300 {
00301   Listener        *m_listener;
00302   void (Listener::*m_notify) (bool hasconnections);
00303   virtual void     connections_changed (bool hasconnections) { if (m_listener) (m_listener->*m_notify) (hasconnections); }
00304 public:
00307   void             listener (Listener &object, void (Listener::*method) (bool)) { m_listener = &object; m_notify = method; }
00308 };
00309 
00310 /* --- SlotBase --- */
00311 class SlotBase : protected NonCopyable 
00312 {
00313 protected:
00314   TrampolineLink *m_link;
00315   void
00316   set_trampoline (TrampolineLink *cl)
00317   {
00318     if (cl)
00319       cl->ref_sink();
00320     if (m_link)
00321       m_link->unref();
00322     m_link = cl;
00323   }
00324   ~SlotBase()
00325   { set_trampoline (NULL); }
00326 public:
00327   SlotBase (TrampolineLink *link) :
00328     m_link (NULL)
00329   { set_trampoline (link); }
00330   SlotBase (const SlotBase &src) :
00331     m_link (NULL)
00332   { *this = src; }
00333   SlotBase&
00334   operator= (const SlotBase &src)
00335   {
00336     set_trampoline (src.m_link);
00337     return *this;
00338   }
00339   TrampolineLink*
00340   get_trampoline_link() const
00341   { return m_link; }
00342 };
00343 
00344 // === Signatures ===
00346 template<typename>                      struct Signature {};
00348 template<typename R0>                   struct Signature<R0 ()>   { typedef R0 result_type; };
00349 template<typename R0, typename A1>      struct Signature<R0 (A1)> { typedef A1 argument1_type;  typedef R0 result_type; };
00350 template<typename R0, typename A1, typename A2>
00351 struct Signature<R0 (A1, A2)> {
00352   typedef A1 argument1_type;    typedef A2 argument2_type;      typedef R0 result_type;
00353 };
00354 template<typename R0, typename A1, typename A2, typename A3>
00355 struct Signature<R0 (A1, A2, A3)> {
00356   typedef A1 argument1_type;    typedef A2 argument2_type;      typedef A3 argument3_type;      typedef R0 result_type;
00357 };
00358 template<typename R0, typename A1, typename A2, typename A3, typename A4>
00359 struct Signature<R0 (A1, A2, A3, A4)> {
00360   typedef A1 argument1_type;    typedef A2 argument2_type;      typedef A3 argument3_type;      typedef A4 argument4_type;
00361   typedef R0 result_type;
00362 };
00363 template<typename R0, typename A1, typename A2, typename A3, typename A4, typename A5>
00364 struct Signature<R0 (A1, A2, A3, A4, A5)> {
00365   typedef A1 argument1_type;    typedef A2 argument2_type;      typedef A3 argument3_type;      typedef A4 argument4_type;
00366   typedef A5 argument5_type;    typedef R0 result_type;
00367 };
00368 template<typename R0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6>
00369 struct Signature<R0 (A1, A2, A3, A4, A5, A6)> {
00370   typedef A1 argument1_type;    typedef A2 argument2_type;      typedef A3 argument3_type;      typedef A4 argument4_type;
00371   typedef A5 argument5_type;    typedef A6 argument6_type;      typedef R0 result_type;
00372 };
00373 template<typename R0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7>
00374 struct Signature<R0 (A1, A2, A3, A4, A5, A6, A7)> {
00375   typedef A1 argument1_type;    typedef A2 argument2_type;      typedef A3 argument3_type;      typedef A4 argument4_type;
00376   typedef A5 argument5_type;    typedef A6 argument6_type;      typedef A7 argument7_type;      typedef R0 result_type;
00377 };
00378 template<typename R0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8>
00379 struct Signature<R0 (A1, A2, A3, A4, A5, A6, A7, A8)> {
00380   typedef A1 argument1_type;    typedef A2 argument2_type;      typedef A3 argument3_type;      typedef A4 argument4_type;
00381   typedef A5 argument5_type;    typedef A6 argument6_type;      typedef A7 argument7_type;      typedef A8 argument8_type;
00382   typedef R0 result_type;
00383 };
00384 template<typename R0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8,
00385          typename A9>
00386 struct Signature<R0 (A1, A2, A3, A4, A5, A6, A7, A8, A9)> {
00387   typedef A1 argument1_type;    typedef A2 argument2_type;      typedef A3 argument3_type;      typedef A4 argument4_type;
00388   typedef A5 argument5_type;    typedef A6 argument6_type;      typedef A7 argument7_type;      typedef A8 argument8_type;
00389   typedef A9 argument9_type;    typedef R0 result_type;
00390 };
00391 template<typename R0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8,
00392          typename A9, typename A10>
00393 struct Signature<R0 (A1, A2, A3, A4, A5, A6, A7, A8, A9, A10)> {
00394   typedef A1 argument1_type;    typedef A2 argument2_type;      typedef A3 argument3_type;      typedef A4 argument4_type;
00395   typedef A5 argument5_type;    typedef A6 argument6_type;      typedef A7 argument7_type;      typedef A8 argument8_type;
00396   typedef A9 argument9_type;    typedef A10 argument10_type;    typedef R0 result_type;
00397 };
00398 template<typename R0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8,
00399          typename A9, typename A10, typename A11>
00400 struct Signature<R0 (A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11)> {
00401   typedef A1 argument1_type;    typedef A2 argument2_type;      typedef A3 argument3_type;      typedef A4 argument4_type;
00402   typedef A5 argument5_type;    typedef A6 argument6_type;      typedef A7 argument7_type;      typedef A8 argument8_type;
00403   typedef A9 argument9_type;    typedef A10 argument10_type;    typedef A11 argument11_type;    typedef R0 result_type;
00404 };
00405 template<typename R0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8,
00406          typename A9, typename A10, typename A11, typename A12>
00407 struct Signature<R0 (A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12)> {
00408   typedef A1 argument1_type;    typedef A2 argument2_type;      typedef A3 argument3_type;      typedef A4 argument4_type;
00409   typedef A5 argument5_type;    typedef A6 argument6_type;      typedef A7 argument7_type;      typedef A8 argument8_type;
00410   typedef A9 argument9_type;    typedef A10 argument10_type;    typedef A11 argument11_type;    typedef A12 argument12_type;
00411   typedef R0 result_type;
00412 };
00413 template<typename R0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8,
00414          typename A9, typename A10, typename A11, typename A12, typename A13>
00415 struct Signature<R0 (A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13)> {
00416   typedef A1 argument1_type;    typedef A2 argument2_type;      typedef A3 argument3_type;      typedef A4 argument4_type;
00417   typedef A5 argument5_type;    typedef A6 argument6_type;      typedef A7 argument7_type;      typedef A8 argument8_type;
00418   typedef A9 argument9_type;    typedef A10 argument10_type;    typedef A11 argument11_type;    typedef A12 argument12_type;
00419   typedef A13 argument13_type;  typedef R0 result_type;
00420 };
00421 template<typename R0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8,
00422          typename A9, typename A10, typename A11, typename A12, typename A13, typename A14>
00423 struct Signature<R0 (A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14)> {
00424   typedef A1 argument1_type;    typedef A2 argument2_type;      typedef A3 argument3_type;      typedef A4 argument4_type;
00425   typedef A5 argument5_type;    typedef A6 argument6_type;      typedef A7 argument7_type;      typedef A8 argument8_type;
00426   typedef A9 argument9_type;    typedef A10 argument10_type;    typedef A11 argument11_type;    typedef A12 argument12_type;
00427   typedef A13 argument13_type;  typedef A14 argument14_type;    typedef R0 result_type;
00428 };
00429 template<typename R0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8,
00430          typename A9, typename A10, typename A11, typename A12, typename A13, typename A14, typename A15>
00431 struct Signature<R0 (A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15)> {
00432   typedef A1 argument1_type;    typedef A2 argument2_type;      typedef A3 argument3_type;      typedef A4 argument4_type;
00433   typedef A5 argument5_type;    typedef A6 argument6_type;      typedef A7 argument7_type;      typedef A8 argument8_type;
00434   typedef A9 argument9_type;    typedef A10 argument10_type;    typedef A11 argument11_type;    typedef A12 argument12_type;
00435   typedef A13 argument13_type;  typedef A14 argument14_type;    typedef A15 argument15_type;    typedef R0 result_type;
00436 };
00437 template<typename R0, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7, typename A8,
00438          typename A9, typename A10, typename A11, typename A12, typename A13, typename A14, typename A15, typename A16>
00439 struct Signature<R0 (A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, A16)> {
00440   typedef A1 argument1_type;    typedef A2 argument2_type;      typedef A3 argument3_type;      typedef A4 argument4_type;
00441   typedef A5 argument5_type;    typedef A6 argument6_type;      typedef A7 argument7_type;      typedef A8 argument8_type;
00442   typedef A9 argument9_type;    typedef A10 argument10_type;    typedef A11 argument11_type;    typedef A12 argument12_type;
00443   typedef A13 argument13_type;  typedef A14 argument14_type;    typedef A15 argument15_type;    typedef A16 argument16_type;
00444   typedef R0 result_type;
00445 };
00447 
00448 template <class Emitter,
00449           typename SignalSignature,
00450           class Collector = CollectorDefault<typename Signature<SignalSignature>::result_type>,
00451           class SignalAncestor = SignalBase
00452           > struct Signal;
00453 
00454 template <class Emitter,
00455           typename SignalSignature
00456           > struct SignalProxy;
00457 
00458 /* --- Casting --- */
00459 template<class TrampolineP> TrampolineP
00460 trampoline_cast (TrampolineLink *link)
00461 {
00462   if (1) // could be disabled for performance
00463     return dynamic_cast<TrampolineP> (link);
00464   else  // cheap cast
00465     return reinterpret_cast<TrampolineP> (link);
00466 }
00467 
00468 /* --- Trampoline + Slot + Signal generation --- */
00469 #include <rcore/rapicornsignalvariants.hh> // contains multiple versions of "rapicornsignaltemplate.hh"
00470 
00471 /* --- predefined slots --- */
00472 typedef Slot0<void, void> VoidSlot;
00473 typedef Slot0<bool, void> BoolSlot;
00474 
00475 /* --- predefined signals --- */
00476 template<class Emitter>
00477 class SignalFinalize : public Signal0 <Emitter, void, ScopeReferenceFinalizationMark> 
00478 {
00479   typedef Signal0 <Emitter, void, ScopeReferenceFinalizationMark> SignalVariant;
00480 public:
00481   explicit SignalFinalize (Emitter &emitter)                             : SignalVariant (emitter) {}
00482   explicit SignalFinalize (Emitter &emitter, void (Emitter::*method) ()) : SignalVariant (emitter, method) {}
00483 };
00484 
00485 template<class Emitter>
00486 class SignalVoid : public Signal0 <Emitter, void> 
00487 {
00488   typedef Signal0 <Emitter, void> SignalVariant;
00489 public:
00490   explicit SignalVoid (Emitter &emitter)                                 : SignalVariant (emitter) {}
00491   explicit SignalVoid (Emitter &emitter, void (Emitter::*method) (void)) : SignalVariant (emitter, method) {}
00492 };
00493 
00494 } // Signals
00495 
00496 /* --- Rapicorn::Signal imports --- */
00497 using Signals::SignalConnectionRelay;
00498 using Signals::CollectorDefault;
00499 using Signals::CollectorWhile0;
00500 using Signals::CollectorUntil0;
00501 using Signals::CollectorVector;
00502 using Signals::CollectorLast;
00503 using Signals::CollectorSum;
00504 using Signals::VoidSlot;
00505 using Signals::BoolSlot;
00506 using Signals::SignalProxy;
00507 using Signals::SignalFinalize;
00508 using Signals::SignalVoid;
00509 using Signals::Signal;
00510 using Signals::slot;
00511 
00512 } // Rapicorn
00513 
00514 #endif  /* __RAPICORN_SIGNAL_HH__ */
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines