]> git.tdb.fi Git - ext/sigc++-2.0.git/blob - tests/test_disconnect.cc
Adjust the name of the library to match upstream
[ext/sigc++-2.0.git] / tests / test_disconnect.cc
1 /* Copyright 2002, The libsigc++ Development Team
2  *  Assigned to public domain.  Use as you wish without restriction.
3  */
4
5 #include "testutilities.h"
6 #include <sigc++/trackable.h>
7 #include <sigc++/signal.h>
8 #include <sigc++/connection.h>
9 #include <sigc++/adaptors/compose.h>
10 #include <sigc++/functors/ptr_fun.h>
11 #include <sigc++/functors/mem_fun.h>
12 #include <sstream>
13 #include <cstdlib>
14
15 //The Tru64 compiler seems to need this to avoid an unresolved symbol
16 //See bug #161503
17 #include <new>
18
19 namespace
20 {
21 std::ostringstream result_stream;
22
23 int foo(int i)
24 {
25   result_stream << "foo(" << i << ") ";
26   return 1;
27 }
28
29 int bar(double i)
30 {
31   result_stream << "bar(" << i << ") ";
32   return 1;
33 }
34
35 struct A : public sigc::trackable
36 {
37   int foo(int i)
38   {
39     result_stream << "A::foo(" << i << ") ";
40     return 1;
41   }
42 };
43
44 void good_bye_world()
45 {
46   result_stream << "Good bye world!";
47 }
48
49 struct B : public sigc::trackable
50 {
51   B()
52   {
53     sig.connect(sigc::mem_fun(*this, &B::destroy));
54     sig.connect(sigc::mem_fun(*this, &B::boom));
55     sig.connect(sigc::ptr_fun(&good_bye_world));
56   }
57
58   void destroy()   // Calling destroy() during signal emission seems weird!
59   {                // However, if this works, anything will work!
60     delete this;   // valgrind reports a small memory leak, that's all.
61   }
62
63   void boom()
64   {
65     result_stream << "boom!";
66   }
67
68   void emit()
69   {
70     sig.emit();
71   }
72
73   sigc::signal<void> sig;
74 };
75
76 } // end anonymous namespace
77
78 int main(int argc, char* argv[])
79 {
80   auto util = TestUtilities::get_instance();
81
82   if (!util->check_command_args(argc, argv))
83     return util->get_result_and_delete_instance() ? EXIT_SUCCESS : EXIT_FAILURE;
84
85   sigc::signal<int, int> sig;
86   sigc::signal<int, int>::iterator confoo;
87   sigc::signal<int, int>::iterator conbar;
88   sigc::connection cona;  // connection objects are safe to use beyond the life time of a signal.
89
90   {
91     A a;
92     sig.connect(sigc::mem_fun1(a, &A::foo));
93     confoo = sig.connect(sigc::ptr_fun1(&foo));
94     conbar = sig.connect(sigc::ptr_fun1(&bar));
95     result_stream << "sig is connected to A::foo, foo, bar (size=" << sig.size() << "): ";
96     sig(1);
97     util->check_result(result_stream,
98       "sig is connected to A::foo, foo, bar (size=3): A::foo(1) foo(1) bar(1) ");
99   }                     // auto disconnection! iterators stay valid after disconnections.
100
101   result_stream << "sig is connected to foo, bar (size=" << sig.size() << "): ";
102   sig(2);
103   util->check_result(result_stream, "sig is connected to foo, bar (size=2): foo(2) bar(2) ");
104
105   A a;                  // iterators stay valid after further connections.
106   cona = sig.slots().insert(conbar, sigc::mem_fun1(a, &A::foo));
107   result_stream << "sig is connected to foo, A::foo, bar (size=" << sig.size() << "): ";
108   sig(3);
109   util->check_result(result_stream,
110     "sig is connected to foo, A::foo, bar (size=3): foo(3) A::foo(3) bar(3) ");
111
112   conbar->disconnect(); // manual disconnection
113   result_stream << "sig is connected to foo, A::foo (size=" << sig.size() << "): ";
114   sig(4);
115   util->check_result(result_stream, "sig is connected to foo, A::foo (size=2): foo(4) A::foo(4) ");
116
117   confoo->disconnect(); // manual disconnection
118   result_stream << "sig is connected to A::foo (size=" << sig.size() << "): ";
119   sig(5);
120   util->check_result(result_stream, "sig is connected to A::foo (size=1): A::foo(5) ");
121
122   cona.disconnect();    // manual disconnection
123   result_stream << "sig is empty (size=" << sig.size() << "): ";
124   sig(6);
125   util->check_result(result_stream, "sig is empty (size=0): ");
126
127   cona.disconnect();    // already disconnected -> legal with connection objects, however, nothing happens ...
128
129   {
130     A a2;
131     sig.connect(sigc::compose(sigc::mem_fun(a2, &A::foo), &foo));
132     result_stream << "sig is connected to compose(A::foo, foo) (size=" << sig.size() << "): ";
133     sig(7);
134     util->check_result(result_stream, "sig is connected to compose(A::foo, foo) (size=1): foo(7) A::foo(1) ");
135   }
136   result_stream << "sig is empty (size=" << sig.size() << "): ";
137   sig(8);
138   util->check_result(result_stream, "sig is empty (size=0): ");
139
140   { // A slot# within a slot
141     A a2;
142     sigc::slot1<int, int> setter = sigc::mem_fun(a2, &A::foo);
143     sig.connect(sigc::compose(setter, &foo));
144     result_stream << "sig is connected to compose(slot1(A::foo), foo) (size=" << sig.size() << "): ";
145     sig(9);
146     util->check_result(result_stream, "sig is connected to compose(slot1(A::foo), foo) (size=1): foo(9) A::foo(1) ");
147   }
148   result_stream << "sig is empty (size=" << sig.size() << "): ";
149   sig(10);
150   util->check_result(result_stream, "sig is empty (size=0): ");
151
152   { // A slot within a slot
153     A a2;
154     sigc::slot<int, int> setter = sigc::mem_fun(a2, &A::foo);
155     sig.connect(sigc::compose(setter, &foo));
156     result_stream << "sig is connected to compose(slot(A::foo), foo) (size=" << sig.size() << "): ";
157     sig(11);
158     util->check_result(result_stream, "sig is connected to compose(slot(A::foo), foo) (size=1): foo(11) A::foo(1) ");
159   }
160   result_stream << "sig is empty (size=" << sig.size() << "): ";
161   sig(12);
162   util->check_result(result_stream, "sig is empty (size=0): ");
163
164   result_stream << "deleting a signal during emission... ";
165   auto b = new B;
166   b->emit();
167   util->check_result(result_stream, "deleting a signal during emission... Good bye world!");
168
169   return util->get_result_and_delete_instance() ? EXIT_SUCCESS : EXIT_FAILURE;
170 }