]> git.lyx.org Git - lyx.git/blob - boost/boost/signals/connection.hpp
complie fix
[lyx.git] / boost / boost / signals / connection.hpp
1 // Boost.Signals library
2 //
3 // Copyright (C) 2001-2002 Doug Gregor (gregod@cs.rpi.edu)
4 //
5 // Permission to copy, use, sell and distribute this software is granted
6 // provided this copyright notice appears in all copies.
7 // Permission to modify the code and to distribute modified code is granted
8 // provided this copyright notice appears in all copies, and a notice
9 // that the code was modified is included with the copyright notice.
10 //
11 // This software is provided "as is" without express or implied warranty,
12 // and with no claim as to its suitability for any purpose.
13  
14 // For more information, see http://www.boost.org
15
16 #ifndef BOOST_SIGNALS_CONNECTION_HPP
17 #define BOOST_SIGNALS_CONNECTION_HPP
18
19 #include <boost/signals/detail/signals_common.hpp>
20 #include <boost/smart_ptr.hpp>
21 #include <boost/operators.hpp>
22 #include <boost/any.hpp>
23 #include <list>
24 #include <cassert>
25 #include <utility>
26
27 namespace boost {
28   namespace BOOST_SIGNALS_NAMESPACE {
29     class trackable;
30
31     namespace detail {
32       // Represents an object that has been bound as part of a slot, and how
33       // to notify that object of a disconnect
34       struct bound_object {
35         void* obj;
36         void* data;
37         void (*disconnect)(void*, void*);
38
39         bool operator==(const bound_object& other) const
40           { return obj == other.obj && data == other.data; }
41         bool operator<(const bound_object& other) const 
42           { return obj < other.obj; }
43       };
44       
45       // Describes the connection between a signal and the objects that are
46       // bound for a specific slot. Enables notification of the signal and the
47       // slots when a disconnect is requested.
48       struct basic_connection {
49         void* signal;
50         void* signal_data;
51         void (*signal_disconnect)(void*, void*);
52         
53         std::list<bound_object> bound_objects;
54       };
55     } // end namespace detail
56
57     // The user may freely pass around the "connection" object and terminate
58     // the connection at any time using disconnect().
59     class connection : 
60       private less_than_comparable1<connection>,
61       private equality_comparable1<connection>
62     {
63     public:
64       connection();
65       connection(const connection&);
66       ~connection();
67
68       // Disconnect the signal and slot, if they are connected
69       void disconnect() const;
70
71       // Returns true if the signal and slot are connected
72       bool connected() const { return con.get() && con->signal_disconnect; }
73
74       // Comparison of connections
75       inline bool operator==(const connection& other) const;
76       inline bool operator<(const connection& other) const;
77
78       // Connection assignment
79       connection& operator=(const connection& other) ;
80
81       // Swap connections
82       inline void swap(connection& other);
83
84     public: // TBD: CHANGE THIS
85       // Set whether this connection object is controlling or not
86       void set_controlling() { controlling_connection = true; }
87
88     private:
89       friend class detail::signal_base_impl;
90       friend class detail::slot_base;
91       friend class trackable;
92
93       // Reset this connection to refer to a different actual connection
94       void reset(BOOST_SIGNALS_NAMESPACE::detail::basic_connection*);
95
96       // Add a bound object to this connection (not for users)
97       void add_bound_object(const BOOST_SIGNALS_NAMESPACE::detail::bound_object& b);
98
99       friend class BOOST_SIGNALS_NAMESPACE::detail::bound_objects_visitor;
100
101       // Pointer to the actual contents of the connection
102       shared_ptr<BOOST_SIGNALS_NAMESPACE::detail::basic_connection> con;
103
104       // True if the destruction of this connection object should disconnect
105       bool controlling_connection;
106     };
107
108     // Similar to connection, but will disconnect the connection when it is
109     // destroyed unless release() has been called.
110     class scoped_connection : public connection {
111     public:
112       scoped_connection() : connection(), released(false) {}
113       scoped_connection(const connection&);
114       scoped_connection(const scoped_connection&);
115       ~scoped_connection();
116
117       connection release();
118
119       inline void swap(scoped_connection&);
120
121       scoped_connection& operator=(const connection&);
122       scoped_connection& operator=(const scoped_connection&);
123
124     private:
125       bool released;
126     };
127
128     inline connection::connection() :
129       con(), controlling_connection(false)
130     {
131     }
132
133     inline connection::connection(const connection& other) :
134       con(other.con), controlling_connection(other.controlling_connection) 
135     {
136     }
137
138     inline connection::~connection()
139     {
140       if (controlling_connection) {
141         disconnect();
142       }
143     }
144
145     inline void 
146     connection::reset(BOOST_SIGNALS_NAMESPACE::detail::basic_connection* new_con)
147     {
148       con.reset(new_con);
149     }
150
151     inline void 
152     connection::add_bound_object(const BOOST_SIGNALS_NAMESPACE::detail::bound_object& b)
153     {
154       assert(con.get() != 0);
155       con->bound_objects.push_back(b);
156     }
157
158     inline bool connection::operator==(const connection& other) const
159     {
160       return con.get() == other.con.get();
161     }
162
163     inline bool connection::operator<(const connection& other) const
164     {
165       return con.get() < other.con.get();
166     }
167
168     inline connection& connection::operator=(const connection& other)
169     { 
170       connection(other).swap(*this);
171       return *this;
172     }
173
174     inline void connection::swap(connection& other)
175     {
176       this->con.swap(other.con);
177       std::swap(this->controlling_connection, other.controlling_connection);
178     }
179
180     inline void swap(connection& c1, connection& c2)
181     {
182       c1.swap(c2);
183     }
184
185     inline scoped_connection::scoped_connection(const connection& other) :
186       connection(other),
187       released(false)
188     {
189     }
190
191     inline 
192     scoped_connection::scoped_connection(const scoped_connection& other) :
193       connection(other),
194       released(other.released)
195     {
196     }
197
198     inline scoped_connection::~scoped_connection()
199     {
200       if (!released) {
201         this->disconnect();
202       }
203     }
204
205     inline connection scoped_connection::release()
206     {
207       released = true;
208       return *this;
209     }
210
211     inline void scoped_connection::swap(scoped_connection& other)
212     {
213       this->connection::swap(other);
214       bool other_released = other.released;
215       other.released = this->released;
216       this->released = other_released;
217     }
218
219     inline void swap(scoped_connection& c1, scoped_connection& c2)
220     {
221       c1.swap(c2);
222     }
223
224     inline scoped_connection& 
225     scoped_connection::operator=(const connection& other)
226     {
227       scoped_connection(other).swap(*this);
228       return *this;
229     }
230
231     inline scoped_connection& 
232     scoped_connection::operator=(const scoped_connection& other)
233     {
234       scoped_connection(other).swap(*this);
235       return *this;
236     }
237
238     namespace detail {
239       struct connection_slot_pair {
240         connection first;
241         any second;
242
243         connection_slot_pair() {}
244
245         connection_slot_pair(const connection& c, const any& a) 
246           : first(c), second(a) 
247         {
248         }
249
250         // Dummys to allow explicit instantiation to work
251         bool operator==(const connection_slot_pair&) const { return false; }
252         bool operator<(const connection_slot_pair&) const { return false;} 
253       };
254       
255       // Determines if the underlying connection is disconnected
256       struct is_disconnected {
257         typedef std::pair<const any, connection_slot_pair> argument_type;
258         typedef bool result_type;
259
260         inline bool operator()(const argument_type& c) const
261         {
262           return !c.second.first.connected();
263         }
264       };
265
266       // Autodisconnects the bound object when it is destroyed unless the
267       // release method is invoked.
268       class auto_disconnect_bound_object {
269       public:
270         auto_disconnect_bound_object(const bound_object& b) : 
271           binding(b), auto_disconnect(true)
272         {
273         }
274
275         ~auto_disconnect_bound_object()
276         {
277           if (auto_disconnect)
278             binding.disconnect(binding.obj, binding.data);
279         }
280
281         void release() { auto_disconnect = false; }
282
283       private:
284         bound_object binding;
285         bool auto_disconnect;
286       };
287     } // end namespace detail
288   } // end namespace BOOST_SIGNALS_NAMESPACE
289 } // end namespace boost
290
291 #endif // BOOST_SIGNALS_CONNECTION_HPP