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