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/ref.hpp>
18 #include <boost/weak_ptr.hpp>
19
20 using namespace boost::placeholders;
21
22 struct short_lived : public boost::signals2::trackable {
~short_livedshort_lived23 ~short_lived() {}
24 };
25
26 struct swallow {
27 typedef int result_type;
operator ()swallow28 template<typename T> int operator()(const T*, int i) { return i; }
operator ()swallow29 template<typename T> int operator()(T &, int i) { return i; }
operator ()swallow30 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>
operator ()max_or_default38 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 {
delete_myselfself_deleting52 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.
test_immediate_disconnect_on_delete()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(boost::bind(&self_deleting::delete_myself, obj, _1));
69 sig();
70 }
71
BOOST_AUTO_TEST_CASE(test_main)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(boost::bind<int>(swallow(), &shorty, _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(boost::bind<int>(swallow(), boost::ref(shorty), _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(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>(swallow(), shorty, _1));
106 delete shorty;
107
108 BOOST_CHECK(s1(5) == 0);
109 }
110
111 test_immediate_disconnect_on_delete();
112 }
113