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