delegateSignal.h 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666
  1. //-----------------------------------------------------------------------------
  2. // Copyright (c) 2013 GarageGames, LLC
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy
  5. // of this software and associated documentation files (the "Software"), to
  6. // deal in the Software without restriction, including without limitation the
  7. // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  8. // sell copies of the Software, and to permit persons to whom the Software is
  9. // furnished to do so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included in
  12. // all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  19. // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  20. // IN THE SOFTWARE.
  21. //-----------------------------------------------------------------------------
  22. #ifndef _DELEGATESIGNAL_H_
  23. #define _DELEGATESIGNAL_H_
  24. #ifndef _UTIL_DELEGATE_H_
  25. #include "delegates/delegate.h"
  26. #endif
  27. #ifndef _VECTOR_H_
  28. #include "collection/vector.h"
  29. #endif
  30. /// Signals (Multi-cast Delegates)
  31. ///
  32. /// Signals are used throughout this engine to allow subscribers to listen
  33. /// for generated events for various things.
  34. ///
  35. /// Signals are called according to their order parameter (lower
  36. /// numbers first).
  37. ///
  38. /// Signal functions can return bool or void. If bool then returning false
  39. /// from a signal function will cause entries in the ordered signal list after
  40. /// that one to not be called.
  41. ///
  42. /// This allows handlers of a given event to say to the signal generator, "I handled this message, and
  43. /// it is no longer appropriate for other listeners to handle it"
  44. class SignalBase
  45. {
  46. public:
  47. SignalBase()
  48. {
  49. mList.next = mList.prev = &mList;
  50. mList.order = 0.5f;
  51. //mTriggerNext = NULL;
  52. }
  53. ~SignalBase();
  54. /// Removes all the delegates from the signal.
  55. void removeAll();
  56. /// Returns true if the delegate list is empty.
  57. bool isEmpty() const
  58. {
  59. return mList.next == &mList;
  60. }
  61. protected:
  62. struct DelegateLink
  63. {
  64. DelegateLink *next,*prev;
  65. F32 order;
  66. void insert(DelegateLink* node, F32 order);
  67. void unlink();
  68. };
  69. DelegateLink mList;
  70. /// We need to protect the delegate list against removal of the currently
  71. /// triggering node as well removal of the next node in the list. When not
  72. /// handling these two cases correctly, removing delegates from a signal
  73. /// while it is triggering will lead to crashes.
  74. ///
  75. /// So this field stores the next node of each active traversal so that when
  76. /// we unlink a node, we can check it against this field and move the traversal
  77. /// along if needed.
  78. Vector<DelegateLink*> mTriggerNext;
  79. };
  80. template<typename Signature> class SignalBaseT : public SignalBase
  81. {
  82. public:
  83. /// The delegate signature for this signal.
  84. typedef Delegate<Signature> DelegateSig;
  85. SignalBaseT() {}
  86. SignalBaseT( const SignalBaseT &base )
  87. {
  88. mList.next = mList.prev = &mList;
  89. merge( base );
  90. }
  91. void operator =( const SignalBaseT &base )
  92. {
  93. removeAll();
  94. merge( base );
  95. }
  96. void merge( const SignalBaseT &base )
  97. {
  98. for ( DelegateLink *ptr = base.mList.next; ptr != &base.mList; ptr = ptr->next )
  99. {
  100. DelegateLinkImpl *del = static_cast<DelegateLinkImpl*>( ptr );
  101. notify( del->mDelegate, del->order );
  102. }
  103. }
  104. void notify( const DelegateSig &dlg, F32 order = 0.5f)
  105. {
  106. mList.insert(new DelegateLinkImpl(dlg), order);
  107. }
  108. void remove( DelegateSig dlg )
  109. {
  110. for( DelegateLink* ptr = mList.next;ptr != &mList; ptr = ptr->next )
  111. {
  112. if( DelegateLinkImpl* del = static_cast< DelegateLinkImpl* >( ptr ) )
  113. {
  114. if( del->mDelegate == dlg )
  115. {
  116. for ( int i = 0; i < mTriggerNext.size(); i++ )
  117. {
  118. if( mTriggerNext[i] == ptr )
  119. mTriggerNext[i] = ptr->next;
  120. }
  121. del->unlink();
  122. delete del;
  123. return;
  124. }
  125. }
  126. }
  127. }
  128. template <class T,class U>
  129. void notify(T obj,U func, F32 order = 0.5f)
  130. {
  131. DelegateSig dlg(obj, func);
  132. notify(dlg, order);
  133. }
  134. template <class T>
  135. void notify(T func, F32 order = 0.5f)
  136. {
  137. DelegateSig dlg(func);
  138. notify(dlg, order);
  139. }
  140. template <class T,class U>
  141. void remove(T obj,U func)
  142. {
  143. DelegateSig compDelegate(obj, func);
  144. remove(compDelegate);
  145. }
  146. template <class T>
  147. void remove(T func)
  148. {
  149. DelegateSig compDelegate(func);
  150. remove(compDelegate);
  151. }
  152. /// Returns true if the signal already contains this delegate.
  153. bool contains( const DelegateSig &dlg ) const
  154. {
  155. for ( DelegateLink *ptr = mList.next; ptr != &mList; ptr = ptr->next )
  156. {
  157. DelegateLinkImpl *del = static_cast<DelegateLinkImpl*>( ptr );
  158. if ( del->mDelegate == dlg )
  159. return true;
  160. }
  161. return false;
  162. }
  163. protected:
  164. struct DelegateLinkImpl : public SignalBase::DelegateLink
  165. {
  166. DelegateSig mDelegate;
  167. DelegateLinkImpl(DelegateSig dlg) : mDelegate(dlg) {}
  168. };
  169. DelegateSig & getDelegate(SignalBase::DelegateLink * link)
  170. {
  171. return ((DelegateLinkImpl*)link)->mDelegate;
  172. }
  173. };
  174. //-----------------------------------------------------------------------------
  175. template<typename Signature> class Signal;
  176. // Short-circuit signal implementations
  177. template<>
  178. class Signal<bool()> : public SignalBaseT<bool()>
  179. {
  180. public:
  181. bool trigger()
  182. {
  183. this->mTriggerNext.push_back(NULL);
  184. for( SignalBase::DelegateLink* ptr = this->mList.next; ptr != &this->mList; )
  185. {
  186. this->mTriggerNext.last() = ptr->next;
  187. if( !this->getDelegate( ptr )() )
  188. {
  189. this->mTriggerNext.pop_back();
  190. return false;
  191. }
  192. ptr = this->mTriggerNext.last();
  193. }
  194. this->mTriggerNext.pop_back();
  195. return true;
  196. }
  197. };
  198. template<class A>
  199. class Signal<bool(A)> : public SignalBaseT<bool(A)>
  200. {
  201. public:
  202. bool trigger( A a )
  203. {
  204. this->mTriggerNext.push_back(NULL);
  205. for( SignalBase::DelegateLink* ptr = this->mList.next; ptr != &this->mList; )
  206. {
  207. this->mTriggerNext.last() = ptr->next;
  208. if( !this->getDelegate( ptr )( a ) )
  209. {
  210. this->mTriggerNext.pop_back();
  211. return false;
  212. }
  213. ptr = this->mTriggerNext.last();
  214. }
  215. this->mTriggerNext.pop_back();
  216. return true;
  217. }
  218. };
  219. template<class A, class B>
  220. class Signal<bool(A,B)> : public SignalBaseT<bool(A,B)>
  221. {
  222. public:
  223. bool trigger( A a, B b )
  224. {
  225. this->mTriggerNext.push_back(NULL);
  226. for( SignalBase::DelegateLink* ptr = this->mList.next; ptr != &this->mList; )
  227. {
  228. this->mTriggerNext.last() = ptr->next;
  229. if( !this->getDelegate( ptr )( a, b ) )
  230. {
  231. this->mTriggerNext.pop_back();
  232. return false;
  233. }
  234. ptr = this->mTriggerNext.last();
  235. }
  236. this->mTriggerNext.pop_back();
  237. return true;
  238. }
  239. };
  240. template<class A, class B, class C>
  241. class Signal<bool(A,B,C)> : public SignalBaseT<bool(A,B,C)>
  242. {
  243. public:
  244. bool trigger( A a, B b, C c )
  245. {
  246. this->mTriggerNext.push_back(NULL);
  247. for( SignalBase::DelegateLink* ptr = this->mList.next; ptr != &this->mList; )
  248. {
  249. this->mTriggerNext.last() = ptr->next;
  250. if( !this->getDelegate( ptr )( a, b, c ) )
  251. {
  252. this->mTriggerNext.pop_back();
  253. return false;
  254. }
  255. ptr = this->mTriggerNext.last();
  256. }
  257. this->mTriggerNext.pop_back();
  258. return true;
  259. }
  260. };
  261. template<class A, class B, class C, class D>
  262. class Signal<bool(A,B,C,D)> : public SignalBaseT<bool(A,B,C,D)>
  263. {
  264. public:
  265. bool trigger( A a, B b, C c, D d )
  266. {
  267. this->mTriggerNext.push_back(NULL);
  268. for( SignalBase::DelegateLink* ptr = this->mList.next; ptr != &this->mList; )
  269. {
  270. this->mTriggerNext.last() = ptr->next;
  271. if( !this->getDelegate( ptr )( a, b, c, d ) )
  272. {
  273. this->mTriggerNext.pop_back();
  274. return false;
  275. }
  276. ptr = this->mTriggerNext.last();
  277. }
  278. this->mTriggerNext.pop_back();
  279. return true;
  280. }
  281. };
  282. template<class A, class B, class C, class D, class E>
  283. class Signal<bool(A,B,C,D,E)> : public SignalBaseT<bool(A,B,C,D,E)>
  284. {
  285. public:
  286. bool trigger( A a, B b, C c, D d, E e )
  287. {
  288. this->mTriggerNext.push_back(NULL);
  289. for( SignalBase::DelegateLink* ptr = this->mList.next; ptr != &this->mList; )
  290. {
  291. this->mTriggerNext.last() = ptr->next;
  292. if( !this->getDelegate( ptr )( a, b, c, d, e ) )
  293. {
  294. this->mTriggerNext.pop_back();
  295. return false;
  296. }
  297. ptr = this->mTriggerNext.last();
  298. }
  299. this->mTriggerNext.pop_back();
  300. return true;
  301. }
  302. };
  303. template<class A, class B, class C, class D, class E, class F>
  304. class Signal<bool(A,B,C,D,E,F)> : public SignalBaseT<bool(A,B,C,D,E,F)>
  305. {
  306. public:
  307. bool trigger( A a, B b, C c, D d, E e, F f )
  308. {
  309. this->mTriggerNext.push_back(NULL);
  310. for( SignalBase::DelegateLink* ptr = this->mList.next; ptr != &this->mList; )
  311. {
  312. this->mTriggerNext.last() = ptr->next;
  313. if( !this->getDelegate( ptr )( a, b, c, d, e, f ) )
  314. {
  315. this->mTriggerNext.pop_back();
  316. return false;
  317. }
  318. ptr = this->mTriggerNext.last();
  319. }
  320. this->mTriggerNext.pop_back();
  321. return true;
  322. }
  323. };
  324. template<class A, class B, class C, class D, class E, class F, class G>
  325. class Signal<bool(A,B,C,D,E,F,G)> : public SignalBaseT<bool(A,B,C,D,E,F,G)>
  326. {
  327. public:
  328. bool trigger( A a, B b, C c, D d, E e, F f, G g )
  329. {
  330. this->mTriggerNext.push_back(NULL);
  331. for( SignalBase::DelegateLink* ptr = this->mList.next; ptr != &this->mList; )
  332. {
  333. this->mTriggerNext.last() = ptr->next;
  334. if( !this->getDelegate( ptr )( a, b, c, d, e, f, g ) )
  335. {
  336. this->mTriggerNext.pop_back();
  337. return false;
  338. }
  339. ptr = this->mTriggerNext.last();
  340. }
  341. this->mTriggerNext.pop_back();
  342. return true;
  343. }
  344. };
  345. template<class A, class B, class C, class D, class E, class F, class G, class H>
  346. class Signal<bool(A,B,C,D,E,F,G,H)> : public SignalBaseT<bool(A,B,C,D,E,F,G,H)>
  347. {
  348. public:
  349. bool trigger( A a, B b, C c, D d, E e, F f, G g, H h )
  350. {
  351. this->mTriggerNext.push_back(NULL);
  352. for( SignalBase::DelegateLink* ptr = this->mList.next; ptr != &this->mList; )
  353. {
  354. this->mTriggerNext.last() = ptr->next;
  355. if( !this->getDelegate( ptr )( a, b, c, d, e, f, g, h ) )
  356. {
  357. this->mTriggerNext.pop_back();
  358. return false;
  359. }
  360. ptr = this->mTriggerNext.last();
  361. }
  362. this->mTriggerNext.pop_back();
  363. return true;
  364. }
  365. };
  366. template<class A, class B, class C, class D, class E, class F, class G, class H, class I>
  367. class Signal<bool(A,B,C,D,E,F,G,H,I)> : public SignalBaseT<bool(A,B,C,D,E,F,G,H,I)>
  368. {
  369. public:
  370. bool trigger( A a, B b, C c, D d, E e, F f, G g, H h, I i )
  371. {
  372. this->mTriggerNext.push_back(NULL);
  373. for( SignalBase::DelegateLink* ptr = this->mList.next; ptr != &this->mList; )
  374. {
  375. this->mTriggerNext.last() = ptr->next;
  376. if( !this->getDelegate( ptr )( a, b, c, d, e, f, g, h, i ) )
  377. {
  378. this->mTriggerNext.pop_back();
  379. return false;
  380. }
  381. ptr = this->mTriggerNext.last();
  382. }
  383. this->mTriggerNext.pop_back();
  384. return true;
  385. }
  386. };
  387. template<class A, class B, class C, class D, class E, class F, class G, class H, class I, class J>
  388. class Signal<bool(A,B,C,D,E,F,G,H,I,J)> : public SignalBaseT<bool(A,B,C,D,E,F,G,H,I,J)>
  389. {
  390. public:
  391. bool trigger( A a, B b, C c, D d, E e, F f, G g, H h, I i, J j )
  392. {
  393. this->mTriggerNext.push_back(NULL);
  394. for( SignalBase::DelegateLink* ptr = this->mList.next; ptr != &this->mList; )
  395. {
  396. this->mTriggerNext.last() = ptr->next;
  397. if( !this->getDelegate( ptr )( a, b, c, d, e, f, g, h, i, j ) )
  398. {
  399. this->mTriggerNext.pop_back();
  400. return false;
  401. }
  402. ptr = this->mTriggerNext.last();
  403. }
  404. this->mTriggerNext.pop_back();
  405. return true;
  406. }
  407. };
  408. // Non short-circuit signal implementations
  409. template<>
  410. class Signal<void()> : public SignalBaseT<void()>
  411. {
  412. public:
  413. void trigger()
  414. {
  415. this->mTriggerNext.push_back(NULL);
  416. for( SignalBase::DelegateLink* ptr = this->mList.next; ptr != &this->mList; )
  417. {
  418. this->mTriggerNext.last() = ptr->next;
  419. this->getDelegate( ptr )();
  420. ptr = this->mTriggerNext.last();
  421. }
  422. this->mTriggerNext.pop_back();
  423. }
  424. };
  425. template<class A>
  426. class Signal<void(A)> : public SignalBaseT<void(A)>
  427. {
  428. public:
  429. void trigger( A a )
  430. {
  431. this->mTriggerNext.push_back(NULL);
  432. for( SignalBase::DelegateLink* ptr = this->mList.next; ptr != &this->mList; )
  433. {
  434. this->mTriggerNext.last() = ptr->next;
  435. this->getDelegate( ptr )( a );
  436. ptr = this->mTriggerNext.last();
  437. }
  438. this->mTriggerNext.pop_back();
  439. }
  440. };
  441. template<class A, class B>
  442. class Signal<void(A,B)> : public SignalBaseT<void(A,B)>
  443. {
  444. public:
  445. void trigger( A a, B b )
  446. {
  447. this->mTriggerNext.push_back(NULL);
  448. for( SignalBase::DelegateLink* ptr = this->mList.next; ptr != &this->mList; )
  449. {
  450. this->mTriggerNext.last() = ptr->next;
  451. this->getDelegate( ptr )( a, b );
  452. ptr = this->mTriggerNext.last();
  453. }
  454. this->mTriggerNext.pop_back();
  455. }
  456. };
  457. template<class A, class B, class C>
  458. class Signal<void(A,B,C)> : public SignalBaseT<void(A,B,C)>
  459. {
  460. public:
  461. void trigger( A a, B b, C c )
  462. {
  463. this->mTriggerNext.push_back(NULL);
  464. for( SignalBase::DelegateLink* ptr = this->mList.next; ptr != &this->mList; )
  465. {
  466. this->mTriggerNext.last() = ptr->next;
  467. this->getDelegate( ptr )( a, b, c );
  468. ptr = this->mTriggerNext.last();
  469. }
  470. this->mTriggerNext.pop_back();
  471. }
  472. };
  473. template<class A, class B, class C, class D>
  474. class Signal<void(A,B,C,D)> : public SignalBaseT<void(A,B,C,D)>
  475. {
  476. public:
  477. void trigger( A a, B b, C c, D d )
  478. {
  479. this->mTriggerNext.push_back(NULL);
  480. for( SignalBase::DelegateLink* ptr = this->mList.next; ptr != &this->mList; )
  481. {
  482. this->mTriggerNext.last() = ptr->next;
  483. this->getDelegate( ptr )( a, b, c, d );
  484. ptr = this->mTriggerNext.last();
  485. }
  486. this->mTriggerNext.pop_back();
  487. }
  488. };
  489. template<class A, class B, class C, class D, class E>
  490. class Signal<void(A,B,C,D,E)> : public SignalBaseT<void(A,B,C,D,E)>
  491. {
  492. public:
  493. void trigger( A a, B b, C c, D d, E e )
  494. {
  495. this->mTriggerNext.push_back(NULL);
  496. for( SignalBase::DelegateLink* ptr = this->mList.next; ptr != &this->mList; )
  497. {
  498. this->mTriggerNext.last() = ptr->next;
  499. this->getDelegate( ptr )( a, b, c, d, e );
  500. ptr = this->mTriggerNext.last();
  501. }
  502. this->mTriggerNext.pop_back();
  503. }
  504. };
  505. template<class A, class B, class C, class D, class E, class F>
  506. class Signal<void(A,B,C,D,E,F)> : public SignalBaseT<void(A,B,C,D,E,F)>
  507. {
  508. public:
  509. void trigger( A a, B b, C c, D d, E e, F f )
  510. {
  511. this->mTriggerNext.push_back(NULL);
  512. for( SignalBase::DelegateLink* ptr = this->mList.next; ptr != &this->mList; )
  513. {
  514. this->mTriggerNext.last() = ptr->next;
  515. this->getDelegate( ptr )( a, b, c, d, e, f );
  516. ptr = this->mTriggerNext.last();
  517. }
  518. this->mTriggerNext.pop_back();
  519. }
  520. };
  521. template<class A, class B, class C, class D, class E, class F, class G>
  522. class Signal<void(A,B,C,D,E,F,G)> : public SignalBaseT<void(A,B,C,D,E,F,G)>
  523. {
  524. public:
  525. void trigger( A a, B b, C c, D d, E e, F f, G g )
  526. {
  527. this->mTriggerNext.push_back(NULL);
  528. for( SignalBase::DelegateLink* ptr = this->mList.next; ptr != &this->mList; )
  529. {
  530. this->mTriggerNext.last() = ptr->next;
  531. this->getDelegate( ptr )( a, b, c, d, e, f, g );
  532. ptr = this->mTriggerNext.last();
  533. }
  534. this->mTriggerNext.pop_back();
  535. }
  536. };
  537. template<class A, class B, class C, class D, class E, class F, class G, class H>
  538. class Signal<void(A,B,C,D,E,F,G,H)> : public SignalBaseT<void(A,B,C,D,E,F,G,H)>
  539. {
  540. public:
  541. void trigger( A a, B b, C c, D d, E e, F f, G g, H h )
  542. {
  543. this->mTriggerNext.push_back(NULL);
  544. for( SignalBase::DelegateLink* ptr = this->mList.next; ptr != &this->mList; )
  545. {
  546. this->mTriggerNext.last() = ptr->next;
  547. this->getDelegate( ptr )( a, b, c, d, e, f, g, h );
  548. ptr = this->mTriggerNext.last();
  549. }
  550. this->mTriggerNext.pop_back();
  551. }
  552. };
  553. template<class A, class B, class C, class D, class E, class F, class G, class H, class I>
  554. class Signal<void(A,B,C,D,E,F,G,H,I)> : public SignalBaseT<void(A,B,C,D,E,F,G,H,I)>
  555. {
  556. public:
  557. void trigger( A a, B b, C c, D d, E e, F f, G g, H h, I i )
  558. {
  559. this->mTriggerNext.push_back(NULL);
  560. for( SignalBase::DelegateLink* ptr = this->mList.next; ptr != &this->mList; )
  561. {
  562. this->mTriggerNext.last() = ptr->next;
  563. this->getDelegate( ptr )( a, b, c, d, e, f, g, h, i );
  564. ptr = this->mTriggerNext.last();
  565. }
  566. this->mTriggerNext.pop_back();
  567. }
  568. };
  569. template<class A, class B, class C, class D, class E, class F, class G, class H, class I, class J>
  570. class Signal<void(A,B,C,D,E,F,G,H,I,J)> : public SignalBaseT<void(A,B,C,D,E,F,G,H,I,J)>
  571. {
  572. public:
  573. void trigger( A a, B b, C c, D d, E e, F f, G g, H h, I i, J j )
  574. {
  575. this->mTriggerNext.push_back(NULL);
  576. for( SignalBase::DelegateLink* ptr = this->mList.next; ptr != &this->mList; )
  577. {
  578. this->mTriggerNext.last() = ptr->next;
  579. this->getDelegate( ptr )( a, b, c, d, e, f, g, h, i, j );
  580. ptr = this->mTriggerNext.last();
  581. }
  582. this->mTriggerNext.pop_back();
  583. }
  584. };
  585. #endif // _DELEGATESIGNAL_H_