1 // Boost.Signals library
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)
8 // For more information, see http://www.boost.org
10 #define BOOST_SIGNALS_SOURCE
12 #include <boost/signals/detail/named_slot_map.hpp>
18 namespace boost { namespace BOOST_SIGNALS_NAMESPACE { namespace detail {
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;
26 class named_slot_map::impl
29 impl(const compare_type& compare) : groups(compare)
43 slot_container_type groups;
46 bool empty(const_group_iterator group) const
48 return (group->second.empty() && group != groups.begin() && group != back);
52 class named_slot_map_iterator::impl
55 impl() : slot_assigned(false) {}
57 impl(group_iterator group, group_iterator last_group)
58 : group(group), last_group(last_group), slot_assigned(false)
59 { init_next_group(); }
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)
66 impl(const impl& other)
67 : group(other.group), last_group(other.last_group),
68 slot_assigned(other.slot_assigned)
70 if (slot_assigned) slot_ = other.slot_;
73 impl& operator=(const impl& other)
76 last_group = other.last_group;
77 slot_assigned = other.slot_assigned;
78 if (slot_assigned) slot_ = other.slot_;
82 void init_next_group()
84 while (group != last_group && group->second.empty()) ++group;
85 if (group != last_group) {
86 slot_ = group->second.begin();
92 group_iterator last_group;
93 slot_pair_iterator slot_;
97 named_slot_map_iterator::named_slot_map_iterator() {}
99 named_slot_map_iterator::named_slot_map_iterator(std::auto_ptr<impl> impl_)
102 named_slot_map_iterator
103 ::named_slot_map_iterator(const named_slot_map_iterator& other)
105 impl_.reset(new impl(*other.impl_));
108 named_slot_map_iterator::~named_slot_map_iterator() {}
110 named_slot_map_iterator&
111 named_slot_map_iterator::operator=(const named_slot_map_iterator& other)
113 if (impl_) *impl_ = *other.impl_;
114 else impl_.reset(new impl(*other.impl_));
118 connection_slot_pair& named_slot_map_iterator::dereference() const
119 { return *impl_->slot_; }
121 void named_slot_map_iterator::increment()
124 if (impl_->slot_ == impl_->group->second.end()) {
126 impl_->init_next_group();
131 named_slot_map_iterator::equal(const named_slot_map_iterator& other) const
133 return (impl_->group == other.impl_->group
134 && (impl_->group == impl_->last_group
135 || impl_->slot_ == other.impl_->slot_));
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); }
143 named_slot_map::named_slot_map(const compare_type& compare)
145 impl_.reset(new impl(compare));
148 named_slot_map::~named_slot_map() {}
150 void named_slot_map::clear() { impl_->clear(); }
152 named_slot_map::iterator named_slot_map::begin()
154 typedef named_slot_map::iterator::impl iterator_impl;
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);
162 named_slot_map::iterator named_slot_map::end()
164 typedef named_slot_map::iterator::impl iterator_impl;
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);
172 named_slot_map::iterator
173 named_slot_map::insert(const any& name, const connection& con, const any& slot,
176 group_iterator group;
179 case at_front: group = impl_->groups.begin(); break;
180 case at_back: group = impl_->back; break;
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;
189 typedef named_slot_map::iterator::impl iterator_impl;
190 std::auto_ptr<iterator_impl> it(new iterator_impl);
192 it->last_group = impl_->groups.end();
196 group->second.push_back(connection_slot_pair(con, slot));
197 it->slot_ = group->second.end();
198 it->slot_assigned = true;
203 group->second.push_front(connection_slot_pair(con, slot));
204 it->slot_ = group->second.begin();
205 it->slot_assigned = true;
211 void named_slot_map::disconnect(const any& name)
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;
219 i->first.disconnect();
222 impl_->groups.erase(group);
226 void named_slot_map::erase(iterator pos)
229 pos.impl_->slot_->first.disconnect();
230 // pos.impl_->group->second.erase(pos.impl_->slot_); ?
233 void named_slot_map::remove_disconnected_slots()
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++);
244 // Clear out empty groups
245 if (impl_->empty(g)) impl_->groups.erase(g++);