Changed: use padding option instead of alignment one
[libcds.git] / cds / intrusive / details / single_link_struct.h
1 //$$CDS-header$$
2
3 #ifndef CDSLIB_INTRUSIVE_DETAILS_SINGLE_LINK_STRUCT_H
4 #define CDSLIB_INTRUSIVE_DETAILS_SINGLE_LINK_STRUCT_H
5
6 #include <cds/intrusive/details/base.h>
7 #include <cds/gc/default_gc.h>
8 #include <cds/algo/atomic.h>
9
10 namespace cds { namespace intrusive {
11
12     /// Definitions common for single-linked data structures
13     /** @ingroup cds_intrusive_helper
14     */
15     namespace single_link {
16
17         /// Container's node
18         /**
19             Template parameters:
20             - GC - garbage collector used
21             - Tag - a tag used to distinguish between different implementation
22         */
23         template <class GC, typename Tag = opt::none>
24         struct node
25         {
26             typedef GC              gc  ;   ///< Garbage collector
27             typedef Tag             tag ;   ///< tag
28
29             typedef typename gc::template atomic_ref<node>    atomic_node_ptr    ;    ///< atomic pointer
30
31             /// Rebind node for other template parameters
32             template <class GC2, typename Tag2 = tag>
33             struct rebind {
34                 typedef node<GC2, Tag2>  other ;    ///< Rebinding result
35             };
36
37             atomic_node_ptr m_pNext ; ///< pointer to the next node in the container
38
39             node() CDS_NOEXCEPT
40             {
41                 m_pNext.store( nullptr, atomics::memory_order_release );
42             }
43         };
44
45         //@cond
46         struct default_hook {
47             typedef cds::gc::default_gc gc;
48             typedef opt::none           tag;
49         };
50         //@endcond
51
52         //@cond
53         template < typename HookType, typename... Options>
54         struct hook
55         {
56             typedef typename opt::make_options< default_hook, Options...>::type  options;
57             typedef typename options::gc    gc;
58             typedef typename options::tag   tag;
59             typedef node<gc, tag> node_type;
60             typedef HookType      hook_type;
61         };
62         //@endcond
63
64         /// Base hook
65         /**
66             \p Options are:
67             - opt::gc - garbage collector used.
68             - opt::tag - tag
69         */
70         template < typename... Options >
71         struct base_hook: public hook< opt::base_hook_tag, Options... >
72         {};
73
74         /// Member hook
75         /**
76             \p MemberOffset defines offset in bytes of \ref node member into your structure.
77             Use \p offsetof macro to define \p MemberOffset
78
79             \p Options are:
80             - opt::gc - garbage collector used.
81             - opt::tag - tag
82         */
83         template < size_t MemberOffset, typename... Options >
84         struct member_hook: public hook< opt::member_hook_tag, Options... >
85         {
86             //@cond
87             static const size_t c_nMemberOffset = MemberOffset;
88             //@endcond
89         };
90
91         /// Traits hook
92         /**
93             \p NodeTraits defines type traits for node.
94             See \ref node_traits for \p NodeTraits interface description
95
96             \p Options are:
97             - opt::gc - garbage collector used.
98             - opt::tag - tag
99         */
100         template <typename NodeTraits, typename... Options >
101         struct traits_hook: public hook< opt::traits_hook_tag, Options... >
102         {
103             //@cond
104             typedef NodeTraits node_traits;
105             //@endcond
106         };
107
108         /// Check link
109         template <typename Node>
110         struct link_checker {
111             //@cond
112             typedef Node node_type;
113             //@endcond
114
115             /// Checks if the link field of node \p pNode is \p nullptr
116             /**
117                 An asserting is generated if \p pNode link field is not \p nullptr
118             */
119             static void is_empty( const node_type * pNode )
120             {
121                 assert( pNode->m_pNext.load( atomics::memory_order_relaxed ) == nullptr );
122                 CDS_UNUSED( pNode );
123             }
124         };
125
126         //@cond
127         template <class GC, typename Node, opt::link_check_type LinkType >
128         struct link_checker_selector;
129
130         template <typename GC, typename Node>
131         struct link_checker_selector< GC, Node, opt::never_check_link >
132         {
133             typedef intrusive::opt::v::empty_link_checker<Node>  type;
134         };
135
136         template <typename GC, typename Node>
137         struct link_checker_selector< GC, Node, opt::debug_check_link >
138         {
139 #       ifdef _DEBUG
140             typedef link_checker<Node>  type;
141 #       else
142             typedef intrusive::opt::v::empty_link_checker<Node>  type;
143 #       endif
144         };
145
146         template <typename GC, typename Node>
147         struct link_checker_selector< GC, Node, opt::always_check_link >
148         {
149             typedef link_checker<Node>  type;
150         };
151         //@endcond
152
153         /// Metafunction for selecting appropriate link checking policy
154         template < typename Node, opt::link_check_type LinkType >
155         struct get_link_checker
156         {
157             //@cond
158             typedef typename link_checker_selector< typename Node::gc, Node, LinkType>::type type;
159             //@endcond
160         };
161
162     }   // namespace single_link
163
164 }}  // namespace cds::intrusive
165
166
167
168 #endif // #ifndef CDSLIB_INTRUSIVE_DETAILS_SINGLE_LINK_STRUCT_H