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