1 // Boost.Signals library
2 
3 // Copyright Douglas Gregor 2001-2003. 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 
8 // For more information, see http://www.boost.org
9 
10 #include <boost/test/minimal.hpp>
11 #include <boost/signal.hpp>
12 #include <iostream>
13 #include <string>
14 
15 static boost::BOOST_SIGNALS_NAMESPACE::connection connections[5];
16 
17 static std::string test_output;
18 
19 struct remove_connection {
remove_connectionremove_connection20   explicit remove_connection(int v = 0, int i = -1) : value(v), idx(i) {}
21 
operator ()remove_connection22   void operator()() const {
23     if (idx >= 0)
24       connections[idx].disconnect();
25 
26     //return value;
27     std::cout << value << " ";
28 
29     test_output += static_cast<char>(value + '0');
30   }
31 
32   int value;
33   int idx;
34 };
35 
operator ==(const remove_connection & x,const remove_connection & y)36 bool operator==(const remove_connection& x, const remove_connection& y)
37 { return x.value == y.value && x.idx == y.idx; }
38 
39 static void
test_remove_self()40 test_remove_self()
41 {
42   boost::signal0<void> s0;
43 
44   connections[0] = s0.connect(remove_connection(0));
45   connections[1] = s0.connect(remove_connection(1));
46   connections[2] = s0.connect(remove_connection(2, 2));
47   connections[3] = s0.connect(remove_connection(3));
48 
49   std::cout << "Deleting 2" << std::endl;
50 
51   test_output = "";
52   s0(); std::cout << std::endl;
53   BOOST_CHECK(test_output == "0123");
54 
55   test_output = "";
56   s0(); std::cout << std::endl;
57   BOOST_CHECK(test_output == "013");
58 
59   s0.disconnect_all_slots();
60   BOOST_CHECK(s0.empty());
61 
62   connections[0] = s0.connect(remove_connection(0));
63   connections[1] = s0.connect(remove_connection(1));
64   connections[2] = s0.connect(remove_connection(2));
65   connections[3] = s0.connect(remove_connection(3, 3));
66 
67   std::cout << "Deleting 3" << std::endl;
68 
69   test_output = "";
70   s0(); std::cout << std::endl;
71   BOOST_CHECK(test_output == "0123");
72 
73   test_output = "";
74   s0(); std::cout << std::endl;
75   BOOST_CHECK(test_output == "012");
76 
77   s0.disconnect_all_slots();
78   BOOST_CHECK(s0.num_slots() == 0);
79 
80   connections[0] = s0.connect(remove_connection(0, 0));
81   connections[1] = s0.connect(remove_connection(1));
82   connections[2] = s0.connect(remove_connection(2));
83   connections[3] = s0.connect(remove_connection(3));
84 
85   std::cout << "Deleting 0" << std::endl;
86 
87   test_output = "";
88   s0(); std::cout << std::endl;
89   BOOST_CHECK(test_output == "0123");
90 
91   test_output = "";
92   s0(); std::cout << std::endl;
93   BOOST_CHECK(test_output == "123");
94 
95   std::cout << "Blocking 2" << std::endl;
96 
97   connections[2].block();
98   test_output = "";
99   s0(); std::cout << std::endl;
100   BOOST_CHECK(test_output == "13");
101 
102   std::cout << "Unblocking 2" << std::endl;
103 
104   connections[2].unblock();
105   test_output = "";
106   s0(); std::cout << std::endl;
107   BOOST_CHECK(test_output == "123");
108 
109   s0.disconnect_all_slots();
110   BOOST_CHECK(s0.empty());
111 
112   connections[0] = s0.connect(remove_connection(0, 0));
113   connections[1] = s0.connect(remove_connection(1, 1));
114   connections[2] = s0.connect(remove_connection(2, 2));
115   connections[3] = s0.connect(remove_connection(3, 3));
116 
117   std::cout << "Mass suicide" << std::endl;
118 
119   test_output = "";
120   s0(); std::cout << std::endl;
121   BOOST_CHECK(test_output == "0123");
122 
123   test_output = "";
124   s0(); std::cout << std::endl;
125   BOOST_CHECK(test_output == "");
126 }
127 
128 static void
test_remove_prior()129 test_remove_prior()
130 {
131   boost::signal0<void> s0;
132 
133   connections[0] = s0.connect(remove_connection(0));
134   connections[1] = s0.connect(remove_connection(1, 0));
135   connections[2] = s0.connect(remove_connection(2));
136   connections[3] = s0.connect(remove_connection(3));
137 
138   std::cout << "1 removes 0" << std::endl;
139 
140   test_output = "";
141   s0(); std::cout << std::endl;
142   BOOST_CHECK(test_output == "0123");
143 
144   test_output = "";
145   s0(); std::cout << std::endl;
146   BOOST_CHECK(test_output == "123");
147 
148   s0.disconnect_all_slots();
149   BOOST_CHECK(s0.empty());
150 
151   connections[0] = s0.connect(remove_connection(0));
152   connections[1] = s0.connect(remove_connection(1));
153   connections[2] = s0.connect(remove_connection(2));
154   connections[3] = s0.connect(remove_connection(3, 2));
155 
156   std::cout << "3 removes 2" << std::endl;
157 
158   test_output = "";
159   s0(); std::cout << std::endl;
160   BOOST_CHECK(test_output == "0123");
161 
162   test_output = "";
163   s0(); std::cout << std::endl;
164   BOOST_CHECK(test_output == "013");
165 }
166 
167 static void
test_remove_after()168 test_remove_after()
169 {
170   boost::signal0<void> s0;
171 
172   connections[0] = s0.connect(remove_connection(0, 1));
173   connections[1] = s0.connect(remove_connection(1));
174   connections[2] = s0.connect(remove_connection(2));
175   connections[3] = s0.connect(remove_connection(3));
176 
177   std::cout << "0 removes 1" << std::endl;
178 
179   test_output = "";
180   s0(); std::cout << std::endl;
181   BOOST_CHECK(test_output == "023");
182 
183   test_output = "";
184   s0(); std::cout << std::endl;
185   BOOST_CHECK(test_output == "023");
186 
187   s0.disconnect_all_slots();
188   BOOST_CHECK(s0.empty());
189 
190   connections[0] = s0.connect(remove_connection(0));
191   connections[1] = s0.connect(remove_connection(1, 3));
192   connections[2] = s0.connect(remove_connection(2));
193   connections[3] = s0.connect(remove_connection(3));
194 
195   std::cout << "1 removes 3" << std::endl;
196 
197   test_output = "";
198   s0(); std::cout << std::endl;
199   BOOST_CHECK(test_output == "012");
200 
201   test_output = "";
202   s0(); std::cout << std::endl;
203   BOOST_CHECK(test_output == "012");
204 }
205 
206 static void
test_bloodbath()207 test_bloodbath()
208 {
209   boost::signal0<void> s0;
210 
211   connections[0] = s0.connect(remove_connection(0, 1));
212   connections[1] = s0.connect(remove_connection(1, 1));
213   connections[2] = s0.connect(remove_connection(2, 0));
214   connections[3] = s0.connect(remove_connection(3, 2));
215 
216   std::cout << "0 removes 1, 2 removes 0, 3 removes 2" << std::endl;
217 
218   test_output = "";
219   s0(); std::cout << std::endl;
220   BOOST_CHECK(test_output == "023");
221 
222   test_output = "";
223   s0(); std::cout << std::endl;
224   BOOST_CHECK(test_output == "3");
225 }
226 
227 static void
test_disconnect_equal()228 test_disconnect_equal()
229 {
230   boost::signal0<void> s0;
231 
232   connections[0] = s0.connect(remove_connection(0));
233   connections[1] = s0.connect(remove_connection(1));
234   connections[2] = s0.connect(remove_connection(2));
235   connections[3] = s0.connect(remove_connection(3));
236 
237   std::cout << "Deleting 2" << std::endl;
238 
239   test_output = "";
240   s0(); std::cout << std::endl;
241   BOOST_CHECK(test_output == "0123");
242 
243 #if BOOST_WORKAROUND(BOOST_MSVC, <= 1300)
244   connections[2].disconnect();
245 #else
246   s0.disconnect(remove_connection(2));
247 #endif
248 
249   test_output = "";
250   s0(); std::cout << std::endl;
251   BOOST_CHECK(test_output == "013");
252 }
253 
test_main(int,char * [])254 int test_main(int, char* [])
255 {
256   test_remove_self();
257   test_remove_prior();
258   test_remove_after();
259   test_bloodbath();
260   test_disconnect_equal();
261   return 0;
262 }
263