]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
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 | #ifndef BOOST_SIGNALS_NAMED_SLOT_MAP_HPP | |
11 | #define BOOST_SIGNALS_NAMED_SLOT_MAP_HPP | |
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/shared_ptr.hpp> | |
17 | #include <boost/function/function2.hpp> | |
18 | #include <boost/iterator/iterator_facade.hpp> | |
19 | #include <map> | |
20 | #include <memory> | |
21 | #include <utility> | |
22 | ||
23 | namespace boost { namespace BOOST_SIGNALS_NAMESPACE { | |
24 | ||
25 | enum connect_position { at_back, at_front }; | |
26 | ||
27 | namespace detail { | |
28 | ||
29 | class stored_group | |
30 | { | |
31 | public: | |
32 | enum storage_kind { sk_empty, sk_front, sk_back, sk_group }; | |
33 | ||
34 | stored_group(storage_kind p_kind = sk_empty) : kind(p_kind), group() { } | |
35 | ||
36 | template<typename T> | |
37 | stored_group(const T& p_group) : kind(sk_group), group(new T(p_group)) { } | |
38 | ||
39 | bool is_front() const { return kind == sk_front; } | |
40 | bool is_back() const { return kind == sk_back; } | |
41 | bool empty() const { return kind == sk_empty; } | |
42 | ||
43 | void* get() const { return group.get(); } | |
44 | ||
45 | private: | |
46 | storage_kind kind; | |
47 | shared_ptr<void> group; | |
48 | }; | |
49 | ||
50 | typedef function2<bool, stored_group, stored_group> compare_type; | |
51 | ||
52 | // This function object bridges from a pair of any objects that hold | |
53 | // values of type Key to the underlying function object that compares | |
54 | // values of type Key. | |
55 | template<typename Compare, typename Key> | |
56 | class group_bridge_compare { | |
57 | public: | |
58 | typedef bool result_type; | |
59 | typedef const stored_group& first_argument_type; | |
60 | typedef const stored_group& second_argument_type; | |
61 | ||
62 | group_bridge_compare(const Compare& c) : comp(c) | |
63 | { } | |
64 | ||
65 | bool operator()(const stored_group& k1, const stored_group& k2) const | |
66 | { | |
67 | if (k1.is_front()) return !k2.is_front(); | |
68 | if (k1.is_back()) return false; | |
69 | if (k2.is_front()) return false; | |
70 | if (k2.is_back()) return true; | |
71 | ||
72 | // Neither is empty, so compare their values to order them | |
73 | return comp(*static_cast<Key*>(k1.get()), *static_cast<Key*>(k2.get())); | |
74 | } | |
75 | ||
76 | private: | |
77 | Compare comp; | |
78 | }; | |
79 | ||
80 | class BOOST_SIGNALS_DECL named_slot_map_iterator : | |
81 | public iterator_facade<named_slot_map_iterator, | |
82 | connection_slot_pair, | |
83 | forward_traversal_tag> | |
84 | { | |
85 | typedef std::list<connection_slot_pair> group_list; | |
86 | typedef group_list::iterator slot_pair_iterator; | |
87 | typedef std::map<stored_group, group_list, compare_type> slot_container_type; | |
88 | typedef slot_container_type::iterator group_iterator; | |
89 | typedef slot_container_type::const_iterator const_group_iterator; | |
90 | ||
91 | typedef iterator_facade<named_slot_map_iterator, | |
92 | connection_slot_pair, | |
93 | forward_traversal_tag> inherited; | |
94 | public: | |
95 | named_slot_map_iterator() : slot_assigned(false) | |
96 | { } | |
97 | named_slot_map_iterator(const named_slot_map_iterator& other) | |
98 | : group(other.group), last_group(other.last_group), | |
99 | slot_assigned(other.slot_assigned) | |
100 | { | |
101 | if (slot_assigned) slot_ = other.slot_; | |
102 | } | |
103 | named_slot_map_iterator& operator=(const named_slot_map_iterator& other) | |
104 | { | |
105 | slot_assigned = other.slot_assigned; | |
106 | group = other.group; | |
107 | last_group = other.last_group; | |
108 | if (slot_assigned) slot_ = other.slot_; | |
109 | return *this; | |
110 | } | |
111 | connection_slot_pair& dereference() const | |
112 | { | |
113 | return *slot_; | |
114 | } | |
115 | void increment() | |
116 | { | |
117 | ++slot_; | |
118 | if (slot_ == group->second.end()) { | |
119 | ++group; | |
120 | init_next_group(); | |
121 | } | |
122 | } | |
123 | bool equal(const named_slot_map_iterator& other) const { | |
124 | return (group == other.group | |
125 | && (group == last_group | |
126 | || slot_ == other.slot_)); | |
127 | } | |
128 | ||
129 | #if BOOST_WORKAROUND(_MSC_VER, <= 1900) | |
130 | void decrement(); | |
131 | void advance(difference_type); | |
132 | #endif | |
133 | ||
134 | private: | |
135 | named_slot_map_iterator(group_iterator giter, group_iterator last) : | |
136 | group(giter), last_group(last), slot_assigned(false) | |
137 | { init_next_group(); } | |
138 | named_slot_map_iterator(group_iterator giter, group_iterator last, | |
139 | slot_pair_iterator slot) : | |
140 | group(giter), last_group(last), slot_(slot), slot_assigned(true) | |
141 | { } | |
142 | ||
143 | void init_next_group() | |
144 | { | |
145 | while (group != last_group && group->second.empty()) ++group; | |
146 | if (group != last_group) { | |
147 | slot_ = group->second.begin(); | |
148 | slot_assigned = true; | |
149 | } | |
150 | } | |
151 | ||
152 | group_iterator group; | |
153 | group_iterator last_group; | |
154 | slot_pair_iterator slot_; | |
155 | bool slot_assigned; | |
156 | ||
157 | friend class named_slot_map; | |
158 | }; | |
159 | ||
160 | class BOOST_SIGNALS_DECL named_slot_map | |
161 | { | |
162 | public: | |
163 | typedef named_slot_map_iterator iterator; | |
164 | ||
165 | named_slot_map(const compare_type& compare); | |
166 | ||
167 | void clear(); | |
168 | iterator begin(); | |
169 | iterator end(); | |
170 | iterator insert(const stored_group& name, const connection& con, | |
171 | const any& slot, connect_position at); | |
172 | void disconnect(const stored_group& name); | |
173 | void erase(iterator pos); | |
174 | void remove_disconnected_slots(); | |
175 | ||
176 | private: | |
177 | typedef std::list<connection_slot_pair> group_list; | |
178 | typedef std::map<stored_group, group_list, compare_type> slot_container_type; | |
179 | typedef slot_container_type::iterator group_iterator; | |
180 | typedef slot_container_type::const_iterator const_group_iterator; | |
181 | ||
182 | bool empty(const_group_iterator group) const | |
183 | { | |
184 | return (group->second.empty() && group != groups.begin() && group != back); | |
185 | } | |
186 | slot_container_type groups; | |
187 | group_iterator back; | |
188 | }; | |
189 | ||
190 | } } } | |
191 | ||
192 | #endif // BOOST_SIGNALS_NAMED_SLOT_MAP_HPP |