fork download
  1. #include <iostream>
  2.  
  3.  
  4. #include <vector> //for containers
  5. #include <algorithm> //for remove_if
  6. #include <utility> //for pair
  7. #include <cassert>
  8.  
  9. namespace sisl { // signal slot
  10.  
  11. namespace detail {
  12.  
  13.  
  14.  
  15. //==============types for customization===================
  16.  
  17. template <typename TInvokable>
  18. struct SlotContainer {
  19. typedef std::vector<TInvokable> type;
  20. };
  21.  
  22. template <typename TResult>
  23. struct ReturnValueAggregateContainerType {
  24. typedef std::vector<TResult> type;
  25. };
  26.  
  27. /**
  28.  * @brief The LockingDisabled struct is a locking implementation
  29.  * which does nothing which is the default synchronization behaviour.
  30.  */
  31. struct LockingDisabled{
  32. struct Mutex{};
  33. struct ScopedLock{ScopedLock(Mutex const&){}};
  34. };
  35.  
  36.  
  37. struct ScopedLock{
  38. typedef LockingDisabled::ScopedLock type;
  39. };
  40.  
  41. struct Mutex{
  42. typedef LockingDisabled::Mutex type;
  43. };
  44.  
  45.  
  46.  
  47.  
  48.  
  49.  
  50. /**
  51.  * @brief Instances of this struct represent the aggregated return values
  52.  */
  53. template <typename R>
  54. struct ReturnValueAggregate {
  55.  
  56. typedef typename ReturnValueAggregateContainerType<R>::type type;
  57.  
  58. operator type() const { return out; }
  59.  
  60. type out;
  61. };
  62.  
  63. template <>
  64. struct ReturnValueAggregate<void> {};
  65.  
  66.  
  67.  
  68. /**
  69.  * @brief This interface represents an abstract call.
  70.  */
  71.  
  72. template <typename R = void, typename A1 = void, typename A2 = void, typename A3 = void, typename A4 = void, typename A5 = void>
  73. struct Invokable;
  74.  
  75. template <typename R, typename A1, typename A2, typename A3, typename A4>
  76. struct Invokable<R, A1, A2, A3, A4> {
  77. virtual R operator()(A1, A2, A3, A4) = 0;
  78. virtual ~Invokable() {}
  79. };
  80.  
  81. template <typename R, typename A1, typename A2, typename A3>
  82. struct Invokable<R, A1, A2, A3> {
  83. virtual R operator()(A1, A2, A3) = 0;
  84. virtual ~Invokable() {}
  85. };
  86.  
  87. template <typename R, typename A1, typename A2>
  88. struct Invokable<R, A1, A2> {
  89. virtual R operator()(A1, A2) = 0;
  90. virtual ~Invokable() {}
  91. };
  92.  
  93. template <typename R, typename A1>
  94. struct Invokable<R, A1> {
  95. virtual R operator()(A1) = 0;
  96. virtual ~Invokable() {}
  97. };
  98.  
  99. template <typename R>
  100. struct Invokable<R> {
  101. virtual R operator()() = 0;
  102. virtual ~Invokable() {}
  103. };
  104.  
  105.  
  106.  
  107. //==============struct MemberFunc===================
  108.  
  109. struct Const{};
  110. struct NonConst{};
  111.  
  112.  
  113.  
  114. /**
  115.  * @brief This helper class defines the type of a member function specialized for const / non-const.
  116.  */
  117. template <typename TObj, typename Constness, typename R = void, typename A1 = void, typename A2 = void, typename A3 = void, typename A4 = void>
  118. struct MemberFunc;
  119.  
  120. template <typename TObj, typename R, typename A1, typename A2, typename A3, typename A4>
  121. struct MemberFunc<TObj, NonConst, R, A1, A2, A3, A4> {
  122. typedef R (TObj::*type)(A1, A2, A3, A4);
  123. };
  124.  
  125. template <typename TObj, typename R, typename A1, typename A2, typename A3>
  126. struct MemberFunc<TObj, NonConst, R, A1, A2, A3> {
  127. typedef R (TObj::*type)(A1, A2, A3);
  128. };
  129.  
  130. template <typename TObj, typename R, typename A1, typename A2>
  131. struct MemberFunc<TObj, NonConst, R, A1, A2> {
  132. typedef R (TObj::*type)(A1, A2);
  133. };
  134.  
  135. template <typename TObj, typename R, typename A1>
  136. struct MemberFunc<TObj, NonConst, R, A1> {
  137. typedef R (TObj::*type)(A1);
  138. };
  139.  
  140. template <typename R, typename TObj>
  141. struct MemberFunc<TObj, NonConst, R> {
  142. typedef R (TObj::*type)();
  143. };
  144.  
  145. template <typename TObj, typename R, typename A1, typename A2, typename A3, typename A4>
  146. struct MemberFunc<TObj, Const, R, A1, A2, A3, A4> {
  147. typedef R (TObj::*type)(A1, A2, A3, A4) const;
  148. };
  149.  
  150. template <typename TObj, typename R, typename A1, typename A2, typename A3>
  151. struct MemberFunc<TObj, Const, R, A1, A2, A3> {
  152. typedef R (TObj::*type)(A1, A2, A3) const;
  153. };
  154.  
  155. template <typename TObj, typename R, typename A1, typename A2>
  156. struct MemberFunc<TObj, Const, R, A1, A2> {
  157. typedef R (TObj::*type)(A1, A2) const;
  158. };
  159.  
  160. template <typename TObj, typename R, typename A1>
  161. struct MemberFunc<TObj, Const, R, A1> {
  162. typedef R (TObj::*type)(A1) const;
  163. };
  164.  
  165. template <typename R, typename TObj>
  166. struct MemberFunc<TObj, Const, R> {
  167. typedef R (TObj::*type)() const;
  168. };
  169.  
  170.  
  171. struct Default{};
  172. struct NonDefault{};
  173. //==============struct CallableImpl===================
  174.  
  175. /**
  176.  * @brief The struct CallableImpl contains conrcrete
  177.  * implementations of the Invokable-inferface specializing void and non-void cases
  178.  */
  179. template <typename R>
  180. struct InvokableImpl {
  181.  
  182. typedef R R_;
  183.  
  184. template <typename A1 = void, typename A2 = void, typename A3 = void, typename A4 = void, typename A5 = void, typename isDefault = Default>
  185. struct GlobalFunction;
  186.  
  187. template <typename A1, typename A2, typename A3, typename A4>
  188. struct GlobalFunction<A1, A2, A3, A4> : public Invokable<R_, A1, A2, A3, A4> {
  189. typedef GlobalFunction<A1, A2, A3, A4> Classtype;
  190. typedef Invokable<R_, A1, A2, A3, A4> Superclass;
  191. typedef R_ (*Member)(A1, A2, A3, A4);
  192. virtual R_ operator()(A1 a1, A2 a2, A3 a3, A4 a4) { return m_member(a1, a2, a3, a4); }
  193. GlobalFunction(Member member) : m_member(member) {}
  194. bool isEqual(Classtype const& other)const{ return m_member == other.m_member;}
  195. private:
  196. Member m_member;
  197. };
  198.  
  199. template <typename A1, typename A2, typename A3>
  200. struct GlobalFunction<A1, A2, A3> : public Invokable<R_, A1, A2, A3> {
  201. typedef GlobalFunction<A1, A2, A3> Classtype;
  202. typedef Invokable<R_, A1, A2, A3> Superclass;
  203. typedef R_ (*Member)(A1, A2, A3);
  204. virtual R_ operator()(A1 a1, A2 a2, A3 a3) { return m_member(a1, a2, a3); }
  205. GlobalFunction(Member member) : m_member(member) {}
  206. bool isEqual(Classtype const& other)const{ return m_member == other.m_member;}
  207. private:
  208. Member m_member;
  209. };
  210.  
  211. template <typename A1, typename A2>
  212. struct GlobalFunction<A1, A2> : public Invokable<R_, A1, A2> {
  213. typedef GlobalFunction<A1, A2> Classtype;
  214. typedef Invokable<R_, A1, A2> Superclass;
  215. typedef R_ (*Member)(A1, A2);
  216. virtual R_ operator()(A1 a1, A2 a2) { return m_member(a1, a2); }
  217. GlobalFunction(Member member) : m_member(member) {}
  218. bool isEqual(Classtype const& other)const{ return m_member == other.m_member;}
  219. private:
  220. Member m_member;
  221. };
  222.  
  223. template <typename A1>
  224. struct GlobalFunction<A1> : public Invokable<R_, A1> {
  225. typedef GlobalFunction<A1> Classtype;
  226. typedef Invokable<R_, A1> Superclass;
  227. typedef R_ (*Member)(A1);
  228. virtual R_ operator()(A1 a1) { return m_member(a1); }
  229. GlobalFunction(Member member) : m_member(member) {}
  230. bool isEqual(Classtype const& other)const{ return m_member == other.m_member;}
  231. private:
  232. Member m_member;
  233. };
  234.  
  235. template <typename isDefault> // must have at least one template parameter to compile!
  236. struct GlobalFunction<void, void, void, void, void, isDefault> : public Invokable<R_> { //must be non-default!
  237. typedef GlobalFunction<void, void, void, void, void, isDefault> Classtype;
  238. typedef Invokable<R_> Superclass;
  239. typedef R_ (*Member)();
  240. virtual R_ operator()() { return m_member(); }
  241. GlobalFunction(Member member) : m_member(member) {}
  242. bool isEqual(Classtype const& other)const{ return m_member == other.m_member;}
  243. private:
  244. Member m_member;
  245. };
  246.  
  247.  
  248.  
  249.  
  250. //////////////////////////////////////////////////////////
  251. template <typename TObj, typename Constness, typename A1 = void, typename A2 = void, typename A3 = void, typename A4 = void, typename A5 = void>
  252. struct MemberFunction;
  253.  
  254. template <typename TObj, typename Constness, typename A1, typename A2, typename A3, typename A4>
  255. struct MemberFunction<TObj, Constness, A1, A2, A3, A4> : public Invokable<R_, A1, A2, A3, A4> {
  256.  
  257. typedef MemberFunction<TObj, Constness, A1, A2, A3, A4> Classtype;
  258. typedef Invokable<R_, A1, A2, A3, A4> Superclass;
  259.  
  260. typedef typename MemberFunc<TObj, Constness, R_, A1, A2, A3, A4>::type Member;
  261.  
  262. virtual R_ operator()(A1 a1, A2 a2, A3 a3, A4 a4) { return (m_obj.*m_member)(a1, a2, a3, a4); }
  263.  
  264. MemberFunction(TObj& obj, Member member) : m_obj(obj), m_member(member) {}
  265.  
  266. bool isEqual(Classtype const& other)const{
  267. return (&m_obj == &(other.m_obj)) && (m_member == other.m_member);
  268. }
  269. private:
  270.  
  271. TObj& m_obj;
  272. Member m_member;
  273. };
  274.  
  275.  
  276. template <typename TObj, typename Constness, typename A1, typename A2, typename A3>
  277. struct MemberFunction<TObj, Constness, A1, A2, A3> : public Invokable<R_, A1, A2, A3> {
  278.  
  279. typedef MemberFunction<TObj, Constness, A1, A2, A3> Classtype;
  280. typedef Invokable<R_, A1, A2, A3> Superclass;
  281.  
  282. typedef typename MemberFunc<TObj, Constness, R_, A1, A2, A3>::type Member;
  283.  
  284. virtual R_ operator()(A1 a1, A2 a2, A3 a3) { return (m_obj.*m_member)(a1, a2, a3); }
  285.  
  286. MemberFunction(TObj& obj, Member member) : m_obj(obj), m_member(member) {}
  287.  
  288. bool isEqual(Classtype const& other)const{
  289. return (&m_obj == &(other.m_obj)) && (m_member == other.m_member);
  290. }
  291. private:
  292.  
  293. TObj& m_obj;
  294. Member m_member;
  295. };
  296. template <typename TObj, typename Constness, typename A1, typename A2>
  297. struct MemberFunction<TObj, Constness, A1, A2> : public Invokable<R_, A1, A2> {
  298.  
  299. typedef MemberFunction<TObj, Constness, A1, A2> Classtype;
  300. typedef Invokable<R_, A1, A2> Superclass;
  301. typedef typename MemberFunc<TObj, Constness, R_, A1, A2>::type Member;
  302.  
  303. virtual R_ operator()(A1 a1, A2 a2) { return (m_obj.*m_member)(a1, a2); }
  304.  
  305. MemberFunction(TObj& obj, Member member) : m_obj(obj), m_member(member) {}
  306.  
  307. bool isEqual(Classtype const& other)const{
  308. return (&m_obj == &(other.m_obj)) && (m_member == other.m_member);
  309. }
  310. private:
  311.  
  312. TObj& m_obj;
  313. Member m_member;
  314. };
  315. template <typename TObj, typename Constness, typename A1>
  316. struct MemberFunction<TObj, Constness, A1> : public Invokable<R_, A1> {
  317.  
  318. typedef MemberFunction<TObj, Constness, A1> Classtype;
  319. typedef Invokable<R_, A1> Superclass;
  320.  
  321. typedef typename MemberFunc<TObj, Constness, R_, A1>::type Member;
  322.  
  323. virtual R_ operator()(A1 a1) { return (m_obj.*m_member)(a1); }
  324.  
  325. MemberFunction(TObj& obj, Member member) : m_obj(obj), m_member(member) {}
  326.  
  327. bool isEqual(Classtype const& other)const{
  328. return (&m_obj == &(other.m_obj)) && (m_member == other.m_member);
  329. }
  330. private:
  331.  
  332. TObj& m_obj;
  333. Member m_member;
  334. };
  335. template <typename TObj, typename Constness>
  336. struct MemberFunction<TObj, Constness> : public Invokable<R_> {
  337.  
  338. typedef MemberFunction<TObj, Constness> Classtype;
  339. typedef Invokable<R_> Superclass;
  340.  
  341. typedef typename MemberFunc<TObj, Constness, R_>::type Member;
  342.  
  343. virtual R_ operator()() { return (m_obj.*m_member)(); }
  344.  
  345. MemberFunction(TObj& obj, Member member) : m_obj(obj), m_member(member) {}
  346.  
  347. bool isEqual(Classtype const& other)const{
  348. return (&m_obj == &(other.m_obj)) && (m_member == other.m_member);
  349. }
  350.  
  351. private:
  352. TObj& m_obj;
  353. Member m_member;
  354. };
  355.  
  356. template <typename A1 = void, typename A2 = void, typename A3 = void, typename A4 = void, typename A5 = void, typename isDefault = Default>
  357. struct BoundFunction;
  358.  
  359. template <typename A1, typename A2, typename A3, typename A4>
  360. struct BoundFunction<A1, A2, A3, A4> {
  361. A1 a1;
  362. A2 a2;
  363. A3 a3;
  364. A4 a4;
  365. BoundFunction(A1 a1_, A2 a2_, A3 a3_, A4 a4_):a1(a1_),a2(a2_),a3(a3_),a4(a4_){}
  366. virtual R_ operator()(Invokable<R_,A1, A2, A3, A4>& invokable) { return invokable(a1,a2,a3,a4); }
  367. };
  368.  
  369. template <typename A1, typename A2, typename A3>
  370. struct BoundFunction<A1, A2, A3> {
  371. A1 a1;
  372. A2 a2;
  373. A3 a3;
  374. BoundFunction(A1 a1_, A2 a2_, A3 a3_):a1(a1_),a2(a2_),a3(a3_){}
  375. virtual R_ operator()(Invokable<R_,A1, A2, A3>& invokable) { return invokable(a1,a2,a3); }
  376. };
  377.  
  378. template <typename A1, typename A2>
  379. struct BoundFunction<A1, A2> {
  380. A1 a1;
  381. A2 a2;
  382. BoundFunction(A1 a1_, A2 a2_):a1(a1_),a2(a2_){}
  383. virtual R_ operator()(Invokable<R_,A1, A2>& invokable) { return invokable(a1,a2); }
  384. };
  385.  
  386. template <typename A1>
  387. struct BoundFunction<A1> {
  388. A1 a1;
  389. BoundFunction(A1 a1_):a1(a1_){}
  390. virtual R_ operator()(Invokable<R_,A1>& invokable) { return invokable(a1); }
  391. };
  392.  
  393. template<typename isDefault> // must have at least one template parameter to compile!
  394. struct BoundFunction<void,void,void,void,void,isDefault> {
  395. BoundFunction(){}
  396. virtual R_ operator()(Invokable<R_>& invokable) { return invokable(); }
  397. };
  398. };
  399. template <>
  400. struct InvokableImpl<void> {
  401.  
  402. typedef void R_;
  403.  
  404. template <typename A1 = void, typename A2 = void, typename A3 = void, typename A4 = void, typename A5 = void, typename isDefault = Default>
  405. struct GlobalFunction;
  406.  
  407. template <typename A1, typename A2, typename A3, typename A4>
  408. struct GlobalFunction<A1, A2, A3, A4> : public Invokable<R_, A1, A2, A3, A4> {
  409.  
  410. typedef GlobalFunction<A1, A2, A3, A4> Classtype;
  411. typedef Invokable<R_, A1, A2, A3, A4> Superclass;
  412.  
  413. typedef R_ (*Member)(A1, A2, A3, A4);
  414.  
  415. virtual R_ operator()(A1 a1, A2 a2, A3 a3, A4 a4) { m_member(a1, a2, a3, a4); }
  416.  
  417. bool isEqual(Classtype const& other)const{ return m_member == other.m_member;}
  418.  
  419. GlobalFunction(Member member) : m_member(member) {}
  420.  
  421. private:
  422. Member m_member;
  423. };
  424.  
  425. template <typename A1, typename A2, typename A3>
  426. struct GlobalFunction<A1, A2, A3> : public Invokable<R_, A1, A2, A3> {
  427.  
  428. typedef GlobalFunction<A1, A2, A3> Classtype;
  429. typedef Invokable<R_, A1, A2, A3> Superclass;
  430.  
  431. typedef R_ (*Member)(A1, A2, A3);
  432.  
  433. virtual R_ operator()(A1 a1, A2 a2, A3 a3) { m_member(a1, a2, a3); }
  434.  
  435. GlobalFunction(Member member) : m_member(member) {}
  436.  
  437. bool isEqual(Classtype const& other)const{ return m_member == other.m_member;}
  438.  
  439. private:
  440. Member m_member;
  441. };
  442. template <typename A1, typename A2>
  443. struct GlobalFunction<A1, A2> : public Invokable<R_, A1, A2> {
  444.  
  445. typedef GlobalFunction<A1, A2> Classtype;
  446. typedef Invokable<R_, A1, A2> Superclass;
  447.  
  448. typedef R_ (*Member)(A1, A2);
  449.  
  450. virtual R_ operator()(A1 a1, A2 a2) { m_member(a1, a2); }
  451.  
  452. GlobalFunction(Member member) : m_member(member) {}
  453.  
  454. bool isEqual(Classtype const& other)const{ return m_member == other.m_member;}
  455.  
  456. private:
  457. Member m_member;
  458.  
  459. };
  460.  
  461. template <typename A1>
  462. struct GlobalFunction<A1> : public Invokable<R_, A1> {
  463.  
  464. typedef GlobalFunction<A1> Classtype;
  465. typedef Invokable<R_, A1> Superclass;
  466.  
  467. typedef R_ (*Member)(A1);
  468.  
  469. virtual R_ operator()(A1 a1) { m_member(a1); }
  470.  
  471. GlobalFunction(Member member) : m_member(member) {}
  472.  
  473. bool isEqual(Classtype const& other)const{ return m_member == other.m_member;}
  474.  
  475. private:
  476. Member m_member;
  477. };
  478.  
  479. template <typename isDefault> // must have at least one template parameter to compile!
  480. struct GlobalFunction<void, void, void, void, void, isDefault> : public Invokable<R_> { //must be nonDefault
  481.  
  482. typedef GlobalFunction<void, void, void, void, void, isDefault> Classtype;
  483. typedef Invokable<R_> Superclass;
  484.  
  485. typedef R_ (*Member)();
  486.  
  487. virtual R_ operator()() { m_member(); }
  488.  
  489. GlobalFunction(Member member) : m_member(member) {}
  490.  
  491. bool isEqual(Classtype const& other)const{ return m_member == other.m_member;}
  492.  
  493. private:
  494. Member m_member;
  495. };
  496.  
  497.  
  498. //////////////////////////////////////////////////////////
  499.  
  500.  
  501. template <typename TObj, typename Constness, typename A1 = void, typename A2 = void, typename A3 = void, typename A4 = void, typename A5 = void>
  502. struct MemberFunction;
  503.  
  504. template <typename TObj, typename Constness, typename A1, typename A2, typename A3, typename A4>
  505. struct MemberFunction<TObj, Constness, A1, A2, A3, A4> : public Invokable<R_, A1, A2, A3, A4> {
  506.  
  507. typedef MemberFunction<TObj, Constness, A1, A2, A3, A4> Classtype;
  508. typedef Invokable<R_, A1, A2, A3, A4> Superclass;
  509.  
  510. typedef typename MemberFunc<TObj, Constness, R_, A1, A2, A3, A4>::type Member;
  511.  
  512. virtual R_ operator()(A1 a1, A2 a2, A3 a3, A4 a4) { (m_obj.*m_member)(a1, a2, a3, a4); }
  513.  
  514. MemberFunction(TObj& obj, Member member) : m_obj(obj), m_member(member) {}
  515.  
  516. bool isEqual(Classtype const& other)const{
  517. return (&m_obj == &(other.m_obj)) && (m_member == other.m_member);
  518. }
  519.  
  520. private:
  521. TObj& m_obj;
  522. Member m_member;
  523. };
  524.  
  525. template <typename TObj, typename Constness, typename A1, typename A2, typename A3>
  526. struct MemberFunction<TObj, Constness, A1, A2, A3> : public Invokable<R_, A1, A2, A3> {
  527.  
  528. typedef MemberFunction<TObj, Constness, A1, A2, A3> Classtype;
  529. typedef Invokable<R_, A1, A2, A3> Superclass;
  530.  
  531. typedef typename MemberFunc<TObj, Constness, R_, A1, A2, A3>::type Member;
  532.  
  533. virtual R_ operator()(A1 a1, A2 a2, A3 a3) { (m_obj.*m_member)(a1, a2, a3); }
  534.  
  535. MemberFunction(TObj& obj, Member member) : m_obj(obj), m_member(member) {}
  536.  
  537. bool isEqual(Classtype const& other)const{
  538. return (&m_obj == &(other.m_obj)) && (m_member == other.m_member);
  539. }
  540.  
  541. private:
  542. TObj& m_obj;
  543. Member m_member;
  544. };
  545.  
  546. template <typename TObj, typename Constness, typename A1, typename A2>
  547. struct MemberFunction<TObj, Constness, A1, A2> : public Invokable<R_, A1, A2> {
  548.  
  549. typedef MemberFunction<TObj, Constness, A1, A2> Classtype;
  550. typedef Invokable<R_, A1, A2> Superclass;
  551.  
  552. typedef typename MemberFunc<TObj, Constness, R_, A1, A2>::type Member;
  553.  
  554. virtual R_ operator()(A1 a1, A2 a2) { (m_obj.*m_member)(a1, a2); }
  555.  
  556. MemberFunction(TObj& obj, Member member) : m_obj(obj), m_member(member) {}
  557.  
  558. bool isEqual(Classtype const& other)const{
  559. return (&m_obj == &(other.m_obj)) && (m_member == other.m_member);
  560. }
  561.  
  562. private:
  563. TObj& m_obj;
  564. Member m_member;
  565. };
  566.  
  567. template <typename TObj, typename Constness, typename A1>
  568. struct MemberFunction<TObj, Constness, A1> : public Invokable<R_, A1> {
  569.  
  570. typedef MemberFunction<TObj, Constness, A1> Classtype;
  571. typedef Invokable<R_, A1> Superclass;
  572.  
  573. typedef typename MemberFunc<TObj, Constness, R_, A1>::type Member;
  574.  
  575. virtual R_ operator()(A1 a1) { (m_obj.*m_member)(a1); }
  576.  
  577. MemberFunction(TObj& obj, Member member) : m_obj(obj), m_member(member) {}
  578.  
  579. bool isEqual(Classtype const& other)const{
  580. return (&m_obj == &(other.m_obj)) && (m_member == other.m_member);
  581. }
  582.  
  583. private:
  584. TObj& m_obj;
  585. Member m_member;
  586. };
  587.  
  588. template <typename TObj, typename Constness>
  589. struct MemberFunction<TObj, Constness> : public Invokable<R_> {
  590.  
  591. typedef MemberFunction<TObj, Constness> Classtype;
  592. typedef Invokable<R_> Superclass;
  593.  
  594. typedef typename MemberFunc<TObj, Constness, R_>::type Member;
  595.  
  596. virtual R_ operator()() { (m_obj.*m_member)(); }
  597.  
  598. MemberFunction(TObj& obj, Member member) : m_obj(obj), m_member(member) {}
  599.  
  600. bool isEqual(Classtype const& other)const{
  601. return (&m_obj == &(other.m_obj)) && (m_member == other.m_member);
  602. }
  603.  
  604. private:
  605. TObj& m_obj;
  606. Member m_member;
  607. };
  608.  
  609. template <typename A1 = void, typename A2 = void, typename A3 = void, typename A4 = void, typename A5 = void, typename isDefault = Default>
  610. struct BoundFunction;
  611.  
  612. template <typename A1, typename A2, typename A3, typename A4>
  613. struct BoundFunction<A1, A2, A3, A4> {
  614. A1 a1;
  615. A2 a2;
  616. A3 a3;
  617. A4 a4;
  618. BoundFunction(A1 a1_, A2 a2_, A3 a3_, A4 a4_):a1(a1_),a2(a2_),a3(a3_),a4(a4_){}
  619. virtual R_ operator()(Invokable<R_,A1, A2, A3, A4>& invokable) { invokable(a1,a2,a3,a4); }
  620. };
  621.  
  622. template <typename A1, typename A2, typename A3>
  623. struct BoundFunction<A1, A2, A3> {
  624. A1 a1;
  625. A2 a2;
  626. A3 a3;
  627. BoundFunction(A1 a1_, A2 a2_, A3 a3_):a1(a1_),a2(a2_),a3(a3_){}
  628. virtual R_ operator()(Invokable<R_,A1, A2, A3>& invokable) { invokable(a1,a2,a3); }
  629. };
  630.  
  631. template <typename A1, typename A2>
  632. struct BoundFunction<A1, A2> {
  633. A1 a1;
  634. A2 a2;
  635. BoundFunction(A1 a1_, A2 a2_):a1(a1_),a2(a2_){}
  636. virtual R_ operator()(Invokable<R_,A1, A2>& invokable) { invokable(a1,a2); }
  637. };
  638.  
  639. template <typename A1>
  640. struct BoundFunction<A1> {
  641. A1 a1;
  642. BoundFunction(A1 a1_):a1(a1_){}
  643. virtual R_ operator()(Invokable<R_,A1>& invokable) { invokable(a1); }
  644. };
  645.  
  646. template<typename isDefault> // must have at least one template parameter to compile!
  647. struct BoundFunction<void,void,void,void,void,isDefault> {
  648. BoundFunction(){}
  649. virtual R_ operator()(Invokable<R_>& invokable) { invokable(); }
  650. };
  651. };
  652.  
  653. struct ScopedInversion{
  654. bool& target;
  655. const bool origValue;
  656. ScopedInversion(bool& target_):target(target_),origValue(target_){target = !target;}
  657. ~ScopedInversion(){target = origValue;}
  658. };
  659.  
  660.  
  661.  
  662. typedef bool DisconnectionPending;
  663. inline DisconnectionPending disconnectPending(){return true;}
  664. inline DisconnectionPending connected(){return disconnectPending()==false;}
  665.  
  666.  
  667. template<typename TInvokablePtr>
  668. struct IsPendingDisconnect {
  669.  
  670. typedef std::pair<TInvokablePtr,bool> Slot;
  671.  
  672. bool operator()(Slot const& other)const{
  673. return other.second == disconnectPending();
  674. }
  675. };
  676.  
  677.  
  678. /**
  679.  * @brief Comparing of 2 invokable instances
  680.  */
  681. template<typename TInvokable>
  682. struct IsCaller {
  683.  
  684. typedef std::pair<typename TInvokable::Superclass*,bool> Slot;
  685.  
  686. IsCaller(TInvokable const& c):invokable(c){}
  687. TInvokable const& invokable;
  688.  
  689. bool operator()(Slot const& other)const{
  690. TInvokable const* t = dynamic_cast<TInvokable const*>(other.first);
  691. return t!=NULL ? invokable.isEqual(*t) : false;
  692. }
  693. };
  694.  
  695.  
  696.  
  697.  
  698. /**
  699.  * Removing a slot from the list of slots
  700.  */
  701. template<typename Slots>
  702. void disconnectNow(Slots& slots){
  703.  
  704. const IsPendingDisconnect<typename Slots::value_type::first_type> pred;
  705.  
  706. typedef typename Slots::const_iterator It;
  707. for(It it = slots.begin(), end = slots.end();it!=end;++it)
  708. if (pred(*it))
  709. delete it->first;
  710.  
  711. slots.erase(std::remove_if(slots.begin(),slots.end(), pred), slots.end());
  712. }
  713.  
  714. template<typename Slots, typename TCaller>
  715. void disconnectDelayed(Slots& slots, TCaller const& caller){
  716.  
  717. const IsCaller<TCaller> pred(caller);
  718.  
  719. typedef typename Slots::iterator It;
  720. for(It it = slots.begin(), end = slots.end();it!=end;++it)
  721. if (pred(*it))
  722. it->second = disconnectPending();
  723.  
  724. }
  725.  
  726.  
  727. template<typename Slots, typename TCaller>
  728. void disconnect(Slots& slots, bool isCurrentlyEmitting, TCaller const& caller){
  729.  
  730. disconnectDelayed(slots,caller);
  731.  
  732. if (!isCurrentlyEmitting)
  733. disconnectNow(slots);
  734. }
  735.  
  736. /**
  737.  * Removing a slot from the list of slots
  738.  */
  739.  
  740.  
  741. template<typename Slots>
  742. void disconnectAll(Slots& slots){
  743. typedef typename Slots::const_iterator SlotsCIt;
  744. for (SlotsCIt it = slots.begin(), end = slots.end(); it != end; ++it)
  745. delete *it;
  746. slots.clear();
  747. }
  748.  
  749. template<typename Slots>
  750. void disconnectAllNow(Slots& slots){
  751. typedef typename Slots::const_iterator SlotsCIt;
  752. for (SlotsCIt it = slots.begin(), end = slots.end(); it != end; ++it)
  753. delete it->first;
  754. slots.clear();
  755. }
  756.  
  757. template<typename Slots>
  758. void disconnectAllDelayed(Slots& slots){
  759. typedef typename Slots::iterator SlotsCIt;
  760. for (SlotsCIt it = slots.begin(), end = slots.end(); it != end; ++it)
  761. it->second = disconnectPending();
  762.  
  763. }
  764.  
  765. template<typename Slots>
  766. void disconnectAll(Slots& slots, bool isCurrentlyEmitting){
  767. if (isCurrentlyEmitting)
  768. disconnectAllDelayed(slots);
  769. else
  770. disconnectAllNow(slots);
  771.  
  772. }
  773.  
  774. template<typename OutType_, typename CallResult>
  775. void aggregateReturnValue(OutType_& c, CallResult const& r) {
  776. c.out.push_back(r);
  777. }
  778.  
  779. template <typename R>
  780. struct ReturnValueAggregator {
  781.  
  782. typedef R R_;
  783.  
  784. template <typename Slots, typename Args>
  785. static void invokeAndAggregate(ReturnValueAggregate<R_>& r, Slots& slots, Args& args) {
  786.  
  787. typedef typename Slots::const_iterator SlotsCIt;
  788. for (SlotsCIt it = slots.begin(), end = slots.end(); it != end; ++it) {
  789. aggregateReturnValue(r,args(*(it->first)));
  790. }
  791. }
  792. };
  793.  
  794. template <>
  795. struct ReturnValueAggregator<void> {
  796.  
  797. typedef void R_;
  798.  
  799. template <typename Slots, typename Args>
  800. static void invokeAndAggregate(ReturnValueAggregate<R_>&, Slots& slots, Args& args) {
  801.  
  802. typedef typename Slots::const_iterator SlotsCIt;
  803. for (SlotsCIt it = slots.begin(), end = slots.end(); it != end; ++it) {
  804. args(*(it->first));
  805. }
  806. }
  807. };
  808.  
  809.  
  810. template<typename Slots, typename Invokable>
  811. void connect(Slots& slots, Invokable invokable){
  812. slots.push_back(invokable);
  813. }
  814.  
  815.  
  816. template<typename Slots>
  817. void connectPending(Slots& slots, Slots& pendingConnects){
  818.  
  819. typedef typename Slots::const_iterator SlotsCIt;
  820. for (SlotsCIt it = pendingConnects.begin(), end = pendingConnects.end(); it != end; ++it)
  821. connect(slots,*it);
  822.  
  823. pendingConnects.clear();
  824. }
  825.  
  826. template<typename Slots>
  827. void disconnectPending(Slots& slots){
  828. disconnectNow(slots);
  829. }
  830.  
  831.  
  832. } //namespace detail
  833.  
  834.  
  835. /**
  836.  * @brief Main class realizing signal slot behaviour.
  837.  */
  838. template <typename TFunc>
  839. struct Signal;
  840.  
  841. template <typename R, typename A1, typename A2, typename A3,typename A4>
  842. struct Signal<R(A1, A2, A3, A4)> {
  843.  
  844. void connect(R (*member)(A1, A2, A3, A4)) {
  845. ScopedLock_ lock(slotsMutex);
  846. detail::connect(isCurrentlyEmitting ? pendingConnects : slots, Slot(new GCaller(member),detail::connected()));
  847. }
  848.  
  849. template <typename TObj>
  850. void connect(TObj& obj, R (TObj::*member)(A1, A2, A3, A4)) {
  851. ScopedLock_ lock(slotsMutex);
  852. typedef typename MCaller<TObj,detail::NonConst>::type MCaller_;
  853. detail::connect(isCurrentlyEmitting ? pendingConnects : slots, Slot(new MCaller_(obj, member),detail::connected()));
  854. }
  855.  
  856. template <typename TObj>
  857. void connect(TObj const& obj, R (TObj::*member)(A1, A2, A3, A4) const) {
  858. ScopedLock_ lock(slotsMutex);
  859. typedef typename MCaller<const TObj,detail::Const>::type MCaller_;
  860. detail::connect(isCurrentlyEmitting ? pendingConnects : slots, Slot(new MCaller_(obj, member),detail::connected()));
  861. }
  862.  
  863. detail::ReturnValueAggregate<R> emit(A1 a1, A2 a2, A3 a3, A4 a4) {
  864. ScopedLock_ lock(slotsMutex);
  865. Args args(a1,a2,a3,a4);
  866. detail::ReturnValueAggregate<R> r;
  867. if (isCurrentlyEmitting) return r;
  868. detail::ScopedInversion inverter(isCurrentlyEmitting);
  869. detail::ReturnValueAggregator<R>::invokeAndAggregate(r, slots, args);
  870. detail::disconnectPending(slots);
  871. detail::connectPending(slots, pendingConnects);
  872. return r;
  873. }
  874.  
  875. void disconnect(R (*member)(A1, A2, A3, A4)) {
  876. ScopedLock_ lock(slotsMutex);
  877. detail::disconnect(slots, isCurrentlyEmitting, GCaller(member));
  878. }
  879.  
  880. template <typename TObj>
  881. void disconnect(TObj& obj, R (TObj::*member)(A1, A2, A3, A4)) {
  882. ScopedLock_ lock(slotsMutex);
  883. typedef typename MCaller<TObj,detail::NonConst>::type MCaller_;
  884. detail::disconnect(slots, isCurrentlyEmitting, MCaller_(obj,member));
  885. }
  886.  
  887. template <typename TObj>
  888. void disconnect(TObj const& obj, R (TObj::*member)(A1, A2, A3, A4) const) {
  889. ScopedLock_ lock(slotsMutex);
  890. typedef typename MCaller<const TObj,detail::Const>::type MCaller_;
  891. detail::disconnect(slots, isCurrentlyEmitting, MCaller_(obj,member));
  892. }
  893.  
  894. void disconnectAll(){
  895. ScopedLock_ lock(slotsMutex);
  896. detail::disconnectAll(slots, isCurrentlyEmitting);
  897. }
  898.  
  899. ~Signal(){ assert(isCurrentlyEmitting==false); disconnectAll(); } //upon returning from dtor object is invalid so a pending emit()-call would be invalid too!
  900.  
  901. private:
  902. typedef typename detail::InvokableImpl<R>::template BoundFunction<A1, A2, A3, A4> Args;
  903. typedef typename detail::InvokableImpl<R>::template GlobalFunction<A1, A2, A3, A4> GCaller;
  904.  
  905. template <typename TObj, typename Constness>
  906. struct MCaller{ typedef typename detail::InvokableImpl<R>::template MemberFunction<TObj, Constness, A1, A2, A3, A4> type; };
  907.  
  908. typedef std::pair<detail::Invokable<R, A1, A2, A3, A4>*,detail::DisconnectionPending> Slot;
  909. typedef typename detail::SlotContainer<Slot>::type Slots;
  910.  
  911. typedef detail::Mutex::type Mutex_;
  912. typedef detail::ScopedLock::type ScopedLock_;
  913.  
  914. bool isCurrentlyEmitting = false;
  915. Slots pendingConnects;
  916. Slots slots;
  917. Mutex_ slotsMutex;
  918. };
  919.  
  920. template <typename R, typename A1, typename A2, typename A3>
  921. struct Signal<R(A1, A2, A3)> {
  922.  
  923. void connect(R (*member)(A1, A2, A3)) {
  924. ScopedLock_ lock(slotsMutex);
  925. detail::connect(isCurrentlyEmitting ? pendingConnects : slots, Slot(new GCaller(member),detail::connected()));
  926. }
  927.  
  928. template <typename TObj>
  929. void connect(TObj& obj, R (TObj::*member)(A1, A2, A3)) {
  930. ScopedLock_ lock(slotsMutex);
  931. typedef typename MCaller<TObj,detail::NonConst>::type MCaller_;
  932. detail::connect(isCurrentlyEmitting ? pendingConnects : slots, Slot(new MCaller_(obj, member),detail::connected()));
  933. }
  934.  
  935. template <typename TObj>
  936. void connect(TObj const& obj, R (TObj::*member)(A1, A2, A3) const) {
  937. ScopedLock_ lock(slotsMutex);
  938. typedef typename MCaller<const TObj,detail::Const>::type MCaller_;
  939. detail::connect(isCurrentlyEmitting ? pendingConnects : slots, Slot(new MCaller_(obj, member),detail::connected()));
  940. }
  941.  
  942. detail::ReturnValueAggregate<R> emit(A1 a1, A2 a2, A3 a3) {
  943. ScopedLock_ lock(slotsMutex);
  944. Args args(a1,a2,a3);
  945. detail::ReturnValueAggregate<R> r;
  946. if (isCurrentlyEmitting) return r;
  947. detail::ScopedInversion inverter(isCurrentlyEmitting);
  948. detail::ReturnValueAggregator<R>::invokeAndAggregate(r, slots, args);
  949. detail::disconnectPending(slots);
  950. detail::connectPending(slots, pendingConnects);
  951. return r;
  952. }
  953.  
  954. void disconnect(R (*member)(A1, A2, A3)) {
  955. ScopedLock_ lock(slotsMutex);
  956. detail::disconnect(slots, isCurrentlyEmitting, GCaller(member));
  957. }
  958.  
  959. template <typename TObj>
  960. void disconnect(TObj& obj, R (TObj::*member)(A1, A2, A3)) {
  961. ScopedLock_ lock(slotsMutex);
  962. typedef typename MCaller<TObj,detail::NonConst>::type MCaller_;
  963. detail::disconnect(slots, isCurrentlyEmitting, MCaller_(obj,member));
  964. }
  965.  
  966. template <typename TObj>
  967. void disconnect(TObj const& obj, R (TObj::*member)(A1, A2, A3) const) {
  968. ScopedLock_ lock(slotsMutex);
  969. typedef typename MCaller<const TObj,detail::Const>::type MCaller_;
  970. detail::disconnect(slots, isCurrentlyEmitting, MCaller_(obj,member));
  971. }
  972.  
  973. void disconnectAll(){
  974. ScopedLock_ lock(slotsMutex);
  975. detail::disconnectAll(slots, isCurrentlyEmitting);
  976. }
  977.  
  978. ~Signal(){ assert(isCurrentlyEmitting==false); disconnectAll(); } //upon returning from dtor object is invalid so a pending emit()-call would be invalid too!
  979.  
  980. private:
  981. typedef typename detail::InvokableImpl<R>::template BoundFunction<A1, A2, A3> Args;
  982. typedef typename detail::InvokableImpl<R>::template GlobalFunction<A1, A2, A3> GCaller;
  983.  
  984. template <typename TObj, typename Constness>
  985. struct MCaller{ typedef typename detail::InvokableImpl<R>::template MemberFunction<TObj, Constness, A1, A2, A3> type; };
  986.  
  987. typedef std::pair<detail::Invokable<R, A1, A2, A3>*,detail::DisconnectionPending> Slot;
  988. typedef typename detail::SlotContainer<Slot>::type Slots;
  989.  
  990. typedef detail::Mutex::type Mutex_;
  991. typedef detail::ScopedLock::type ScopedLock_;
  992.  
  993. bool isCurrentlyEmitting = false;
  994. Slots pendingConnects;
  995. Slots slots;
  996. Mutex_ slotsMutex;
  997. };
  998.  
  999.  
  1000.  
  1001. template <typename R, typename A1, typename A2>
  1002. struct Signal<R(A1, A2)> {
  1003.  
  1004. void connect(R (*member)(A1, A2)) {
  1005. ScopedLock_ lock(slotsMutex);
  1006. detail::connect(isCurrentlyEmitting ? pendingConnects : slots, Slot(new GCaller(member),detail::connected()));
  1007. }
  1008.  
  1009. template <typename TObj>
  1010. void connect(TObj& obj, R (TObj::*member)(A1, A2)) {
  1011. ScopedLock_ lock(slotsMutex);
  1012. typedef typename MCaller<TObj,detail::NonConst>::type MCaller_;
  1013. detail::connect(isCurrentlyEmitting ? pendingConnects : slots, Slot(new MCaller_(obj, member),detail::connected()));
  1014. }
  1015.  
  1016. template <typename TObj>
  1017. void connect(TObj const& obj, R (TObj::*member)(A1, A2) const) {
  1018. ScopedLock_ lock(slotsMutex);
  1019. typedef typename MCaller<const TObj,detail::Const>::type MCaller_;
  1020. detail::connect(isCurrentlyEmitting ? pendingConnects : slots, Slot(new MCaller_(obj, member),detail::connected()));
  1021. }
  1022.  
  1023. detail::ReturnValueAggregate<R> emit(A1 a1, A2 a2) {
  1024. ScopedLock_ lock(slotsMutex);
  1025. Args args(a1,a2);
  1026. detail::ReturnValueAggregate<R> r;
  1027. if (isCurrentlyEmitting) return r;
  1028. detail::ScopedInversion inverter(isCurrentlyEmitting);
  1029. detail::ReturnValueAggregator<R>::invokeAndAggregate(r, slots, args);
  1030. detail::disconnectPending(slots);
  1031. detail::connectPending(slots, pendingConnects);
  1032. return r;
  1033. }
  1034.  
  1035. void disconnect(R (*member)(A1, A2)) {
  1036. ScopedLock_ lock(slotsMutex);
  1037. detail::disconnect(slots, isCurrentlyEmitting, GCaller(member));
  1038. }
  1039.  
  1040. template <typename TObj>
  1041. void disconnect(TObj& obj, R (TObj::*member)(A1, A2)) {
  1042. ScopedLock_ lock(slotsMutex);
  1043. typedef typename MCaller<TObj,detail::NonConst>::type MCaller_;
  1044. detail::disconnect(slots, isCurrentlyEmitting, MCaller_(obj,member));
  1045. }
  1046.  
  1047. template <typename TObj>
  1048. void disconnect(TObj const& obj, R (TObj::*member)(A1, A2) const) {
  1049. ScopedLock_ lock(slotsMutex);
  1050. typedef typename MCaller<const TObj,detail::Const>::type MCaller_;
  1051. detail::disconnect(slots, isCurrentlyEmitting, MCaller_(obj,member));
  1052. }
  1053.  
  1054. void disconnectAll(){
  1055. ScopedLock_ lock(slotsMutex);
  1056. detail::disconnectAll(slots, isCurrentlyEmitting);
  1057. }
  1058.  
  1059. ~Signal(){ assert(isCurrentlyEmitting==false); disconnectAll(); } //upon returning from dtor object is invalid so a pending emit()-call would be invalid too!
  1060.  
  1061. private:
  1062. typedef typename detail::InvokableImpl<R>::template BoundFunction<A1, A2> Args;
  1063. typedef typename detail::InvokableImpl<R>::template GlobalFunction<A1, A2> GCaller;
  1064.  
  1065. template <typename TObj, typename Constness>
  1066. struct MCaller{ typedef typename detail::InvokableImpl<R>::template MemberFunction<TObj, Constness, A1, A2> type; };
  1067.  
  1068. typedef std::pair<detail::Invokable<R, A1, A2>*,detail::DisconnectionPending> Slot;
  1069. typedef typename detail::SlotContainer<Slot>::type Slots;
  1070.  
  1071. typedef detail::Mutex::type Mutex_;
  1072. typedef detail::ScopedLock::type ScopedLock_;
  1073.  
  1074. bool isCurrentlyEmitting = false;
  1075. Slots pendingConnects;
  1076. Slots slots;
  1077. Mutex_ slotsMutex;
  1078. };
  1079.  
  1080.  
  1081.  
  1082. template <typename R, typename A1>
  1083. struct Signal<R(A1)> {
  1084.  
  1085. void connect(R (*member)(A1)) {
  1086. ScopedLock_ lock(slotsMutex);
  1087. detail::connect(isCurrentlyEmitting ? pendingConnects : slots, Slot(new GCaller(member),detail::connected()));
  1088. }
  1089.  
  1090. template <typename TObj>
  1091. void connect(TObj& obj, R (TObj::*member)(A1)) {
  1092. ScopedLock_ lock(slotsMutex);
  1093. typedef typename MCaller<TObj,detail::NonConst>::type MCaller_;
  1094. detail::connect(isCurrentlyEmitting ? pendingConnects : slots, Slot(new MCaller_(obj, member),detail::connected()));
  1095. }
  1096.  
  1097. template <typename TObj>
  1098. void connect(TObj const& obj, R (TObj::*member)(A1) const) {
  1099. ScopedLock_ lock(slotsMutex);
  1100. typedef typename MCaller<const TObj,detail::Const>::type MCaller_;
  1101. detail::connect(isCurrentlyEmitting ? pendingConnects : slots, Slot(new MCaller_(obj, member),detail::connected()));
  1102. }
  1103.  
  1104. detail::ReturnValueAggregate<R> emit(A1 a1) {
  1105. ScopedLock_ lock(slotsMutex);
  1106. Args args(a1);
  1107. detail::ReturnValueAggregate<R> r;
  1108. if (isCurrentlyEmitting) return r;
  1109. detail::ScopedInversion inverter(isCurrentlyEmitting);
  1110. detail::ReturnValueAggregator<R>::invokeAndAggregate(r, slots, args);
  1111. detail::disconnectPending(slots);
  1112. detail::connectPending(slots, pendingConnects);
  1113. return r;
  1114. }
  1115.  
  1116. void disconnect(R (*member)(A1)) {
  1117. ScopedLock_ lock(slotsMutex);
  1118. detail::disconnect(slots, isCurrentlyEmitting, GCaller(member));
  1119. }
  1120.  
  1121. template <typename TObj>
  1122. void disconnect(TObj& obj, R (TObj::*member)(A1)) {
  1123. ScopedLock_ lock(slotsMutex);
  1124. typedef typename MCaller<TObj,detail::NonConst>::type MCaller_;
  1125. detail::disconnect(slots, isCurrentlyEmitting, MCaller_(obj,member));
  1126. }
  1127.  
  1128. template <typename TObj>
  1129. void disconnect(TObj const& obj, R (TObj::*member)(A1) const) {
  1130. ScopedLock_ lock(slotsMutex);
  1131. typedef typename MCaller<const TObj,detail::Const>::type MCaller_;
  1132. detail::disconnect(slots, isCurrentlyEmitting, MCaller_(obj,member));
  1133. }
  1134.  
  1135. void disconnectAll(){
  1136. ScopedLock_ lock(slotsMutex);
  1137. detail::disconnectAll(slots, isCurrentlyEmitting);
  1138. }
  1139.  
  1140. ~Signal(){ assert(isCurrentlyEmitting==false); disconnectAll(); } //upon returning from dtor object is invalid so a pending emit()-call would be invalid too!
  1141.  
  1142. private:
  1143. typedef typename detail::InvokableImpl<R>::template BoundFunction<A1> Args;
  1144. typedef typename detail::InvokableImpl<R>::template GlobalFunction<A1> GCaller;
  1145.  
  1146. template <typename TObj, typename Constness>
  1147. struct MCaller{ typedef typename detail::InvokableImpl<R>::template MemberFunction<TObj, Constness, A1> type; };
  1148.  
  1149. typedef std::pair<detail::Invokable<R, A1>*,detail::DisconnectionPending> Slot;
  1150. typedef typename detail::SlotContainer<Slot>::type Slots;
  1151.  
  1152. typedef detail::Mutex::type Mutex_;
  1153. typedef detail::ScopedLock::type ScopedLock_;
  1154.  
  1155. bool isCurrentlyEmitting = false;
  1156. Slots pendingConnects;
  1157. Slots slots;
  1158. Mutex_ slotsMutex;
  1159. };
  1160.  
  1161.  
  1162.  
  1163. template <typename R>
  1164. struct Signal<R()> {
  1165.  
  1166. void connect(R (*member)()) {
  1167. ScopedLock_ lock(slotsMutex);
  1168. detail::connect(isCurrentlyEmitting ? pendingConnects : slots, Slot(new GCaller(member),detail::connected()));
  1169. }
  1170.  
  1171. template <typename TObj>
  1172. void connect(TObj& obj, R (TObj::*member)()) {
  1173. ScopedLock_ lock(slotsMutex);
  1174. typedef typename MCaller<TObj,detail::NonConst>::type MCaller_;
  1175. detail::connect(isCurrentlyEmitting ? pendingConnects : slots, Slot(new MCaller_(obj, member),detail::connected()));
  1176. }
  1177.  
  1178. template <typename TObj>
  1179. void connect(TObj const& obj, R (TObj::*member)() const) {
  1180. ScopedLock_ lock(slotsMutex);
  1181. typedef typename MCaller<const TObj,detail::Const>::type MCaller_;
  1182. detail::connect(isCurrentlyEmitting ? pendingConnects : slots, Slot(new MCaller_(obj, member),detail::connected()));
  1183. }
  1184.  
  1185. detail::ReturnValueAggregate<R> emit() {
  1186. ScopedLock_ lock(slotsMutex);
  1187. Args args;
  1188. detail::ReturnValueAggregate<R> r;
  1189. if (isCurrentlyEmitting) return r;
  1190. detail::ScopedInversion inverter(isCurrentlyEmitting);
  1191. detail::ReturnValueAggregator<R>::invokeAndAggregate(r, slots, args);
  1192. detail::disconnectPending(slots);
  1193. detail::connectPending(slots, pendingConnects);
  1194. return r;
  1195. }
  1196.  
  1197. void disconnect(R (*member)()) {
  1198. ScopedLock_ lock(slotsMutex);
  1199. detail::disconnect(slots, isCurrentlyEmitting, GCaller(member));
  1200. }
  1201.  
  1202. template <typename TObj>
  1203. void disconnect(TObj& obj, R (TObj::*member)()) {
  1204. ScopedLock_ lock(slotsMutex);
  1205. typedef typename MCaller<TObj,detail::NonConst>::type MCaller_;
  1206. detail::disconnect(slots, isCurrentlyEmitting, MCaller_(obj,member));
  1207. }
  1208.  
  1209. template <typename TObj>
  1210. void disconnect(TObj const& obj, R (TObj::*member)() const) {
  1211. ScopedLock_ lock(slotsMutex);
  1212. typedef typename MCaller<const TObj,detail::Const>::type MCaller_;
  1213. detail::disconnect(slots, isCurrentlyEmitting, MCaller_(obj,member));
  1214. }
  1215.  
  1216. void disconnectAll(){
  1217. ScopedLock_ lock(slotsMutex);
  1218. detail::disconnectAll(slots, isCurrentlyEmitting);
  1219. }
  1220.  
  1221. ~Signal(){ assert(isCurrentlyEmitting==false); disconnectAll(); } //upon returning from dtor object is invalid so a pending emit()-call would be invalid too!
  1222.  
  1223. private:
  1224. typedef typename detail::InvokableImpl<R>::template BoundFunction<void, void, void, void, void, detail::NonDefault> Args;
  1225. typedef typename detail::InvokableImpl<R>::template GlobalFunction<void, void, void, void, void, detail::NonDefault> GCaller;
  1226.  
  1227. template <typename TObj, typename Constness>
  1228. struct MCaller{ typedef typename detail::InvokableImpl<R>::template MemberFunction<TObj, Constness> type; };
  1229.  
  1230. typedef std::pair<detail::Invokable<R>*,detail::DisconnectionPending> Slot;
  1231. typedef typename detail::SlotContainer<Slot>::type Slots;
  1232.  
  1233. typedef detail::Mutex::type Mutex_;
  1234. typedef detail::ScopedLock::type ScopedLock_;
  1235.  
  1236. bool isCurrentlyEmitting = false;
  1237. Slots pendingConnects;
  1238. Slots slots;
  1239. Mutex_ slotsMutex;
  1240. };
  1241.  
  1242.  
  1243.  
  1244.  
  1245.  
  1246.  
  1247. } // namespace sisl
  1248.  
  1249.  
  1250. using namespace sisl;
  1251.  
  1252. struct TraficLight{
  1253.  
  1254. Signal<void()> green;
  1255. Signal<void()> red;
  1256.  
  1257. void switchToGreen(){
  1258. std::cout<<"===switching to green===\n";
  1259. green.emit();
  1260. }
  1261. void switchToRed(){
  1262. std::cout<<"===switching to red===\n";
  1263. red.emit();
  1264. }
  1265. };
  1266.  
  1267.  
  1268. struct Pedestrian{
  1269. void walk(){std::cout<<"Pedestrian walk\n";}
  1270. void wait(){std::cout<<"Pedestrian wait\n";}
  1271. };
  1272.  
  1273.  
  1274. int main()
  1275. {
  1276. //create instances
  1277. TraficLight tl;
  1278. Pedestrian p;
  1279.  
  1280. //link
  1281. tl.green.connect(p,&Pedestrian::wait);
  1282. tl.red.connect(p,&Pedestrian::walk);
  1283.  
  1284. //begin operation
  1285. tl.switchToRed();
  1286. tl.switchToGreen();
  1287.  
  1288. return 0;
  1289. }
  1290.  
  1291.  
Success #stdin #stdout 0s 16064KB
stdin
Standard input is empty
stdout
===switching to red===
Pedestrian walk
===switching to green===
Pedestrian wait