1 | ///////////////////////////////////////////////////////////////////////////// |
2 | // |
3 | // (C) Copyright Olaf Krzikalla 2004-2006. |
4 | // (C) Copyright Ion Gaztanaga 2006-2013 |
5 | // |
6 | // Distributed under the Boost Software License, Version 1.0. |
7 | // (See accompanying file LICENSE_1_0.txt or copy at |
8 | // http://www.boost.org/LICENSE_1_0.txt) |
9 | // |
10 | // See http://www.boost.org/libs/intrusive for documentation. |
11 | // |
12 | ///////////////////////////////////////////////////////////////////////////// |
13 | |
14 | #ifndef BOOST_INTRUSIVE_LIST_HOOK_HPP |
15 | #define BOOST_INTRUSIVE_LIST_HOOK_HPP |
16 | |
17 | #include <boost/intrusive/detail/config_begin.hpp> |
18 | #include <boost/intrusive/intrusive_fwd.hpp> |
19 | |
20 | #include <boost/intrusive/detail/list_node.hpp> |
21 | #include <boost/intrusive/circular_list_algorithms.hpp> |
22 | #include <boost/intrusive/options.hpp> |
23 | #include <boost/intrusive/detail/generic_hook.hpp> |
24 | |
25 | #if defined(BOOST_HAS_PRAGMA_ONCE) |
26 | # pragma once |
27 | #endif |
28 | |
29 | |
30 | namespace boost { |
31 | namespace intrusive { |
32 | |
33 | //! Helper metafunction to define a \c \c list_base_hook that yields to the same |
34 | //! type when the same options (either explicitly or implicitly) are used. |
35 | #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) |
36 | template<class ...Options> |
37 | #else |
38 | template<class O1 = void, class O2 = void, class O3 = void> |
39 | #endif |
40 | struct make_list_base_hook |
41 | { |
42 | /// @cond |
43 | typedef typename pack_options |
44 | < hook_defaults, |
45 | #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) |
46 | O1, O2, O3 |
47 | #else |
48 | Options... |
49 | #endif |
50 | >::type packed_options; |
51 | |
52 | typedef generic_hook |
53 | < circular_list_algorithms<list_node_traits<typename packed_options::void_pointer> > |
54 | , typename packed_options::tag |
55 | , packed_options::link_mode |
56 | , ListBaseHookId |
57 | > implementation_defined; |
58 | /// @endcond |
59 | typedef implementation_defined type; |
60 | }; |
61 | |
62 | //! Derive a class from this hook in order to store objects of that class |
63 | //! in an list. |
64 | //! |
65 | //! The hook admits the following options: \c tag<>, \c void_pointer<> and |
66 | //! \c link_mode<>. |
67 | //! |
68 | //! \c tag<> defines a tag to identify the node. |
69 | //! The same tag value can be used in different classes, but if a class is |
70 | //! derived from more than one \c list_base_hook, then each \c list_base_hook needs its |
71 | //! unique tag. |
72 | //! |
73 | //! \c link_mode<> will specify the linking mode of the hook (\c normal_link, |
74 | //! \c auto_unlink or \c safe_link). |
75 | //! |
76 | //! \c void_pointer<> is the pointer type that will be used internally in the hook |
77 | //! and the container configured to use this hook. |
78 | #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) |
79 | template<class ...Options> |
80 | #else |
81 | template<class O1, class O2, class O3> |
82 | #endif |
83 | class list_base_hook |
84 | : public make_list_base_hook |
85 | #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) |
86 | <O1, O2, O3> |
87 | #else |
88 | <Options...> |
89 | #endif |
90 | ::type |
91 | { |
92 | #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) |
93 | public: |
94 | //! <b>Effects</b>: If link_mode is \c auto_unlink or \c safe_link |
95 | //! initializes the node to an unlinked state. |
96 | //! |
97 | //! <b>Throws</b>: Nothing. |
98 | list_base_hook(); |
99 | |
100 | //! <b>Effects</b>: If link_mode is \c auto_unlink or \c safe_link |
101 | //! initializes the node to an unlinked state. The argument is ignored. |
102 | //! |
103 | //! <b>Throws</b>: Nothing. |
104 | //! |
105 | //! <b>Rationale</b>: Providing a copy-constructor |
106 | //! makes classes using the hook STL-compliant without forcing the |
107 | //! user to do some additional work. \c swap can be used to emulate |
108 | //! move-semantics. |
109 | list_base_hook(const list_base_hook& ); |
110 | |
111 | //! <b>Effects</b>: Empty function. The argument is ignored. |
112 | //! |
113 | //! <b>Throws</b>: Nothing. |
114 | //! |
115 | //! <b>Rationale</b>: Providing an assignment operator |
116 | //! makes classes using the hook STL-compliant without forcing the |
117 | //! user to do some additional work. \c swap can be used to emulate |
118 | //! move-semantics. |
119 | list_base_hook& operator=(const list_base_hook& ); |
120 | |
121 | //! <b>Effects</b>: If link_mode is \c normal_link, the destructor does |
122 | //! nothing (ie. no code is generated). If link_mode is \c safe_link and the |
123 | //! object is stored in an list an assertion is raised. If link_mode is |
124 | //! \c auto_unlink and \c is_linked() is true, the node is unlinked. |
125 | //! |
126 | //! <b>Throws</b>: Nothing. |
127 | ~list_base_hook(); |
128 | |
129 | //! <b>Effects</b>: Swapping two nodes swaps the position of the elements |
130 | //! related to those nodes in one or two containers. That is, if the node |
131 | //! this is part of the element e1, the node x is part of the element e2 |
132 | //! and both elements are included in the containers s1 and s2, then after |
133 | //! the swap-operation e1 is in s2 at the position of e2 and e2 is in s1 |
134 | //! at the position of e1. If one element is not in a container, then |
135 | //! after the swap-operation the other element is not in a container. |
136 | //! Iterators to e1 and e2 related to those nodes are invalidated. |
137 | //! |
138 | //! <b>Complexity</b>: Constant |
139 | //! |
140 | //! <b>Throws</b>: Nothing. |
141 | void swap_nodes(list_base_hook &other); |
142 | |
143 | //! <b>Precondition</b>: link_mode must be \c safe_link or \c auto_unlink. |
144 | //! |
145 | //! <b>Returns</b>: true, if the node belongs to a container, false |
146 | //! otherwise. This function can be used to test whether \c list::iterator_to |
147 | //! will return a valid iterator. |
148 | //! |
149 | //! <b>Complexity</b>: Constant |
150 | bool is_linked() const; |
151 | |
152 | //! <b>Effects</b>: Removes the node if it's inserted in a container. |
153 | //! This function is only allowed if link_mode is \c auto_unlink. |
154 | //! |
155 | //! <b>Throws</b>: Nothing. |
156 | void unlink(); |
157 | #endif |
158 | }; |
159 | |
160 | //! Helper metafunction to define a \c \c list_member_hook that yields to the same |
161 | //! type when the same options (either explicitly or implicitly) are used. |
162 | #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) |
163 | template<class ...Options> |
164 | #else |
165 | template<class O1 = void, class O2 = void, class O3 = void> |
166 | #endif |
167 | struct make_list_member_hook |
168 | { |
169 | /// @cond |
170 | typedef typename pack_options |
171 | < hook_defaults, |
172 | #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) |
173 | O1, O2, O3 |
174 | #else |
175 | Options... |
176 | #endif |
177 | >::type packed_options; |
178 | |
179 | typedef generic_hook |
180 | < circular_list_algorithms<list_node_traits<typename packed_options::void_pointer> > |
181 | , member_tag |
182 | , packed_options::link_mode |
183 | , NoBaseHookId |
184 | > implementation_defined; |
185 | /// @endcond |
186 | typedef implementation_defined type; |
187 | }; |
188 | |
189 | //! Store this hook in a class to be inserted |
190 | //! in an list. |
191 | //! |
192 | //! The hook admits the following options: \c void_pointer<> and |
193 | //! \c link_mode<>. |
194 | //! |
195 | //! \c link_mode<> will specify the linking mode of the hook (\c normal_link, |
196 | //! \c auto_unlink or \c safe_link). |
197 | //! |
198 | //! \c void_pointer<> is the pointer type that will be used internally in the hook |
199 | //! and the container configured to use this hook. |
200 | #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) || defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) |
201 | template<class ...Options> |
202 | #else |
203 | template<class O1, class O2, class O3> |
204 | #endif |
205 | class list_member_hook |
206 | : public make_list_member_hook |
207 | #if !defined(BOOST_INTRUSIVE_VARIADIC_TEMPLATES) |
208 | <O1, O2, O3> |
209 | #else |
210 | <Options...> |
211 | #endif |
212 | ::type |
213 | { |
214 | #if defined(BOOST_INTRUSIVE_DOXYGEN_INVOKED) |
215 | public: |
216 | //! <b>Effects</b>: If link_mode is \c auto_unlink or \c safe_link |
217 | //! initializes the node to an unlinked state. |
218 | //! |
219 | //! <b>Throws</b>: Nothing. |
220 | list_member_hook(); |
221 | |
222 | //! <b>Effects</b>: If link_mode is \c auto_unlink or \c safe_link |
223 | //! initializes the node to an unlinked state. The argument is ignored. |
224 | //! |
225 | //! <b>Throws</b>: Nothing. |
226 | //! |
227 | //! <b>Rationale</b>: Providing a copy-constructor |
228 | //! makes classes using the hook STL-compliant without forcing the |
229 | //! user to do some additional work. \c swap can be used to emulate |
230 | //! move-semantics. |
231 | list_member_hook(const list_member_hook& ); |
232 | |
233 | //! <b>Effects</b>: Empty function. The argument is ignored. |
234 | //! |
235 | //! <b>Throws</b>: Nothing. |
236 | //! |
237 | //! <b>Rationale</b>: Providing an assignment operator |
238 | //! makes classes using the hook STL-compliant without forcing the |
239 | //! user to do some additional work. \c swap can be used to emulate |
240 | //! move-semantics. |
241 | list_member_hook& operator=(const list_member_hook& ); |
242 | |
243 | //! <b>Effects</b>: If link_mode is \c normal_link, the destructor does |
244 | //! nothing (ie. no code is generated). If link_mode is \c safe_link and the |
245 | //! object is stored in an list an assertion is raised. If link_mode is |
246 | //! \c auto_unlink and \c is_linked() is true, the node is unlinked. |
247 | //! |
248 | //! <b>Throws</b>: Nothing. |
249 | ~list_member_hook(); |
250 | |
251 | //! <b>Effects</b>: Swapping two nodes swaps the position of the elements |
252 | //! related to those nodes in one or two containers. That is, if the node |
253 | //! this is part of the element e1, the node x is part of the element e2 |
254 | //! and both elements are included in the containers s1 and s2, then after |
255 | //! the swap-operation e1 is in s2 at the position of e2 and e2 is in s1 |
256 | //! at the position of e1. If one element is not in a container, then |
257 | //! after the swap-operation the other element is not in a container. |
258 | //! Iterators to e1 and e2 related to those nodes are invalidated. |
259 | //! |
260 | //! <b>Complexity</b>: Constant |
261 | //! |
262 | //! <b>Throws</b>: Nothing. |
263 | void swap_nodes(list_member_hook &other); |
264 | |
265 | //! <b>Precondition</b>: link_mode must be \c safe_link or \c auto_unlink. |
266 | //! |
267 | //! <b>Returns</b>: true, if the node belongs to a container, false |
268 | //! otherwise. This function can be used to test whether \c list::iterator_to |
269 | //! will return a valid iterator. |
270 | //! |
271 | //! <b>Complexity</b>: Constant |
272 | bool is_linked() const; |
273 | |
274 | //! <b>Effects</b>: Removes the node if it's inserted in a container. |
275 | //! This function is only allowed if link_mode is \c auto_unlink. |
276 | //! |
277 | //! <b>Throws</b>: Nothing. |
278 | void unlink(); |
279 | #endif |
280 | }; |
281 | |
282 | } //namespace intrusive |
283 | } //namespace boost |
284 | |
285 | #include <boost/intrusive/detail/config_end.hpp> |
286 | |
287 | #endif //BOOST_INTRUSIVE_LIST_HOOK_HPP |
288 | |