3 #ifndef CDSLIB_CONTAINER_BRONSON_AVLTREE_MAP_RCU_H
4 #define CDSLIB_CONTAINER_BRONSON_AVLTREE_MAP_RCU_H
7 #include <cds/container/impl/bronson_avltree_map_rcu.h>
9 namespace cds { namespace container {
11 namespace bronson_avltree {
14 template < class RCU, typename Key, typename T, typename Traits>
18 typedef T mapped_type;
19 typedef Traits original_traits;
21 typedef cds::details::Allocator< mapped_type, typename original_traits::allocator > cxx_allocator;
23 struct traits : public original_traits
26 void operator()( mapped_type * p ) const
28 cxx_allocator().Delete( p );
33 // Metafunction result
34 typedef BronsonAVLTreeMap< RCU, Key, mapped_type *, traits > type;
36 } // namespace details
38 } // namespace bronson_avltree
40 /// Bronson et al AVL-tree (RCU specialization)
41 /** @ingroup cds_nonintrusive_map
42 @ingroup cds_nonintrusive_tree
43 @anchor cds_container_BronsonAVLTreeMap_rcu
46 - [2010] N.Bronson, J.Casper, H.Chafi, K.Olukotun "A Practical Concurrent Binary Search Tree"
47 - <a href="http://github.com/nbronson/snaptree">Java implementation</a>
49 This is a concurrent AVL tree algorithm that uses hand-over-hand optimistic validation,
50 a concurrency control mechanism for searching and navigating a binary search tree.
51 This mechanism minimizes spurious retries when concurrent structural changes cannot
52 affect the correctness of the search or navigation result. The algorithm is based on
53 partially external trees, a simple scheme that simplifies deletions by leaving a routing
54 node in the tree when deleting a node that has two children, then opportunistically unlinking
55 routing nodes during rebalancing. As in external trees, which store values only in leaf nodes,
56 deletions can be performed locally while holding a fixed number of locks. Partially
57 external trees, however, require far fewer routing nodes than an external tree for most sequences
58 of insertions and deletions.
60 <b>Template arguments</b>:
61 - \p RCU - one of \ref cds_urcu_gc "RCU type"
63 - \p T - value type to be stored in tree's nodes.
64 - \p Traits - tree traits, default is \p bronson_avltree::traits
65 It is possible to declare option-based tree with \p bronson_avltree::make_traits metafunction
66 instead of \p Traits template argument.
68 There is \ref cds_container_BronsonAVLTreeMap_rcu_ptr "a specialization" for "key -> value pointer" map.
70 @note Before including <tt><cds/container/bronson_avltree_map_rcu.h></tt> you should include appropriate RCU header file,
71 see \ref cds_urcu_gc "RCU type" for list of existing RCU class and corresponding header files.
77 # ifdef CDS_DOXYGEN_INVOKED
78 typename Traits = bronson_avltree::traits
83 class BronsonAVLTreeMap< cds::urcu::gc<RCU>, Key, T, Traits >
84 #ifdef CDS_DOXYGEN_INVOKED
85 : private BronsonAVLTreeMap< cds::urcu::gc<RCU>, Key, T*, Traits >
87 : private bronson_avltree::details::make_map< cds::urcu::gc<RCU>, Key, T, Traits >::type
91 typedef bronson_avltree::details::make_map< cds::urcu::gc<RCU>, Key, T, Traits > maker;
92 typedef typename maker::type base_class;
96 typedef cds::urcu::gc<RCU> gc; ///< RCU Garbage collector
97 typedef Key key_type; ///< type of a key stored in the map
98 typedef T mapped_type; ///< type of value stored in the map
99 typedef Traits traits; ///< Traits template parameter
101 typedef typename base_class::key_comparator key_comparator; ///< key compare functor based on \p Traits::compare and \p Traits::less
102 typedef typename traits::item_counter item_counter; ///< Item counting policy
103 typedef typename traits::memory_model memory_model; ///< Memory ordering, see \p cds::opt::memory_model option
104 typedef typename traits::allocator allocator_type; ///< allocator for value
105 typedef typename traits::node_allocator node_allocator_type;///< allocator for maintaining internal nodes
106 typedef typename traits::stat stat; ///< internal statistics
107 typedef typename traits::rcu_check_deadlock rcu_check_deadlock; ///< Deadlock checking policy
108 typedef typename traits::back_off back_off; ///< Back-off strategy
109 typedef typename traits::sync_monitor sync_monitor; ///< @ref cds_sync_monitor "Synchronization monitor" type for node-level locking
111 /// Enabled or disabled @ref bronson_avltree::relaxed_insert "relaxed insertion"
112 static bool const c_bRelaxedInsert = traits::relaxed_insert;
114 /// Group of \p extract_xxx functions does not require external locking
115 static CDS_CONSTEXPR const bool c_bExtractLockExternal = base_class::c_bExtractLockExternal;
117 typedef typename base_class::rcu_lock rcu_lock; ///< RCU scoped lock
119 /// Returned pointer to \p mapped_type of extracted node
120 typedef typename base_class::exempt_ptr exempt_ptr;
124 typedef typename base_class::node_type node_type;
125 typedef typename base_class::node_scoped_lock node_scoped_lock;
126 typedef typename maker::cxx_allocator cxx_allocator;
128 typedef typename base_class::update_flags update_flags;
132 /// Creates empty map
140 /// Inserts new node with \p key and default value
142 The function creates a node with \p key and default value, and then inserts the node created into the map.
145 - The \p key_type should be constructible from a value of type \p K.
146 - The \p mapped_type should be default-constructible.
148 RCU \p synchronize() can be called. RCU should not be locked.
150 Returns \p true if inserting successful, \p false otherwise.
152 template <typename K>
153 bool insert( K const& key )
155 return base_class::do_update(key, key_comparator(),
156 []( node_type * pNode ) -> mapped_type*
158 assert( pNode->m_pValue.load( memory_model::memory_order_relaxed ) == nullptr );
160 return cxx_allocator().New();
162 update_flags::allow_insert
163 ) == update_flags::result_inserted;
168 The function creates a node with copy of \p val value
169 and then inserts the node created into the map.
172 - The \p key_type should be constructible from \p key of type \p K.
173 - The \p mapped_type should be constructible from \p val of type \p V.
175 RCU \p synchronize() method can be called. RCU should not be locked.
177 Returns \p true if \p val is inserted into the map, \p false otherwise.
179 template <typename K, typename V>
180 bool insert( K const& key, V const& val )
182 return base_class::do_update( key, key_comparator(),
183 [&val]( node_type * pNode ) -> mapped_type*
185 assert( pNode->m_pValue.load( memory_model::memory_order_relaxed ) == nullptr );
187 return cxx_allocator().New( val );
189 update_flags::allow_insert
190 ) == update_flags::result_inserted;
193 /// Inserts new node and initialize it by a functor
195 This function inserts new node with key \p key and if inserting is successful then it calls
196 \p func functor with signature
199 void operator()( key_type const& key, mapped_type& item );
203 The key_type should be constructible from value of type \p K.
205 The function allows to split creating of new item into two part:
206 - create item from \p key;
207 - insert new item into the map;
208 - if inserting is successful, initialize the value of item by calling \p func functor
210 This can be useful if complete initialization of object of \p value_type is heavyweight and
211 it is preferable that the initialization should be completed only if inserting is successful.
212 The functor is called under the node lock.
214 RCU \p synchronize() method can be called. RCU should not be locked.
216 template <typename K, typename Func>
217 bool insert_with( K const& key, Func func )
219 return base_class::do_update( key, key_comparator(),
220 [&func]( node_type * pNode ) -> mapped_type*
222 assert( pNode->m_pValue.load( memory_model::memory_order_relaxed ) == nullptr );
223 mapped_type * pVal = cxx_allocator().New();
224 func( pNode->m_key, *pVal );
227 update_flags::allow_insert
228 ) == update_flags::result_inserted;
231 /// For key \p key inserts data of type \p mapped_type created in-place from \p args
233 Returns \p true if inserting successful, \p false otherwise.
235 RCU \p synchronize() method can be called. RCU should not be locked.
237 template <typename K, typename... Args>
238 bool emplace( K&& key, Args&&... args )
240 # if !( CDS_COMPILER == CDS_COMPILER_GCC && CDS_COMPILER_VERSION >= 40800 && CDS_COMPILER_VERSION < 40900 )
241 // Probably, the following code is not so efficient, since we pass lvalues instead rvalues to lambda
242 //TODO: study how to pass a parameter pack to a lambda efficiently using perfect forwarding
243 // see http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#904 - this is what we need
244 return base_class::do_update( key, key_comparator(),
245 [&args...]( node_type * pNode ) -> mapped_type *
247 assert( pNode->m_pValue.load( memory_model::memory_order_relaxed ) == nullptr );
249 return cxx_allocator().New( std::forward<Args>(args)...);
251 update_flags::allow_insert
252 ) == update_flags::result_inserted;
254 // gcc 4.8 error: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47226
255 // workaround (from http://stackoverflow.com/questions/14191989/how-do-i-use-variadic-perfect-forwarding-into-a-lambda)
256 auto f = std::bind<mapped_type *>(
257 []( Args... args) -> mapped_type* { return cxx_allocator().New( std::move(args)...); },
258 std::forward<Args>(args)...
260 return base_class::do_update( key, key_comparator(),
261 [&f]( node_type * pNode ) -> mapped_type *
263 assert( pNode->m_pValue.load( memory_model::memory_order_relaxed ) == nullptr );
267 update_flags::allow_insert
268 ) == update_flags::result_inserted;
272 /// Ensures that the \p key exists in the map
274 The operation performs inserting or changing data with lock-free manner.
276 If the \p key not found in the map, then the new item created from \p key
277 will be inserted into the map (note that in this case the \ref key_type should be
278 constructible from type \p K).
279 Otherwise, the functor \p func is called with item found.
280 The functor \p Func may be a functor:
283 void operator()( bool bNew, key_type const& key, mapped_type& item );
288 - \p bNew - \p true if the item has been inserted, \p false otherwise
291 The functor may change any fields of the \p item. The functor is called under the node lock.
293 RCU \p synchronize() method can be called. RCU should not be locked.
295 Returns <tt> std::pair<bool, bool> </tt> where \p first is \p true if operation is successfull,
296 \p second is \p true if new item has been added or \p false if the item with \p key
299 template <typename K, typename Func>
300 std::pair<bool, bool> update( K const& key, Func func )
302 int result = base_class::do_update( key, key_comparator(),
303 [&func]( node_type * pNode ) -> mapped_type*
305 mapped_type * pVal = pNode->m_pValue.load( memory_model::memory_order_relaxed );
307 pVal = cxx_allocator().New();
308 func( true, pNode->m_key, *pVal );
311 func( false, pNode->m_key, *pVal );
314 update_flags::allow_insert | update_flags::allow_update
316 return std::make_pair( result != 0, (result & update_flags::result_inserted) != 0 );
320 template <typename K, typename Func>
321 std::pair<bool, bool> ensure( K const& key, Func func )
323 return update( key, func );
328 /// Delete \p key from the map
330 RCU \p synchronize() method can be called. RCU should not be locked.
332 Return \p true if \p key is found and deleted, \p false otherwise
334 template <typename K>
335 bool erase( K const& key )
337 return base_class::erase( key );
340 /// Deletes the item from the map using \p pred predicate for searching
342 The function is an analog of \p erase(K const&)
343 but \p pred is used for key comparing.
344 \p Less functor has the interface like \p std::less.
345 \p Less must imply the same element order as the comparator used for building the map.
347 template <typename K, typename Less>
348 bool erase_with( K const& key, Less pred )
350 return base_class::erase_with( key, pred );
353 /// Delete \p key from the map
354 /** \anchor cds_nonintrusive_BronsonAVLTreeMap_rcu_erase_func
356 The function searches an item with key \p key, calls \p f functor
357 and deletes the item. If \p key is not found, the functor is not called.
359 The functor \p Func interface:
362 void operator()(key_type const& key, mapped_type& item) { ... }
366 RCU \p synchronize method can be called. RCU should not be locked.
368 Return \p true if key is found and deleted, \p false otherwise
370 template <typename K, typename Func>
371 bool erase( K const& key, Func f )
373 return base_class::erase( key, f );
376 /// Deletes the item from the map using \p pred predicate for searching
378 The function is an analog of \ref cds_nonintrusive_BronsonAVLTreeMap_rcu_erase_func "erase(K const&, Func)"
379 but \p pred is used for key comparing.
380 \p Less functor has the interface like \p std::less.
381 \p Less must imply the same element order as the comparator used for building the map.
383 template <typename K, typename Less, typename Func>
384 bool erase_with( K const& key, Less pred, Func f )
386 return base_class::erase_with( key, pred, f );
389 /// Extracts a value with minimal key from the map
391 Returns \p exempt_ptr pointer to the leftmost item.
392 If the set is empty, returns empty \p exempt_ptr.
394 Note that the function returns only the value for minimal key.
395 To retrieve its key use \p extract_min( Func ) member function.
397 @note Due the concurrent nature of the map, the function extracts <i>nearly</i> minimum key.
398 It means that the function gets leftmost leaf of the tree and tries to unlink it.
399 During unlinking, a concurrent thread may insert an item with key less than leftmost item's key.
400 So, the function returns the item with minimum key at the moment of tree traversing.
402 RCU \p synchronize method can be called. RCU should NOT be locked.
403 The function does not free the item.
404 The deallocator will be implicitly invoked when the returned object is destroyed or when
405 its \p release() member function is called.
407 exempt_ptr extract_min()
409 return base_class::extract_min();
412 /// Extracts minimal key key and corresponding value
414 Returns \p exempt_ptr to the leftmost item.
415 If the tree is empty, returns empty \p exempt_ptr.
417 \p Func functor is used to store minimal key.
418 \p Func has the following signature:
421 void operator()( key_type const& key );
424 If the tree is empty, \p f is not called.
425 Otherwise, is it called with minimal key, the pointer to corresponding value is returned
428 @note Due the concurrent nature of the map, the function extracts <i>nearly</i> minimum key.
429 It means that the function gets leftmost leaf of the tree and tries to unlink it.
430 During unlinking, a concurrent thread may insert an item with key less than leftmost item's key.
431 So, the function returns the item with minimum key at the moment of tree traversing.
433 RCU \p synchronize method can be called. RCU should NOT be locked.
434 The function does not free the item.
435 The deallocator will be implicitly invoked when the returned object is destroyed or when
436 its \p release() member function is called.
438 template <typename Func>
439 exempt_ptr extract_min( Func f )
441 return base_class::extract_min( f );
444 /// Extracts minimal key key and corresponding value
446 This function is a shortcut for the following call:
449 exempt_ptr xp = theTree.extract_min( [&key]( key_type const& k ) { key = k; } );
451 \p key_type should be copy-assignable. The copy of minimal key
452 is returned in \p min_key argument.
454 typename std::enable_if< std::is_copy_assignable<key_type>::value, exempt_ptr >::type
455 extract_min_key( key_type& min_key )
457 return base_class::extract_min_key( min_key );
460 /// Extracts an item with maximal key from the map
462 Returns \p exempt_ptr pointer to the rightmost item.
463 If the set is empty, returns empty \p exempt_ptr.
465 Note that the function returns only the value for maximal key.
466 To retrieve its key use \p extract_max( Func ) or \p extract_max_key(key_type&) member function.
468 @note Due the concurrent nature of the map, the function extracts <i>nearly</i> maximal key.
469 It means that the function gets rightmost leaf of the tree and tries to unlink it.
470 During unlinking, a concurrent thread may insert an item with key great than leftmost item's key.
471 So, the function returns the item with maximum key at the moment of tree traversing.
473 RCU \p synchronize method can be called. RCU should NOT be locked.
474 The function does not free the item.
475 The deallocator will be implicitly invoked when the returned object is destroyed or when
476 its \p release() is called.
478 exempt_ptr extract_max()
480 return base_class::extract_max();
483 /// Extracts the maximal key and corresponding value
485 Returns \p exempt_ptr pointer to the rightmost item.
486 If the set is empty, returns empty \p exempt_ptr.
488 \p Func functor is used to store maximal key.
489 \p Func has the following signature:
492 void operator()( key_type const& key );
495 If the tree is empty, \p f is not called.
496 Otherwise, is it called with maximal key, the pointer to corresponding value is returned
499 @note Due the concurrent nature of the map, the function extracts <i>nearly</i> maximal key.
500 It means that the function gets rightmost leaf of the tree and tries to unlink it.
501 During unlinking, a concurrent thread may insert an item with key great than leftmost item's key.
502 So, the function returns the item with maximum key at the moment of tree traversing.
504 RCU \p synchronize method can be called. RCU should NOT be locked.
505 The function does not free the item.
506 The deallocator will be implicitly invoked when the returned object is destroyed or when
507 its \p release() is called.
509 template <typename Func>
510 exempt_ptr extract_max( Func f )
512 return base_class::extract_max( f );
515 /// Extracts the maximal key and corresponding value
517 This function is a shortcut for the following call:
520 exempt_ptr xp = theTree.extract_max( [&key]( key_type const& k ) { key = k; } );
522 \p key_type should be copy-assignable. The copy of maximal key
523 is returned in \p max_key argument.
525 typename std::enable_if< std::is_copy_assignable<key_type>::value, exempt_ptr >::type
526 extract_max_key( key_type& max_key )
528 return base_class::extract_max_key( max_key );
531 /// Extracts an item from the map
533 The function searches an item with key equal to \p key in the tree,
534 unlinks it, and returns \p exempt_ptr pointer to a value found.
535 If \p key is not found the function returns an empty \p exempt_ptr.
537 RCU \p synchronize method can be called. RCU should NOT be locked.
538 The function does not destroy the value found.
539 The dealloctor will be implicitly invoked when the returned object is destroyed or when
540 its \p release() member function is called.
542 template <typename Q>
543 exempt_ptr extract( Q const& key )
545 return base_class::extract( key );
548 /// Extracts an item from the map using \p pred for searching
550 The function is an analog of \p extract(Q const&)
551 but \p pred is used for key compare.
552 \p Less has the interface like \p std::less.
553 \p pred must imply the same element order as the comparator used for building the map.
555 template <typename Q, typename Less>
556 exempt_ptr extract_with( Q const& key, Less pred )
558 return base_class::extract_with( key, pred );
561 /// Find the key \p key
563 The function searches the item with key equal to \p key and calls the functor \p f for item found.
564 The interface of \p Func functor is:
567 void operator()( key_type const& key, mapped_type& val );
570 where \p val is the item found for \p key
571 The functor is called under node-level lock.
573 The function applies RCU lock internally.
575 The function returns \p true if \p key is found, \p false otherwise.
577 template <typename K, typename Func>
578 bool find( K const& key, Func f )
580 return base_class::find( key, f );
583 /// Finds the key \p val using \p pred predicate for searching
585 The function is an analog of \p find(K const&, Func)
586 but \p pred is used for key comparing.
587 \p Less functor has the interface like \p std::less.
588 \p Less must imply the same element order as the comparator used for building the map.
590 template <typename K, typename Less, typename Func>
591 bool find_with( K const& key, Less pred, Func f )
593 return base_class::find_with( key, pred, f );
596 /// Find the key \p key
598 The function searches the item with key equal to \p key
599 and returns \p true if it is found, and \p false otherwise.
601 The function applies RCU lock internally.
603 template <typename K>
604 bool find( K const& key )
606 return base_class::find( key );
609 /// Finds the key \p val using \p pred predicate for searching
611 The function is an analog of \p find(K const&)
612 but \p pred is used for key comparing.
613 \p Less functor has the interface like \p std::less.
614 \p Less must imply the same element order as the comparator used for building the map.
616 template <typename K, typename Less>
617 bool find_with( K const& key, Less pred )
619 return base_class::find_with( key, pred );
628 /// Checks if the map is empty
631 return base_class::empty();
634 /// Returns item count in the map
636 Only leaf nodes containing user data are counted.
638 The value returned depends on item counter type provided by \p Traits template parameter.
639 If it is \p atomicity::empty_item_counter this function always returns 0.
641 The function is not suitable for checking the tree emptiness, use \p empty()
642 member function for this purpose.
646 return base_class::size();
649 /// Returns const reference to internal statistics
650 stat const& statistics() const
652 return base_class::statistics();
655 /// Checks internal consistency (not atomic, not thread-safe)
657 The debugging function to check internal consistency of the tree.
659 bool check_consistency() const
661 return base_class::check_consistency();
664 /// Checks internal consistency (not atomic, not thread-safe)
666 The debugging function to check internal consistency of the tree.
667 The functor \p Func is called if a violation of internal tree structure
671 void operator()( size_t nLevel, size_t hLeft, size_t hRight );
675 - \p nLevel - the level where the violation is found
676 - \p hLeft - the height of left subtree
677 - \p hRight - the height of right subtree
679 The functor is called for each violation found.
681 template <typename Func>
682 bool check_consistency( Func f ) const
684 return base_class::check_consistency( f );
687 }} // namespace cds::container
689 #endif // #ifndef CDSLIB_CONTAINER_IMPL_BRONSON_AVLTREE_MAP_RCU_H