|
Rapicorn - Experimental UI Toolkit - Source Code 10.08.1
|
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__ */
1.7.4