]> git.lyx.org Git - lyx.git/blob - boost/boost/signals/detail/signal_base.hpp
update boost to pre-1.30.0
[lyx.git] / boost / boost / signals / detail / signal_base.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_SIGNAL_BASE_HEADER
17 #define BOOST_SIGNALS_SIGNAL_BASE_HEADER
18
19 #ifdef BOOST_SIGNALS_IN_LIBRARY_SOURCE
20 #  define BOOST_FUNCTION_SILENT_DEPRECATED
21 #endif
22
23 #include <boost/signals/detail/signals_common.hpp>
24 #include <boost/signals/connection.hpp>
25 #include <boost/signals/trackable.hpp>
26 #include <boost/smart_ptr.hpp>
27 #include <boost/any.hpp>
28 #include <boost/utility.hpp>
29 #include <boost/function/function2.hpp>
30 #include <map>
31 #include <utility>
32 #include <vector>
33
34 namespace boost {
35   namespace BOOST_SIGNALS_NAMESPACE {
36     namespace detail {
37       // Forward declaration for the mapping from slot names to connections
38       class named_slot_map;
39
40       // This function object bridges from a pair of any objects that hold
41       // values of type Key to the underlying function object that compares
42       // values of type Key.
43       template<typename Compare, typename Key>
44       class any_bridge_compare {
45       public:
46         typedef bool result_type;
47         typedef const any& first_argument_type;
48         typedef const any& second_argument_type;
49
50         any_bridge_compare(const Compare& c) : comp(c) {}
51
52         bool operator()(const any& k1, const any& k2) const
53         {
54           // if k1 is empty, then it precedes nothing
55           if (k1.empty())
56             return false;
57
58           // if k2 is empty, then k1 must precede it
59           if (k2.empty())
60             return true;
61
62           // Neither is empty, so compare their values to order them
63           // The strange */& is so that we will get a reference to the
64           // value stored in the any object instead of a copy
65           return comp(*any_cast<Key>(&k1), *any_cast<Key>(&k2));
66         }
67
68       private:
69         Compare comp;
70       };
71
72       // Must be constructed before calling the slots, because it safely
73       // manages call depth
74       class BOOST_SIGNALS_DECL call_notification {
75       public:
76         call_notification(const shared_ptr<signal_base_impl>&);
77         ~call_notification();
78         
79         shared_ptr<signal_base_impl> impl;
80       };
81         
82       // Implementation of base class for all signals. It handles the 
83       // management of the underlying slot lists.
84       class BOOST_SIGNALS_DECL signal_base_impl {
85       public:
86         friend class call_notification;
87
88         typedef function2<bool, any, any> compare_type;
89
90         // Make sure that an exception does not cause the "clearing" flag to
91         // remain set
92         class temporarily_set_clearing {
93         public:
94           temporarily_set_clearing(signal_base_impl* b) : base(b)
95           {
96             base->flags.clearing = true;
97           }
98
99           ~temporarily_set_clearing()
100           {
101             base->flags.clearing = false;
102           }
103
104         private:
105           signal_base_impl* base;
106         };
107
108         friend class temporarily_set_clearing;
109
110         signal_base_impl(const compare_type&);
111         ~signal_base_impl();
112
113         // Disconnect all slots connected to this signal
114         void disconnect_all_slots();
115
116         // Are there any connected slots?
117         bool empty() const;
118
119         // Disconnect all slots in the given group
120         void disconnect(const any&);
121
122         // We're being notified that a slot has disconnected
123         static void slot_disconnected(void* obj, void* data);
124
125         connection connect_slot(const any& slot,
126                                 const any& name,
127                                 const std::vector<const trackable*>&);
128
129       private:
130         // Remove all of the slots that have been marked "disconnected"
131         void remove_disconnected_slots() const;
132
133       public:
134         // Our call depth when invoking slots (> 1 when we have a loop)
135         mutable int call_depth;
136         
137         struct {
138           // True if some slots have disconnected, but we were not able to
139           // remove them from the list of slots because there are valid 
140           // iterators into the slot list
141           mutable bool delayed_disconnect:1;
142           
143           // True if we are disconnecting all disconnected slots
144           bool clearing:1;
145         } flags;
146         
147         // Slots
148         typedef std::multimap<any, connection_slot_pair, compare_type>
149           slot_container_type;
150         typedef slot_container_type::iterator slot_iterator;
151         typedef slot_container_type::value_type stored_slot_type;
152         mutable slot_container_type slots_;
153       };
154
155       class BOOST_SIGNALS_DECL signal_base : public noncopyable {
156       public:
157         typedef signal_base_impl::compare_type compare_type;
158
159         friend class call_notification;
160
161         signal_base(const compare_type& comp) : impl()
162         {
163           impl.reset(new signal_base_impl(comp));
164         }
165
166         ~signal_base();
167
168       public:
169         // Disconnect all slots connected to this signal
170         void disconnect_all_slots() { impl->disconnect_all_slots(); }
171
172         // Are there any connected slots?
173         bool empty() const { return impl->empty(); }
174        
175       protected:
176         connection connect_slot(const any& slot,
177                                 const any& name,
178                                 const std::vector<const trackable*>& bound)
179         {
180           return impl->connect_slot(slot, name, bound);
181         }
182
183         typedef signal_base_impl::slot_iterator slot_iterator;
184         typedef signal_base_impl::stored_slot_type stored_slot_type;
185
186         shared_ptr<signal_base_impl> impl;
187       };
188     } // end namespace detail
189   } // end namespace BOOST_SIGNALS_NAMESPACE
190 } // end namespace boost
191
192 #endif // BOOST_SIGNALS_SIGNAL_BASE_HEADER