3 #ifndef CDSLIB_CONTAINER_BRONSON_AVLTREE_MAP_RCU_H
4 #define CDSLIB_CONTAINER_BRONSON_AVLTREE_MAP_RCU_H
6 #include <cds/container/impl/bronson_avltree_map_rcu.h>
8 namespace cds { namespace container {
10 namespace bronson_avltree {
13 template < class RCU, typename Key, typename T, typename Traits>
17 typedef T mapped_type;
18 typedef Traits original_traits;
20 typedef cds::details::Allocator< mapped_type, typename original_traits::allocator > cxx_allocator;
22 struct traits : public original_traits
25 void operator()( mapped_type * p ) const
27 cxx_allocator().Delete( p );
32 // Metafunction result
33 typedef BronsonAVLTreeMap< RCU, Key, mapped_type *, traits > type;
35 } // namespace details
37 } // namespace bronson_avltree
39 /// Bronson et al AVL-tree (RCU specialization)
40 /** @ingroup cds_nonintrusive_map
41 @ingroup cds_nonintrusive_tree
42 @anchor cds_container_BronsonAVLTreeMap_rcu
45 - [2010] N.Bronson, J.Casper, H.Chafi, K.Olukotun "A Practical Concurrent Binary Search Tree"
46 - <a href="http://github.com/nbronson/snaptree">Java implementation</a>
48 This is a concurrent AVL tree algorithm that uses hand-over-hand optimistic validation,
49 a concurrency control mechanism for searching and navigating a binary search tree.
50 This mechanism minimizes spurious retries when concurrent structural changes cannot
51 affect the correctness of the search or navigation result. The algorithm is based on
52 partially external trees, a simple scheme that simplifies deletions by leaving a routing
53 node in the tree when deleting a node that has two children, then opportunistically unlinking
54 routing nodes during rebalancing. As in external trees, which store values only in leaf nodes,
55 deletions can be performed locally while holding a fixed number of locks. Partially
56 external trees, however, require far fewer routing nodes than an external tree for most sequences
57 of insertions and deletions.
59 <b>Template arguments</b>:
60 - \p RCU - one of \ref cds_urcu_gc "RCU type"
62 - \p T - value type to be stored in tree's nodes.
63 - \p Traits - tree traits, default is \p bronson_avltree::traits
64 It is possible to declare option-based tree with \p bronson_avltree::make_traits metafunction
65 instead of \p Traits template argument.
67 There is \ref cds_container_BronsonAVLTreeMap_rcu_ptr "a specialization" for "key -> value pointer" map.
69 @note Before including <tt><cds/container/bronson_avltree_map_rcu.h></tt> you should include appropriate RCU header file,
70 see \ref cds_urcu_gc "RCU type" for list of existing RCU class and corresponding header files.
76 # ifdef CDS_DOXYGEN_INVOKED
77 typename Traits = bronson_avltree::traits
82 class BronsonAVLTreeMap< cds::urcu::gc<RCU>, Key, T, Traits >
83 #ifdef CDS_DOXYGEN_INVOKED
84 : private BronsonAVLTreeMap< cds::urcu::gc<RCU>, Key, T*, Traits >
86 : private bronson_avltree::details::make_map< cds::urcu::gc<RCU>, Key, T, Traits >::type
90 typedef bronson_avltree::details::make_map< cds::urcu::gc<RCU>, Key, T, Traits > maker;
91 typedef typename maker::type base_class;
95 typedef cds::urcu::gc<RCU> gc; ///< RCU Garbage collector
96 typedef Key key_type; ///< type of a key stored in the map
97 typedef T mapped_type; ///< type of value stored in the map
98 typedef Traits traits; ///< Traits template parameter
100 typedef typename base_class::key_comparator key_comparator; ///< key compare functor based on \p Traits::compare and \p Traits::less
101 typedef typename traits::item_counter item_counter; ///< Item counting policy
102 typedef typename traits::memory_model memory_model; ///< Memory ordering, see \p cds::opt::memory_model option
103 typedef typename traits::allocator allocator_type; ///< allocator for value
104 typedef typename traits::node_allocator node_allocator_type;///< allocator for maintaining internal nodes
105 typedef typename traits::stat stat; ///< internal statistics
106 typedef typename traits::rcu_check_deadlock rcu_check_deadlock; ///< Deadlock checking policy
107 typedef typename traits::back_off back_off; ///< Back-off strategy
108 typedef typename traits::sync_monitor sync_monitor; ///< @ref cds_sync_monitor "Synchronization monitor" type for node-level locking
110 /// Enabled or disabled @ref bronson_avltree::relaxed_insert "relaxed insertion"
111 static bool const c_bRelaxedInsert = traits::relaxed_insert;
113 /// Group of \p extract_xxx functions does not require external locking
114 static CDS_CONSTEXPR const bool c_bExtractLockExternal = base_class::c_bExtractLockExternal;
116 typedef typename base_class::rcu_lock rcu_lock; ///< RCU scoped lock
118 /// Returned pointer to \p mapped_type of extracted node
119 typedef typename base_class::exempt_ptr exempt_ptr;
123 typedef typename base_class::node_type node_type;
124 typedef typename base_class::node_scoped_lock node_scoped_lock;
125 typedef typename maker::cxx_allocator cxx_allocator;
127 typedef typename base_class::update_flags update_flags;
131 /// Creates empty map
139 /// Inserts new node with \p key and default value
141 The function creates a node with \p key and default value, and then inserts the node created into the map.
144 - The \p key_type should be constructible from a value of type \p K.
145 - The \p mapped_type should be default-constructible.
147 RCU \p synchronize() can be called. RCU should not be locked.
149 Returns \p true if inserting successful, \p false otherwise.
151 template <typename K>
152 bool insert( K const& key )
154 return base_class::do_update(key, key_comparator(),
155 []( node_type * pNode ) -> mapped_type*
157 assert( pNode->m_pValue.load( memory_model::memory_order_relaxed ) == nullptr );
159 return cxx_allocator().New();
161 update_flags::allow_insert
162 ) == update_flags::result_inserted;
167 The function creates a node with copy of \p val value
168 and then inserts the node created into the map.
171 - The \p key_type should be constructible from \p key of type \p K.
172 - The \p mapped_type should be constructible from \p val of type \p V.
174 RCU \p synchronize() method can be called. RCU should not be locked.
176 Returns \p true if \p val is inserted into the map, \p false otherwise.
178 template <typename K, typename V>
179 bool insert( K const& key, V const& val )
181 return base_class::do_update( key, key_comparator(),
182 [&val]( node_type * pNode ) -> mapped_type*
184 assert( pNode->m_pValue.load( memory_model::memory_order_relaxed ) == nullptr );
186 return cxx_allocator().New( val );
188 update_flags::allow_insert
189 ) == update_flags::result_inserted;
192 /// Inserts new node and initialize it by a functor
194 This function inserts new node with key \p key and if inserting is successful then it calls
195 \p func functor with signature
198 void operator()( key_type const& key, mapped_type& item );
202 The key_type should be constructible from value of type \p K.
204 The function allows to split creating of new item into two part:
205 - create item from \p key;
206 - insert new item into the map;
207 - if inserting is successful, initialize the value of item by calling \p func functor
209 This can be useful if complete initialization of object of \p value_type is heavyweight and
210 it is preferable that the initialization should be completed only if inserting is successful.
211 The functor is called under the node lock.
213 RCU \p synchronize() method can be called. RCU should not be locked.
215 template <typename K, typename Func>
216 bool insert_with( K const& key, Func func )
218 return base_class::do_update( key, key_comparator(),
219 [&func]( node_type * pNode ) -> mapped_type*
221 assert( pNode->m_pValue.load( memory_model::memory_order_relaxed ) == nullptr );
222 mapped_type * pVal = cxx_allocator().New();
223 func( pNode->m_key, *pVal );
226 update_flags::allow_insert
227 ) == update_flags::result_inserted;
230 /// For key \p key inserts data of type \p mapped_type created in-place from \p args
232 Returns \p true if inserting successful, \p false otherwise.
234 RCU \p synchronize() method can be called. RCU should not be locked.
236 template <typename K, typename... Args>
237 bool emplace( K&& key, Args&&... args )
239 auto helper = []( Args&&... args ) -> mapped_type *
241 return cxx_allocator().New( std::forward<Args>(args)...);
244 return base_class::do_update( key, key_comparator(),
245 [=]( node_type * pNode ) -> mapped_type *
247 assert( pNode->m_pValue.load( memory_model::memory_order_relaxed ) == nullptr );
249 return helper( args... );
250 // gcc/clang error: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47226
251 //return cxx_allocator().New( std::forward<Args>(args)...);
253 update_flags::allow_insert
254 ) == update_flags::result_inserted;
257 /// Ensures that the \p key exists in the map
259 The operation performs inserting or changing data with lock-free manner.
261 If the \p key not found in the map, then the new item created from \p key
262 will be inserted into the map (note that in this case the \ref key_type should be
263 constructible from type \p K).
264 Otherwise, the functor \p func is called with item found.
265 The functor \p Func may be a functor:
268 void operator()( bool bNew, key_type const& key, mapped_type& item );
273 - \p bNew - \p true if the item has been inserted, \p false otherwise
276 The functor may change any fields of the \p item. The functor is called under the node lock.
278 RCU \p synchronize() method can be called. RCU should not be locked.
280 Returns <tt> std::pair<bool, bool> </tt> where \p first is \p true if operation is successfull,
281 \p second is \p true if new item has been added or \p false if the item with \p key
284 template <typename K, typename Func>
285 std::pair<bool, bool> update( K const& key, Func func )
287 int result = base_class::do_update( key, key_comparator(),
288 [&func]( node_type * pNode ) -> mapped_type*
290 mapped_type * pVal = pNode->m_pValue.load( memory_model::memory_order_relaxed );
292 pVal = cxx_allocator().New();
293 func( true, pNode->m_key, *pVal );
296 func( false, pNode->m_key, *pVal );
299 update_flags::allow_insert | update_flags::allow_update
301 return std::make_pair( result != 0, (result & update_flags::result_inserted) != 0 );
305 template <typename K, typename Func>
306 std::pair<bool, bool> ensure( K const& key, Func func )
308 return update( key, func );
313 /// Delete \p key from the map
315 RCU \p synchronize() method can be called. RCU should not be locked.
317 Return \p true if \p key is found and deleted, \p false otherwise
319 template <typename K>
320 bool erase( K const& key )
322 return base_class::erase( key );
325 /// Deletes the item from the map using \p pred predicate for searching
327 The function is an analog of \p erase(K const&)
328 but \p pred is used for key comparing.
329 \p Less functor has the interface like \p std::less.
330 \p Less must imply the same element order as the comparator used for building the map.
332 template <typename K, typename Less>
333 bool erase_with( K const& key, Less pred )
335 return base_class::erase_with( key, pred );
338 /// Delete \p key from the map
339 /** \anchor cds_nonintrusive_BronsonAVLTreeMap_rcu_erase_func
341 The function searches an item with key \p key, calls \p f functor
342 and deletes the item. If \p key is not found, the functor is not called.
344 The functor \p Func interface:
347 void operator()(key_type const& key, mapped_type& item) { ... }
351 RCU \p synchronize method can be called. RCU should not be locked.
353 Return \p true if key is found and deleted, \p false otherwise
355 template <typename K, typename Func>
356 bool erase( K const& key, Func f )
358 return base_class::erase( key, f );
361 /// Deletes the item from the map using \p pred predicate for searching
363 The function is an analog of \ref cds_nonintrusive_BronsonAVLTreeMap_rcu_erase_func "erase(K const&, Func)"
364 but \p pred is used for key comparing.
365 \p Less functor has the interface like \p std::less.
366 \p Less must imply the same element order as the comparator used for building the map.
368 template <typename K, typename Less, typename Func>
369 bool erase_with( K const& key, Less pred, Func f )
371 return base_class::erase_with( key, pred, f );
374 /// Extracts a value with minimal key from the map
376 Returns \p exempt_ptr pointer to the leftmost item.
377 If the set is empty, returns empty \p exempt_ptr.
379 Note that the function returns only the value for minimal key.
380 To retrieve its key use \p extract_min( Func ) member function.
382 @note Due the concurrent nature of the map, the function extracts <i>nearly</i> minimum key.
383 It means that the function gets leftmost leaf of the tree and tries to unlink it.
384 During unlinking, a concurrent thread may insert an item with key less than leftmost item's key.
385 So, the function returns the item with minimum key at the moment of tree traversing.
387 RCU \p synchronize method can be called. RCU should NOT be locked.
388 The function does not free the item.
389 The deallocator will be implicitly invoked when the returned object is destroyed or when
390 its \p release() member function is called.
392 exempt_ptr extract_min()
394 return base_class::extract_min();
397 /// Extracts minimal key key and corresponding value
399 Returns \p exempt_ptr to the leftmost item.
400 If the tree is empty, returns empty \p exempt_ptr.
402 \p Func functor is used to store minimal key.
403 \p Func has the following signature:
406 void operator()( key_type const& key );
409 If the tree is empty, \p f is not called.
410 Otherwise, is it called with minimal key, the pointer to corresponding value is returned
413 @note Due the concurrent nature of the map, the function extracts <i>nearly</i> minimum key.
414 It means that the function gets leftmost leaf of the tree and tries to unlink it.
415 During unlinking, a concurrent thread may insert an item with key less than leftmost item's key.
416 So, the function returns the item with minimum key at the moment of tree traversing.
418 RCU \p synchronize method can be called. RCU should NOT be locked.
419 The function does not free the item.
420 The deallocator will be implicitly invoked when the returned object is destroyed or when
421 its \p release() member function is called.
423 template <typename Func>
424 exempt_ptr extract_min( Func f )
426 return base_class::extract_min( f );
429 /// Extracts minimal key key and corresponding value
431 This function is a shortcut for the following call:
434 exempt_ptr xp = theTree.extract_min( [&key]( key_type const& k ) { key = k; } );
436 \p key_type should be copy-assignable. The copy of minimal key
437 is returned in \p min_key argument.
439 typename std::enable_if< std::is_copy_assignable<key_type>::value, exempt_ptr >::type
440 extract_min_key( key_type& min_key )
442 return base_class::extract_min_key( min_key );
445 /// Extracts an item with maximal key from the map
447 Returns \p exempt_ptr pointer to the rightmost item.
448 If the set is empty, returns empty \p exempt_ptr.
450 Note that the function returns only the value for maximal key.
451 To retrieve its key use \p extract_max( Func ) or \p extract_max_key(key_type&) member function.
453 @note Due the concurrent nature of the map, the function extracts <i>nearly</i> maximal key.
454 It means that the function gets rightmost leaf of the tree and tries to unlink it.
455 During unlinking, a concurrent thread may insert an item with key great than leftmost item's key.
456 So, the function returns the item with maximum key at the moment of tree traversing.
458 RCU \p synchronize method can be called. RCU should NOT be locked.
459 The function does not free the item.
460 The deallocator will be implicitly invoked when the returned object is destroyed or when
461 its \p release() is called.
463 exempt_ptr extract_max()
465 return base_class::extract_max();
468 /// Extracts the maximal key and corresponding value
470 Returns \p exempt_ptr pointer to the rightmost item.
471 If the set is empty, returns empty \p exempt_ptr.
473 \p Func functor is used to store maximal key.
474 \p Func has the following signature:
477 void operator()( key_type const& key );
480 If the tree is empty, \p f is not called.
481 Otherwise, is it called with maximal key, the pointer to corresponding value is returned
484 @note Due the concurrent nature of the map, the function extracts <i>nearly</i> maximal key.
485 It means that the function gets rightmost leaf of the tree and tries to unlink it.
486 During unlinking, a concurrent thread may insert an item with key great than leftmost item's key.
487 So, the function returns the item with maximum key at the moment of tree traversing.
489 RCU \p synchronize method can be called. RCU should NOT be locked.
490 The function does not free the item.
491 The deallocator will be implicitly invoked when the returned object is destroyed or when
492 its \p release() is called.
494 template <typename Func>
495 exempt_ptr extract_max( Func f )
497 return base_class::extract_max( f );
500 /// Extracts the maximal key and corresponding value
502 This function is a shortcut for the following call:
505 exempt_ptr xp = theTree.extract_max( [&key]( key_type const& k ) { key = k; } );
507 \p key_type should be copy-assignable. The copy of maximal key
508 is returned in \p max_key argument.
510 typename std::enable_if< std::is_copy_assignable<key_type>::value, exempt_ptr >::type
511 extract_max_key( key_type& max_key )
513 return base_class::extract_max_key( max_key );
516 /// Extracts an item from the map
518 The function searches an item with key equal to \p key in the tree,
519 unlinks it, and returns \p exempt_ptr pointer to a value found.
520 If \p key is not found the function returns an empty \p exempt_ptr.
522 RCU \p synchronize method can be called. RCU should NOT be locked.
523 The function does not destroy the value found.
524 The dealloctor will be implicitly invoked when the returned object is destroyed or when
525 its \p release() member function is called.
527 template <typename Q>
528 exempt_ptr extract( Q const& key )
530 return base_class::extract( key );
533 /// Extracts an item from the map using \p pred for searching
535 The function is an analog of \p extract(Q const&)
536 but \p pred is used for key compare.
537 \p Less has the interface like \p std::less.
538 \p pred must imply the same element order as the comparator used for building the map.
540 template <typename Q, typename Less>
541 exempt_ptr extract_with( Q const& key, Less pred )
543 return base_class::extract_with( key, pred );
546 /// Find the key \p key
548 The function searches the item with key equal to \p key and calls the functor \p f for item found.
549 The interface of \p Func functor is:
552 void operator()( key_type const& key, mapped_type& val );
555 where \p val is the item found for \p key
556 The functor is called under node-level lock.
558 The function applies RCU lock internally.
560 The function returns \p true if \p key is found, \p false otherwise.
562 template <typename K, typename Func>
563 bool find( K const& key, Func f )
565 return base_class::find( key, f );
568 /// Finds the key \p val using \p pred predicate for searching
570 The function is an analog of \p find(K const&, Func)
571 but \p pred is used for key comparing.
572 \p Less functor has the interface like \p std::less.
573 \p Less must imply the same element order as the comparator used for building the map.
575 template <typename K, typename Less, typename Func>
576 bool find_with( K const& key, Less pred, Func f )
578 return base_class::find_with( key, pred, f );
581 /// Find the key \p key
583 The function searches the item with key equal to \p key
584 and returns \p true if it is found, and \p false otherwise.
586 The function applies RCU lock internally.
588 template <typename K>
589 bool find( K const& key )
591 return base_class::find( key );
594 /// Finds the key \p val using \p pred predicate for searching
596 The function is an analog of \p find(K const&)
597 but \p pred is used for key comparing.
598 \p Less functor has the interface like \p std::less.
599 \p Less must imply the same element order as the comparator used for building the map.
601 template <typename K, typename Less>
602 bool find_with( K const& key, Less pred )
604 return base_class::find_with( key, pred );
613 /// Checks if the map is empty
616 return base_class::empty();
619 /// Returns item count in the map
621 Only leaf nodes containing user data are counted.
623 The value returned depends on item counter type provided by \p Traits template parameter.
624 If it is \p atomicity::empty_item_counter this function always returns 0.
626 The function is not suitable for checking the tree emptiness, use \p empty()
627 member function for this purpose.
631 return base_class::size();
634 /// Returns const reference to internal statistics
635 stat const& statistics() const
637 return base_class::statistics();
640 /// Checks internal consistency (not atomic, not thread-safe)
642 The debugging function to check internal consistency of the tree.
644 bool check_consistency() const
646 return base_class::check_consistency();
649 /// Checks internal consistency (not atomic, not thread-safe)
651 The debugging function to check internal consistency of the tree.
652 The functor \p Func is called if a violation of internal tree structure
656 void operator()( size_t nLevel, size_t hLeft, size_t hRight );
660 - \p nLevel - the level where the violation is found
661 - \p hLeft - the height of left subtree
662 - \p hRight - the height of right subtree
664 The functor is called for each violation found.
666 template <typename Func>
667 bool check_consistency( Func f ) const
669 return base_class::check_consistency( f );
672 }} // namespace cds::container
674 #endif // #ifndef CDSLIB_CONTAINER_IMPL_BRONSON_AVLTREE_MAP_RCU_H