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