deletion_test.cpp 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297
  1. // Boost.Signals2 library
  2. // Copyright Douglas Gregor 2001-2003.
  3. // Use, modification and
  4. // distribution is subject to the Boost Software License, Version
  5. // 1.0. (See accompanying file LICENSE_1_0.txt or copy at
  6. // http://www.boost.org/LICENSE_1_0.txt)
  7. // For more information, see http://www.boost.org
  8. #include <boost/test/minimal.hpp>
  9. #include <boost/signals2.hpp>
  10. #include <iostream>
  11. #include <string>
  12. static boost::signals2::connection connections[5];
  13. static std::string test_output;
  14. struct remove_connection {
  15. explicit remove_connection(int v = 0, int i = -1) : value(v), idx(i) {}
  16. void operator()() const {
  17. if (idx >= 0)
  18. connections[idx].disconnect();
  19. //return value;
  20. std::cout << value << " ";
  21. test_output += static_cast<char>(value + '0');
  22. }
  23. int value;
  24. int idx;
  25. };
  26. bool operator==(const remove_connection& x, const remove_connection& y)
  27. { return x.value == y.value && x.idx == y.idx; }
  28. static void
  29. test_remove_self()
  30. {
  31. boost::signals2::signal<void ()> s0;
  32. connections[0] = s0.connect(remove_connection(0));
  33. connections[1] = s0.connect(remove_connection(1));
  34. connections[2] = s0.connect(remove_connection(2, 2));
  35. connections[3] = s0.connect(remove_connection(3));
  36. std::cout << "Deleting 2" << std::endl;
  37. test_output = "";
  38. s0(); std::cout << std::endl;
  39. BOOST_CHECK(test_output == "0123");
  40. test_output = "";
  41. s0(); std::cout << std::endl;
  42. BOOST_CHECK(test_output == "013");
  43. s0.disconnect_all_slots();
  44. BOOST_CHECK(s0.empty());
  45. connections[0] = s0.connect(remove_connection(0));
  46. connections[1] = s0.connect(remove_connection(1));
  47. connections[2] = s0.connect(remove_connection(2));
  48. connections[3] = s0.connect(remove_connection(3, 3));
  49. std::cout << "Deleting 3" << std::endl;
  50. test_output = "";
  51. s0(); std::cout << std::endl;
  52. BOOST_CHECK(test_output == "0123");
  53. test_output = "";
  54. s0(); std::cout << std::endl;
  55. BOOST_CHECK(test_output == "012");
  56. s0.disconnect_all_slots();
  57. BOOST_CHECK(s0.num_slots() == 0);
  58. connections[0] = s0.connect(remove_connection(0, 0));
  59. connections[1] = s0.connect(remove_connection(1));
  60. connections[2] = s0.connect(remove_connection(2));
  61. connections[3] = s0.connect(remove_connection(3));
  62. std::cout << "Deleting 0" << std::endl;
  63. test_output = "";
  64. s0(); std::cout << std::endl;
  65. BOOST_CHECK(test_output == "0123");
  66. test_output = "";
  67. s0(); std::cout << std::endl;
  68. BOOST_CHECK(test_output == "123");
  69. s0.disconnect_all_slots();
  70. BOOST_CHECK(s0.empty());
  71. connections[0] = s0.connect(remove_connection(0, 0));
  72. connections[1] = s0.connect(remove_connection(1, 1));
  73. connections[2] = s0.connect(remove_connection(2, 2));
  74. connections[3] = s0.connect(remove_connection(3, 3));
  75. std::cout << "Mass suicide" << std::endl;
  76. test_output = "";
  77. s0(); std::cout << std::endl;
  78. BOOST_CHECK(test_output == "0123");
  79. test_output = "";
  80. s0(); std::cout << std::endl;
  81. BOOST_CHECK(test_output == "");
  82. }
  83. static void
  84. test_remove_prior()
  85. {
  86. boost::signals2::signal<void ()> s0;
  87. connections[0] = s0.connect(remove_connection(0));
  88. connections[1] = s0.connect(remove_connection(1, 0));
  89. connections[2] = s0.connect(remove_connection(2));
  90. connections[3] = s0.connect(remove_connection(3));
  91. std::cout << "1 removes 0" << std::endl;
  92. test_output = "";
  93. s0(); std::cout << std::endl;
  94. BOOST_CHECK(test_output == "0123");
  95. test_output = "";
  96. s0(); std::cout << std::endl;
  97. BOOST_CHECK(test_output == "123");
  98. s0.disconnect_all_slots();
  99. BOOST_CHECK(s0.empty());
  100. connections[0] = s0.connect(remove_connection(0));
  101. connections[1] = s0.connect(remove_connection(1));
  102. connections[2] = s0.connect(remove_connection(2));
  103. connections[3] = s0.connect(remove_connection(3, 2));
  104. std::cout << "3 removes 2" << std::endl;
  105. test_output = "";
  106. s0(); std::cout << std::endl;
  107. BOOST_CHECK(test_output == "0123");
  108. test_output = "";
  109. s0(); std::cout << std::endl;
  110. BOOST_CHECK(test_output == "013");
  111. }
  112. static void
  113. test_remove_after()
  114. {
  115. boost::signals2::signal<void ()> s0;
  116. connections[0] = s0.connect(remove_connection(0, 1));
  117. connections[1] = s0.connect(remove_connection(1));
  118. connections[2] = s0.connect(remove_connection(2));
  119. connections[3] = s0.connect(remove_connection(3));
  120. std::cout << "0 removes 1" << std::endl;
  121. test_output = "";
  122. s0(); std::cout << std::endl;
  123. BOOST_CHECK(test_output == "023");
  124. test_output = "";
  125. s0(); std::cout << std::endl;
  126. BOOST_CHECK(test_output == "023");
  127. s0.disconnect_all_slots();
  128. BOOST_CHECK(s0.empty());
  129. connections[0] = s0.connect(remove_connection(0));
  130. connections[1] = s0.connect(remove_connection(1, 3));
  131. connections[2] = s0.connect(remove_connection(2));
  132. connections[3] = s0.connect(remove_connection(3));
  133. std::cout << "1 removes 3" << std::endl;
  134. test_output = "";
  135. s0(); std::cout << std::endl;
  136. BOOST_CHECK(test_output == "012");
  137. test_output = "";
  138. s0(); std::cout << std::endl;
  139. BOOST_CHECK(test_output == "012");
  140. }
  141. static void
  142. test_bloodbath()
  143. {
  144. boost::signals2::signal<void ()> s0;
  145. connections[0] = s0.connect(remove_connection(0, 1));
  146. connections[1] = s0.connect(remove_connection(1, 1));
  147. connections[2] = s0.connect(remove_connection(2, 0));
  148. connections[3] = s0.connect(remove_connection(3, 2));
  149. std::cout << "0 removes 1, 2 removes 0, 3 removes 2" << std::endl;
  150. test_output = "";
  151. s0(); std::cout << std::endl;
  152. BOOST_CHECK(test_output == "023");
  153. test_output = "";
  154. s0(); std::cout << std::endl;
  155. BOOST_CHECK(test_output == "3");
  156. }
  157. static void
  158. test_disconnect_equal()
  159. {
  160. boost::signals2::signal<void ()> s0;
  161. connections[0] = s0.connect(remove_connection(0));
  162. connections[1] = s0.connect(remove_connection(1));
  163. connections[2] = s0.connect(remove_connection(2));
  164. connections[3] = s0.connect(remove_connection(3));
  165. std::cout << "Deleting 2" << std::endl;
  166. test_output = "";
  167. s0(); std::cout << std::endl;
  168. BOOST_CHECK(test_output == "0123");
  169. #if BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
  170. connections[2].disconnect();
  171. #else
  172. s0.disconnect(remove_connection(2));
  173. #endif
  174. test_output = "";
  175. s0(); std::cout << std::endl;
  176. BOOST_CHECK(test_output == "013");
  177. }
  178. struct signal_deletion_tester
  179. {
  180. public:
  181. signal_deletion_tester() {
  182. b_has_run = false;
  183. sig = new boost::signals2::signal<void(void)>();
  184. connection0 = sig->connect(0, boost::bind(&signal_deletion_tester::a, this));
  185. connection1 = sig->connect(1, boost::bind(&signal_deletion_tester::b, this));
  186. }
  187. ~signal_deletion_tester()
  188. {
  189. if(sig != 0)
  190. delete sig;
  191. }
  192. void a()
  193. {
  194. if(sig != 0)
  195. delete sig;
  196. sig = 0;
  197. }
  198. void b()
  199. {
  200. b_has_run = true;
  201. }
  202. boost::signals2::signal<void(void)> *sig;
  203. bool b_has_run;
  204. boost::signals2::connection connection0;
  205. boost::signals2::connection connection1;
  206. };
  207. // If a signal is deleted mid-invocation, the invocation in progress
  208. // should complete normally. Once all invocations complete, all
  209. // slots which were connected to the deleted signal should be in the
  210. // disconnected state.
  211. static void test_signal_deletion()
  212. {
  213. signal_deletion_tester tester;
  214. (*tester.sig)();
  215. BOOST_CHECK(tester.b_has_run);
  216. BOOST_CHECK(tester.connection0.connected() == false);
  217. BOOST_CHECK(tester.connection1.connected() == false);
  218. }
  219. int test_main(int, char* [])
  220. {
  221. test_remove_self();
  222. test_remove_prior();
  223. test_remove_after();
  224. test_bloodbath();
  225. test_disconnect_equal();
  226. test_signal_deletion();
  227. return 0;
  228. }