765df1290520db0c4b493896d14e30fee77b2a9d
[libcds.git] / cds / intrusive / details / node_traits.h
1 /*
2     This file is a part of libcds - Concurrent Data Structures library
3
4     (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2016
5
6     Source code repo: http://github.com/khizmax/libcds/
7     Download: http://sourceforge.net/projects/libcds/files/
8     
9     Redistribution and use in source and binary forms, with or without
10     modification, are permitted provided that the following conditions are met:
11
12     * Redistributions of source code must retain the above copyright notice, this
13       list of conditions and the following disclaimer.
14
15     * Redistributions in binary form must reproduce the above copyright notice,
16       this list of conditions and the following disclaimer in the documentation
17       and/or other materials provided with the distribution.
18
19     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20     AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21     IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22     DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
23     FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24     DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25     SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26     CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27     OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28     OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.     
29 */
30
31 #ifndef CDSLIB_INTRUSIVE_DETAILS_NODE_TRAITS_H
32 #define CDSLIB_INTRUSIVE_DETAILS_NODE_TRAITS_H
33
34 #include <cds/intrusive/options.h>
35
36 namespace cds { namespace intrusive {
37
38 #ifdef CDS_DOXYGEN_INVOKED
39     /// Container's node traits
40     /** @ingroup cds_intrusive_helper
41         This traits is intended for converting between type \p T of value stored in the intrusive container
42         and container's node type \p NodeType.
43
44         There are separate specializations for each \p Hook type.
45     */
46     template <typename T, typename NodeType, typename Hook>
47     struct node_traits
48     {
49         typedef T        value_type ;  ///< Value type
50         typedef NodeType node_type  ;  ///< Node type
51
52         /// Convert value reference to node pointer
53         static node_type * to_node_ptr( value_type& v );
54
55         /// Convert value pointer to node pointer
56         static node_type * to_node_ptr( value_type * v );
57
58         /// Convert value reference to node pointer (const version)
59         static const node_type * to_node_ptr( value_type const& v );
60
61         /// Convert value pointer to node pointer (const version)
62         static const node_type * to_node_ptr( value_type const * v );
63
64         /// Convert node refernce to value pointer
65         static value_type * to_value_ptr( node_type&  n );
66
67         /// Convert node pointer to value pointer
68         static value_type * to_value_ptr( node_type *  n );
69
70         /// Convert node reference to value pointer (const version)
71         static const value_type * to_value_ptr( node_type const & n );
72
73         /// Convert node pointer to value pointer (const version)
74         static const value_type * to_value_ptr( node_type const * n );
75     };
76
77 #else
78     template <typename T, typename NodeType, class Hook, typename HookType>
79     struct node_traits;
80 #endif
81
82     //@cond
83     template <typename T, typename NodeType, class Hook>
84     struct node_traits<T, NodeType, Hook, opt::base_hook_tag>
85     {
86         typedef T        value_type;
87         typedef NodeType node_type;
88
89         static node_type * to_node_ptr( value_type& v )
90         {
91             return static_cast<node_type *>( &v );
92         }
93         static node_type * to_node_ptr( value_type * v )
94         {
95             return v ? static_cast<node_type *>(v) : nullptr;
96         }
97         static const node_type * to_node_ptr( const value_type& v )
98         {
99             return static_cast<const node_type *>( &v );
100         }
101         static const node_type * to_node_ptr( const value_type * v )
102         {
103             return v ? static_cast<const node_type *>(v) : nullptr;
104         }
105         static value_type * to_value_ptr( node_type&  n )
106         {
107             return static_cast<value_type *>( &n );
108         }
109         static value_type * to_value_ptr( node_type *  n )
110         {
111             return n ? static_cast<value_type *>(n) : nullptr;
112         }
113         static const value_type * to_value_ptr( const node_type& n )
114         {
115             return static_cast<const value_type *>( &n );
116         }
117         static const value_type * to_value_ptr( const node_type * n )
118         {
119             return n ? static_cast<const value_type *>(n) : nullptr;
120         }
121     };
122
123     template <typename T, typename NodeType, class Hook>
124     struct node_traits<T, NodeType, Hook, opt::member_hook_tag>
125     {
126         typedef T        value_type;
127         typedef NodeType node_type;
128
129         static node_type * to_node_ptr( value_type& v )
130         {
131             return reinterpret_cast<node_type *>( reinterpret_cast<char *>(&v) + Hook::c_nMemberOffset );
132         }
133         static node_type * to_node_ptr( value_type * v )
134         {
135             return v ? to_node_ptr( *v ) : nullptr;
136         }
137         static const node_type * to_node_ptr( const value_type& v )
138         {
139             return reinterpret_cast<const node_type *>( reinterpret_cast<const char *>(&v) + Hook::c_nMemberOffset );
140         }
141         static const node_type * to_node_ptr( const value_type * v )
142         {
143             return v ? to_node_ptr( *v ) : nullptr;
144         }
145         static value_type * to_value_ptr( node_type& n )
146         {
147             return reinterpret_cast<value_type *>( reinterpret_cast<char *>(&n) - Hook::c_nMemberOffset );
148         }
149         static value_type * to_value_ptr( node_type * n )
150         {
151             return n ? to_value_ptr( *n ) : nullptr;
152         }
153         static const value_type * to_value_ptr( const node_type& n )
154         {
155             return reinterpret_cast<const value_type *>( reinterpret_cast<const char *>(&n) - Hook::c_nMemberOffset );
156         }
157         static const value_type * to_value_ptr( const node_type * n )
158         {
159             return n ? to_value_ptr( *n ) : nullptr;
160         }
161     };
162
163     template <typename T, typename NodeType, class Hook>
164     struct node_traits<T, NodeType, Hook, opt::traits_hook_tag>: public Hook::node_traits
165     {};
166     //@endcond
167
168     /// Node traits selector metafunction
169     /** @ingroup cds_intrusive_helper
170         The metafunction selects appropriate \ref node_traits specialization based on value type \p T, node type \p NodeType, and hook type \p Hook.
171     */
172     template <typename T, typename NodeType, class Hook>
173     struct get_node_traits
174     {
175         //@cond
176         typedef node_traits<T, NodeType, Hook, typename Hook::hook_type> type;
177         //@endcond
178     };
179
180     //@cond
181     /// Functor converting container's node type to value type
182     //TODO: delete
183     template <class Container>
184     struct node_to_value {
185         typename Container::value_type * operator()( typename Container::node_type * p ) const
186         {
187             typedef typename Container::node_traits node_traits;
188             return node_traits::to_value_ptr( p );
189         }
190     };
191     //@endcond
192
193 }} // namespace cds::intrusuve
194
195 #endif  // #ifndef CDSLIB_INTRUSIVE_DETAILS_NODE_TRAITS_H