1 | // Boost.Signals2 library |
2 | |
3 | // Copyright Douglas Gregor 2001-2006. |
4 | // Copyright Frank Mori Hess 2009. |
5 | // Use, modification and |
6 | // distribution is subject to the Boost Software License, Version |
7 | // 1.0. (See accompanying file LICENSE_1_0.txt or copy at |
8 | // http://www.boost.org/LICENSE_1_0.txt) |
9 | |
10 | // For more information, see http://www.boost.org |
11 | |
12 | #include <boost/signals2/signal.hpp> |
13 | #include <boost/signals2/trackable.hpp> |
14 | #define BOOST_TEST_MODULE trackable_test |
15 | #include <boost/test/included/unit_test.hpp> |
16 | #include <boost/bind/bind.hpp> |
17 | #include <boost/core/ref.hpp> |
18 | #include <boost/weak_ptr.hpp> |
19 | |
20 | using namespace boost::placeholders; |
21 | |
22 | struct short_lived : public boost::signals2::trackable { |
23 | ~short_lived() {} |
24 | }; |
25 | |
26 | struct swallow { |
27 | typedef int result_type; |
28 | template<typename T> int operator()(const T*, int i) { return i; } |
29 | template<typename T> int operator()(T &, int i) { return i; } |
30 | template<typename T> int operator()(boost::weak_ptr<T>, int i) { return i; } |
31 | }; |
32 | |
33 | template<typename T> |
34 | struct max_or_default { |
35 | typedef T result_type; |
36 | |
37 | template<typename InputIterator> |
38 | T operator()(InputIterator first, InputIterator last) const |
39 | { |
40 | if (first == last) |
41 | return T(); |
42 | |
43 | T max = *first++; |
44 | for (; first != last; ++first) |
45 | max = (*first > max)? *first : max; |
46 | |
47 | return max; |
48 | } |
49 | }; |
50 | |
51 | struct self_deleting : public boost::signals2::trackable { |
52 | void delete_myself(boost::signals2::connection connection) |
53 | { |
54 | BOOST_CHECK(connection.connected()); |
55 | delete this; |
56 | BOOST_CHECK(connection.connected() == false); |
57 | } |
58 | }; |
59 | |
60 | // test that slot assocated with signals2::trackable |
61 | // gets disconnected immediately upon deletion of the |
62 | // signals2::trackable, even when a signal invocation |
63 | // is in progress. |
64 | void test_immediate_disconnect_on_delete() |
65 | { |
66 | boost::signals2::signal<void () > sig; |
67 | self_deleting *obj = new self_deleting(); |
68 | sig.connect_extended(slot: boost::bind(f: &self_deleting::delete_myself, a1: obj, a2: _1)); |
69 | sig(); |
70 | } |
71 | |
72 | BOOST_AUTO_TEST_CASE(test_main) |
73 | { |
74 | typedef boost::signals2::signal<int (int), max_or_default<int> > sig_type; |
75 | sig_type s1; |
76 | |
77 | // Test auto-disconnection |
78 | BOOST_CHECK(s1(5) == 0); |
79 | { |
80 | short_lived shorty; |
81 | s1.connect(slot: boost::bind<int>(f: swallow(), a1: &shorty, a2: _1)); |
82 | BOOST_CHECK(s1(5) == 5); |
83 | } |
84 | BOOST_CHECK(s1(5) == 0); |
85 | // Test auto-disconnection of trackable inside reference_wrapper |
86 | { |
87 | short_lived shorty; |
88 | s1.connect(slot: boost::bind<int>(f: swallow(), a1: boost::ref(t&: shorty), a2: _1)); |
89 | BOOST_CHECK(s1(5) == 5); |
90 | } |
91 | BOOST_CHECK(s1(5) == 0); |
92 | |
93 | // Test multiple arg slot constructor |
94 | { |
95 | short_lived shorty; |
96 | s1.connect(slot: sig_type::slot_type(swallow(), &shorty, _1)); |
97 | BOOST_CHECK(s1(5) == 5); |
98 | } |
99 | BOOST_CHECK(s1(5) == 0); |
100 | |
101 | // Test auto-disconnection of slot before signal connection |
102 | { |
103 | short_lived* shorty = new short_lived(); |
104 | |
105 | sig_type::slot_type slot(boost::bind<int>(f: swallow(), a1: shorty, a2: _1)); |
106 | delete shorty; |
107 | |
108 | BOOST_CHECK(s1(5) == 0); |
109 | } |
110 | |
111 | test_immediate_disconnect_on_delete(); |
112 | } |
113 | |