3 #ifndef __CDS_CONTAINER_DETAILS_ELLEN_BINTREE_BASE_H
4 #define __CDS_CONTAINER_DETAILS_ELLEN_BINTREE_BASE_H
6 #include <cds/intrusive/details/ellen_bintree_base.h>
7 #include <cds/container/details/base.h>
8 #include <cds/opt/compare.h>
9 #include <cds/details/binary_functor_wrapper.h>
12 namespace cds { namespace container {
13 /// EllenBinTree related definitions
14 /** @ingroup cds_nonintrusive_helper
16 namespace ellen_bintree {
18 #ifdef CDS_DOXYGEN_INVOKED
19 /// Typedef for \p cds::intrusive::ellen_bintree::update_desc
20 typedef cds::intrusive::ellen_bintree::update_desc update_desc;
22 /// Typedef for \p cds::intrusive::ellen_bintree::internal_node
23 typedef cds::intrusive::ellen_bintree::internal_node internal_node;
25 /// Typedef for \p cds::intrusive::ellen_bintree::key_extractor
26 typedef cds::intrusive::ellen_bintree::key_extractor key_extractor;
28 /// Typedef for \p cds::intrusive::ellen_bintree::update_desc_allocator
29 typedef cds::intrusive::ellen_bintree::update_desc_allocator update_desc_allocator;
31 using cds::intrusive::ellen_bintree::update_desc;
32 using cds::intrusive::ellen_bintree::internal_node;
33 using cds::intrusive::ellen_bintree::key_extractor;
34 using cds::intrusive::ellen_bintree::update_desc_allocator;
35 using cds::intrusive::ellen_bintree::node_types;
37 /// EllenBinTree internal statistics
38 template <typename Counter = cds::intrusive::ellen_bintree::stat<>::event_counter >
39 using stat = cds::intrusive::ellen_bintree::stat< Counter >;
41 /// EllenBinTree empty internal statistics
42 typedef cds::intrusive::ellen_bintree::empty_stat empty_stat;
44 /// EllenBinTree leaf node
45 template <typename GC, typename T>
46 struct node: public cds::intrusive::ellen_bintree::node<GC>
48 typedef T value_type ; ///< Value type
50 T m_Value ; ///< Value
63 template <typename... Args>
64 node( Args const&... args)
69 template <typename... Args>
71 : m_Value( std::forward<Args>(args)... )
75 /// EllenBinTreeMap leaf node
76 template <typename GC, typename Key, typename T>
77 struct map_node: public cds::intrusive::ellen_bintree::node< GC >
79 typedef Key key_type ; ///< key type
80 typedef T mapped_type ; ///< value type
81 typedef std::pair<key_type const, mapped_type> value_type ; ///< key-value pair stored in the map
83 value_type m_Value ; ///< Key-value pair stored in map leaf node
85 /// Initializes key field, value if default-constructed
87 map_node( K const& key )
88 : m_Value( std::make_pair( key_type(key), mapped_type() ))
91 /// Initializes key and value fields
92 template <typename K, typename Q>
93 map_node( K const& key, Q const& v )
94 : m_Value( std::make_pair(key_type(key), mapped_type(v) ))
98 /// Type traits for EllenBinTreeSet and EllenBinTreeMap
101 /// Key extracting functor (only for \p EllenBinTreeSet)
103 You should explicit define a valid functor.
104 The functor has the following prototype:
106 struct key_extractor {
107 void operator ()( Key& dest, T const& src );
110 It should initialize \p dest key from \p src data.
111 The functor is used to initialize internal nodes of \p EllenBinTreeSet
113 typedef opt::none key_extractor;
115 /// Key comparison functor
117 No default functor is provided. If the option is not specified, the \p less is used.
119 See \p cds::opt::compare option description for functor interface.
121 You should provide \p compare or \p less functor.
122 See \ref cds_container_EllenBinTreeSet_rcu_less "predicate requirements".
124 typedef opt::none compare;
126 /// Specifies binary predicate used for key compare.
128 See \p cds::opt::less option description.
130 You should provide \p compare or \p less functor.
131 See \ref cds_container_EllenBinTreeSet_rcu_less "predicate requirements".
133 typedef opt::none less;
137 The type for item counter, by default it is disabled (\p atomicity::empty_item_counter).
138 To enable it use \p atomicity::item_counter
140 typedef atomicity::empty_item_counter item_counter;
142 /// C++ memory ordering model
144 List of available memory ordering see \p opt::memory_model
146 typedef opt::v::relaxed_ordering memory_model;
148 /// Allocator for update descriptors
150 The allocator type is used for \p ellen_bintree::update_desc.
152 Update descriptor is helping data structure with short lifetime and it is good candidate
153 for pooling. The number of simultaneously existing descriptors is a small number
154 limited the number of threads working with the tree.
155 Therefore, a bounded lock-free container like \p cds::container::VyukovMPMCCycleQueue
156 is good choice for the free-list of update descriptors,
157 see \p cds::memory::vyukov_queue_pool free-list implementation.
159 Also notice that size of update descriptor is not dependent on the type of data
160 stored in the tree so single free-list object can be used for several \p EllenBinTree object.
162 typedef CDS_DEFAULT_ALLOCATOR update_desc_allocator;
164 /// Allocator for internal nodes
166 The allocator type is used for \p ellen_bintree::internal_node.
168 typedef CDS_DEFAULT_ALLOCATOR node_allocator;
170 /// Allocator for leaf nodes
172 Each leaf node contains data stored in the container.
174 typedef CDS_DEFAULT_ALLOCATOR allocator;
176 /// Internal statistics
178 By default, internal statistics is disabled (\p ellen_bintree::empty_stat).
179 To enable it use \p ellen_bintree::stat.
181 typedef empty_stat stat;
183 /// RCU deadlock checking policy (only for RCU-based EllenBinTree<i>XXX</i> classes)
185 List of available options see \p opt::rcu_check_deadlock
187 typedef cds::opt::v::rcu_throw_deadlock rcu_check_deadlock;
189 /// Key copy policy (for \p EllenBinTreeMap)
191 The key copy policy defines a functor to copy leaf node's key to internal node.
192 This policy is used only in \p EllenBinTreeMap.
193 By default, assignment operator is used.
195 The copy functor interface is:
197 struct copy_functor {
198 void operator()( Key& dest, Key const& src );
202 typedef opt::none copy_policy;
206 /// Metafunction converting option list to \p EllenBinTreeSet traits
209 - \p ellen_bintree::key_extractor - key extracting functor, mandatory option. The functor has the following prototype:
211 struct key_extractor {
212 void operator ()( Key& dest, T const& src );
215 It should initialize \p dest key from \p src data. The functor is used to initialize internal nodes.
216 - \p opt::compare - key compare functor. No default functor is provided.
217 If the option is not specified, \p %opt::less is used.
218 - \p opt::less - specifies binary predicate used for key compare. At least \p %opt::compare or \p %opt::less should be defined.
219 - \p opt::item_counter - the type of item counter, default is disabled (\p atomicity::empty_item_counter).
220 To enable it use \p atomicity::item_counter
221 - \p opt::memory_model - C++ memory ordering model. Can be \p opt::v::relaxed_ordering (relaxed memory model, the default)
222 or \p opt::v::sequential_consistent (sequentially consisnent memory model).
223 - \p opt::allocator - the allocator for \ref ellen_bintree::node "leaf nodes" which contains data.
224 Default is \ref CDS_DEFAULT_ALLOCATOR.
225 - \p opt::node_allocator - the allocator for internal nodes. Default is \ref CDS_DEFAULT_ALLOCATOR.
226 - \p ellen_bintree::update_desc_allocator - an allocator of \ref ellen_bintree::update_desc "update descriptors",
227 default is \ref CDS_DEFAULT_ALLOCATOR.
228 Note that update descriptor is helping data structure with short lifetime and it is good candidate for pooling.
229 The number of simultaneously existing descriptors is a relatively small number limited the number of threads
230 working with the tree and RCU buffer size.
231 Therefore, a bounded lock-free container like \p cds::container::VyukovMPMCCycleQueue is good choice for the free-list
232 of update descriptors, see \p cds::memory::vyukov_queue_pool free-list implementation.
233 Also notice that size of update descriptor is not dependent on the type of data
234 stored in the tree so single free-list object can be used for several EllenBinTree-based object.
235 - \p opt::stat - internal statistics, by default disabled (\p ellen_bintree::empty_stat). To enable
236 it use \p ellen_bintree::stat.
237 - \p opt::rcu_check_deadlock - a deadlock checking policy, only for RCU-based tree.
238 Default is \p opt::v::rcu_throw_deadlock.
240 template <typename... Options>
241 struct make_set_traits {
242 # ifdef CDS_DOXYGEN_INVOKED
243 typedef implementation_defined type ; ///< Metafunction result
245 typedef typename cds::opt::make_options<
246 typename cds::opt::find_type_traits< traits, Options... >::type
252 /// Metafunction converting option list to \p EllenBinTreeMap traits
255 - \p opt::compare - key compare functor. No default functor is provided.
256 If the option is not specified, \p %opt::less is used.
257 - \p opt::less - specifies binary predicate used for key compare. At least \p %opt::compare or \p %opt::less should be defined.
258 - \p opt::item_counter - the type of item counter, default is disabled (\p atomicity::empty_item_counter).
259 To enable it use \p atomicity::item_counter
260 - opt::memory_model - C++ memory ordering model. Can be \p opt::v::relaxed_ordering (relaxed memory model, the default)
261 or \p opt::v::sequential_consistent (sequentially consisnent memory model).
262 - \p opt::allocator - the allocator used for \ref ellen_bintree::map_node "leaf nodes" which contains data.
263 Default is \ref CDS_DEFAULT_ALLOCATOR.
264 - \p opt::node_allocator - the allocator used for \ref ellen_bintree::internal_node "internal nodes".
265 Default is \ref CDS_DEFAULT_ALLOCATOR.
266 - \p ellen_bintree::update_desc_allocator - an allocator of \ref ellen_bintree::update_desc "update descriptors",
267 default is \ref CDS_DEFAULT_ALLOCATOR.
268 Note that update descriptor is helping data structure with short lifetime and it is good candidate for pooling.
269 The number of simultaneously existing descriptors is a relatively small number limited the number of threads
270 working with the tree and RCU buffer size.
271 Therefore, a bounded lock-free container like \p cds::container::VyukovMPMCCycleQueue is good choice for the free-list
272 of update descriptors, see \p cds::memory::vyukov_queue_pool free-list implementation.
273 Also notice that size of update descriptor is not dependent on the type of data
274 stored in the tree so single free-list object can be used for several EllenBinTree-based object.
275 - \p opt::stat - internal statistics, by default disabled (\p ellen_bintree::empty_stat). To enable
276 it use \p ellen_bintree::stat.
277 - \p opt::rcu_check_deadlock - a deadlock checking policy, only for RCU-based tree. Default is \p opt::v::rcu_throw_deadlock
278 - opt::copy_policy - key copying policy defines a functor to copy leaf node's key to internal node.
279 By default, assignment operator is used.
280 The copy functor interface is:
282 struct copy_functor {
283 void operator()( Key& dest, Key const& src );
287 template <typename... Options>
288 struct make_map_traits {
289 # ifdef CDS_DOXYGEN_INVOKED
290 typedef implementation_defined type ; ///< Metafunction result
292 typedef typename cds::opt::make_options<
293 typename cds::opt::find_type_traits< traits, Options... >::type
302 template < class GC, typename Key, typename T, class Traits>
303 struct make_ellen_bintree_set
306 typedef Key key_type;
307 typedef T value_type;
308 typedef Traits original_traits;
310 typedef node< gc, value_type > leaf_node;
312 struct intrusive_key_extractor
314 void operator()( key_type& dest, leaf_node const& src ) const
316 typename original_traits::key_extractor()( dest, src.m_Value );
320 struct value_accessor
322 value_type const& operator()( leaf_node const& node ) const
328 typedef typename cds::opt::details::make_comparator< value_type, original_traits, false >::type key_comparator;
330 typedef cds::details::Allocator< leaf_node, typename original_traits::allocator> cxx_leaf_node_allocator;
331 struct leaf_deallocator
333 void operator()( leaf_node * p ) const
335 cxx_leaf_node_allocator().Delete( p );
339 struct intrusive_traits: public original_traits
341 typedef cds::intrusive::ellen_bintree::base_hook< cds::opt::gc< gc > > hook;
342 typedef intrusive_key_extractor key_extractor;
343 typedef leaf_deallocator disposer;
344 typedef cds::details::compare_wrapper< leaf_node, key_comparator, value_accessor > compare;
347 // Metafunction result
348 typedef cds::intrusive::EllenBinTree< gc, key_type, leaf_node, intrusive_traits > type;
351 template < class GC, typename Key, typename T, class Traits>
352 struct make_ellen_bintree_map
355 typedef Key key_type;
356 typedef T mapped_type;
357 typedef map_node< gc, key_type, mapped_type > leaf_node;
358 typedef typename leaf_node::value_type value_type;
360 typedef Traits original_traits;
362 struct assignment_copy_policy {
363 void operator()( key_type& dest, key_type const& src )
368 typedef typename std::conditional<
369 std::is_same< typename original_traits::copy_policy, opt::none >::value,
370 assignment_copy_policy,
371 typename original_traits::copy_policy
374 struct intrusive_key_extractor
376 void operator()( key_type& dest, leaf_node const& src ) const
378 copy_policy()( dest, src.m_Value.first );
384 key_type const& operator()( leaf_node const& node ) const
386 return node.m_Value.first;
390 typedef typename cds::opt::details::make_comparator< key_type, original_traits, false >::type key_comparator;
392 typedef cds::details::Allocator< leaf_node, typename original_traits::allocator> cxx_leaf_node_allocator;
393 struct leaf_deallocator
395 void operator()( leaf_node * p ) const
397 cxx_leaf_node_allocator().Delete( p );
401 struct intrusive_traits: public original_traits
403 typedef cds::intrusive::ellen_bintree::base_hook< cds::opt::gc< gc > > hook;
404 typedef intrusive_key_extractor key_extractor;
405 typedef leaf_deallocator disposer;
406 typedef cds::details::compare_wrapper< leaf_node, key_comparator, key_accessor > compare;
409 // Metafunction result
410 typedef cds::intrusive::EllenBinTree< gc, key_type, leaf_node, intrusive_traits > type;
413 } // namespace details
415 } // namespace ellen_bintree
417 // Forward declarations
419 template < class GC, typename Key, typename T, class Traits = ellen_bintree::traits >
420 class EllenBinTreeSet;
422 template < class GC, typename Key, typename T, class Traits = ellen_bintree::traits >
423 class EllenBinTreeMap;
426 }} // namespace cds::container
428 #endif // #ifndef __CDS_CONTAINER_DETAILS_ELLEN_BINTREE_BASE_H