2b02e797dd2f16a5bd1b1732a117867d6374bbac
[libcds.git] / cds / intrusive / details / single_link_struct.h
1 //$$CDS-header$$
2
3 #ifndef __CDS_INTRUSIVE_DETAILS_SINGLE_LINK_STRUCT_H
4 #define __CDS_INTRUSIVE_DETAILS_SINGLE_LINK_STRUCT_H
5
6 #include <cds/intrusive/details/base.h>
7 #include <cds/gc/default_gc.h>
8 #include <cds/cxx11_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()
40                 : m_pNext( nullptr )
41             {}
42         };
43
44         //@cond
45         struct default_hook {
46             typedef cds::gc::default_gc gc;
47             typedef opt::none           tag;
48         };
49         //@endcond
50
51         //@cond
52         template < typename HookType, typename... Options>
53         struct hook
54         {
55             typedef typename opt::make_options< default_hook, Options...>::type  options;
56             typedef typename options::gc    gc;
57             typedef typename options::tag   tag;
58             typedef node<gc, tag> node_type;
59             typedef HookType      hook_type;
60         };
61         //@endcond
62
63         /// Base hook
64         /**
65             \p Options are:
66             - opt::gc - garbage collector used.
67             - opt::tag - tag
68         */
69         template < typename... Options >
70         struct base_hook: public hook< opt::base_hook_tag, Options... >
71         {};
72
73         /// Member hook
74         /**
75             \p MemberOffset defines offset in bytes of \ref node member into your structure.
76             Use \p offsetof macro to define \p MemberOffset
77
78             \p Options are:
79             - opt::gc - garbage collector used.
80             - opt::tag - tag
81         */
82         template < size_t MemberOffset, typename... Options >
83         struct member_hook: public hook< opt::member_hook_tag, Options... >
84         {
85             //@cond
86             static const size_t c_nMemberOffset = MemberOffset;
87             //@endcond
88         };
89
90         /// Traits hook
91         /**
92             \p NodeTraits defines type traits for node.
93             See \ref node_traits for \p NodeTraits interface description
94
95             \p Options are:
96             - opt::gc - garbage collector used.
97             - opt::tag - tag
98         */
99         template <typename NodeTraits, typename... Options >
100         struct traits_hook: public hook< opt::traits_hook_tag, Options... >
101         {
102             //@cond
103             typedef NodeTraits node_traits;
104             //@endcond
105         };
106
107         /// Check link
108         template <typename Node>
109         struct link_checker {
110             //@cond
111             typedef Node node_type;
112             //@endcond
113
114             /// Checks if the link field of node \p pNode is \p nullptr
115             /**
116                 An asserting is generated if \p pNode link field is not \p nullptr
117             */
118             static void is_empty( const node_type * pNode )
119             {
120                 assert( pNode->m_pNext.load( atomics::memory_order_relaxed ) == nullptr );
121             }
122         };
123
124         //@cond
125         template <class GC, typename Node, opt::link_check_type LinkType >
126         struct link_checker_selector;
127
128         template <typename GC, typename Node>
129         struct link_checker_selector< GC, Node, opt::never_check_link >
130         {
131             typedef intrusive::opt::v::empty_link_checker<Node>  type;
132         };
133
134         template <typename GC, typename Node>
135         struct link_checker_selector< GC, Node, opt::debug_check_link >
136         {
137 #       ifdef _DEBUG
138             typedef link_checker<Node>  type;
139 #       else
140             typedef intrusive::opt::v::empty_link_checker<Node>  type;
141 #       endif
142         };
143
144         template <typename GC, typename Node>
145         struct link_checker_selector< GC, Node, opt::always_check_link >
146         {
147             typedef link_checker<Node>  type;
148         };
149         //@endcond
150
151         /// Metafunction for selecting appropriate link checking policy
152         template < typename Node, opt::link_check_type LinkType >
153         struct get_link_checker
154         {
155             //@cond
156             typedef typename link_checker_selector< typename Node::gc, Node, LinkType>::type type;
157             //@endcond
158         };
159
160     }   // namespace single_link
161
162 }}  // namespace cds::intrusive
163
164
165
166 #endif // #ifndef __CDS_INTRUSIVE_DETAILS_SINGLE_LINK_STRUCT_H