]> git.lyx.org Git - lyx.git/blob - boost/libs/signals/src/named_slot_map.cpp
update to boost 1.32.0
[lyx.git] / boost / libs / signals / src / named_slot_map.cpp
1 // Boost.Signals library
2
3 // Copyright Douglas Gregor 2001-2004. 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 #define BOOST_SIGNALS_SOURCE
11
12 #include <boost/signals/detail/named_slot_map.hpp>
13 #include <cassert>
14 #include <map>
15 #include <list>
16 #include <typeinfo>
17
18 namespace boost { namespace BOOST_SIGNALS_NAMESPACE { namespace detail {
19
20 typedef std::list<connection_slot_pair> group_list;
21 typedef group_list::iterator slot_pair_iterator;
22 typedef std::map<any, group_list, compare_type> slot_container_type;
23 typedef slot_container_type::iterator group_iterator;
24 typedef slot_container_type::const_iterator const_group_iterator;
25
26 class named_slot_map::impl
27 {
28 public:
29   impl(const compare_type& compare) : groups(compare)
30   {
31     clear();
32   }
33
34   void clear()
35   {
36     groups.clear();
37     groups[front_type()];
38     groups[back_type()];
39     back = groups.end();
40     --back;
41   }
42
43   slot_container_type groups;
44   group_iterator back;
45
46   bool empty(const_group_iterator group) const
47   {
48     return (group->second.empty() && group != groups.begin() && group != back);
49   }
50 };
51
52 class named_slot_map_iterator::impl
53 {
54 public:
55   impl() : slot_assigned(false) {}
56
57   impl(group_iterator group, group_iterator last_group)
58     : group(group), last_group(last_group), slot_assigned(false)
59   { init_next_group(); }
60
61   impl(group_iterator group, group_iterator last_group,
62        slot_pair_iterator slot_)
63     : group(group), last_group(last_group), slot_(slot_), slot_assigned(true)
64   { }
65
66   impl(const impl& other) 
67     : group(other.group), last_group(other.last_group), 
68       slot_assigned(other.slot_assigned)
69   {
70     if (slot_assigned) slot_ = other.slot_;
71   }
72
73   impl& operator=(const impl& other)
74   {
75     group = other.group;
76     last_group = other.last_group;
77     slot_assigned = other.slot_assigned;
78     if (slot_assigned) slot_ = other.slot_;
79     return *this;
80   }
81
82   void init_next_group()
83   {
84     while (group != last_group && group->second.empty()) ++group;
85     if (group != last_group) {
86       slot_ = group->second.begin();
87       slot_assigned = true;
88     }
89   }
90
91   group_iterator group;
92   group_iterator last_group;
93   slot_pair_iterator slot_;
94   bool slot_assigned;
95 };
96
97 named_slot_map_iterator::named_slot_map_iterator() {}
98
99 named_slot_map_iterator::named_slot_map_iterator(std::auto_ptr<impl> impl_)
100   : impl_(impl_) {}
101
102 named_slot_map_iterator
103   ::named_slot_map_iterator(const named_slot_map_iterator& other)
104 {
105   impl_.reset(new impl(*other.impl_));
106 }
107
108 named_slot_map_iterator::~named_slot_map_iterator() {}
109
110 named_slot_map_iterator&
111 named_slot_map_iterator::operator=(const named_slot_map_iterator& other)
112 {
113   if (impl_) *impl_ = *other.impl_;
114   else impl_.reset(new impl(*other.impl_));
115   return *this;
116 }
117
118 connection_slot_pair& named_slot_map_iterator::dereference() const
119 { return *impl_->slot_; }
120
121 void named_slot_map_iterator::increment()
122 {
123   ++impl_->slot_;
124   if (impl_->slot_ == impl_->group->second.end()) {
125     ++impl_->group;
126     impl_->init_next_group();
127   }
128 }
129
130 bool 
131 named_slot_map_iterator::equal(const named_slot_map_iterator& other) const
132 {
133   return (impl_->group == other.impl_->group
134           && (impl_->group == impl_->last_group
135               || impl_->slot_ == other.impl_->slot_));
136 }
137
138 #if BOOST_WORKAROUND(BOOST_MSVC, <= 0x1701)
139 void named_slot_map_iterator::decrement() { assert(false); }
140 void named_slot_map_iterator::advance(difference_type) { assert(false); }
141 #endif
142
143 named_slot_map::named_slot_map(const compare_type& compare)
144 {
145   impl_.reset(new impl(compare));
146 }
147
148 named_slot_map::~named_slot_map() {}
149
150 void named_slot_map::clear() { impl_->clear(); }
151
152 named_slot_map::iterator named_slot_map::begin()
153 {
154   typedef named_slot_map::iterator::impl iterator_impl;
155
156   std::auto_ptr<iterator_impl> 
157     it(new iterator_impl(impl_->groups.begin(),
158                          impl_->groups.end()));
159   return named_slot_map::iterator(it);
160 }
161
162 named_slot_map::iterator named_slot_map::end()
163 {
164   typedef named_slot_map::iterator::impl iterator_impl;
165
166   std::auto_ptr<iterator_impl> 
167     it(new iterator_impl(impl_->groups.end(),
168                          impl_->groups.end()));
169   return named_slot_map::iterator(it);
170 }
171
172 named_slot_map::iterator
173 named_slot_map::insert(const any& name, const connection& con, const any& slot,
174                        connect_position at)
175 {
176   group_iterator group;
177   if (name.empty()) {
178     switch (at) {
179     case at_front: group = impl_->groups.begin(); break;
180     case at_back: group = impl_->back; break;
181     }
182   } else {
183     group = impl_->groups.find(name);
184     if (group == impl_->groups.end()) {
185       slot_container_type::value_type v(name, group_list());
186       group = impl_->groups.insert(v).first;
187     }
188   }
189   typedef named_slot_map::iterator::impl iterator_impl;
190   std::auto_ptr<iterator_impl> it(new iterator_impl);
191   it->group = group;
192   it->last_group = impl_->groups.end();
193
194   switch (at) {
195   case at_back:
196     group->second.push_back(connection_slot_pair(con, slot));
197     it->slot_ = group->second.end();
198     it->slot_assigned = true;
199     --(it->slot_);
200     break;
201
202   case at_front:
203     group->second.push_front(connection_slot_pair(con, slot));
204     it->slot_ = group->second.begin();
205     it->slot_assigned = true;
206     break;
207   }
208   return iterator(it);
209 }
210
211 void named_slot_map::disconnect(const any& name)
212 {
213   group_iterator group = impl_->groups.find(name);
214   if (group != impl_->groups.end()) {
215     slot_pair_iterator i = group->second.begin();
216     while (i != group->second.end()) {
217       slot_pair_iterator next = i;
218       ++next;
219       i->first.disconnect();
220       i = next;
221     }
222     impl_->groups.erase(group);
223   }
224 }
225
226 void named_slot_map::erase(iterator pos)
227 {
228   // Erase the slot
229   pos.impl_->slot_->first.disconnect();
230   //  pos.impl_->group->second.erase(pos.impl_->slot_); ?
231 }
232
233 void named_slot_map::remove_disconnected_slots()
234 {
235   // Remove any disconnected slots
236   group_iterator g = impl_->groups.begin();
237   while (g != impl_->groups.end()) {
238     slot_pair_iterator s = g->second.begin();
239     while (s != g->second.end()) {
240       if (s->first.connected()) ++s;
241       else g->second.erase(s++);
242     }
243
244     // Clear out empty groups
245     if (impl_->empty(g)) impl_->groups.erase(g++);
246     else ++g;
247   }
248 }
249
250
251 } } }