From: khizmax Date: Wed, 29 Oct 2014 06:51:21 +0000 (+0300) Subject: container::SplitListSet refactoring X-Git-Tag: v2.0.0~164 X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=d51ffb6153fd8681f08ef55fd72ee43ac8d33da8;p=libcds.git container::SplitListSet refactoring --- diff --git a/cds/container/details/make_lazy_list.h b/cds/container/details/make_lazy_list.h index ff5f8c3e..f7923e0b 100644 --- a/cds/container/details/make_lazy_list.h +++ b/cds/container/details/make_lazy_list.h @@ -63,7 +63,7 @@ namespace cds { namespace container { { typedef intrusive::lazy_list::base_hook< opt::gc > hook; typedef node_deallocator disposer; - static const opt::link_check_type link_checker = cds::intrusive::lazy_list::traits::link_checker; + static CDS_CONSTEXPR const opt::link_check_type link_checker = cds::intrusive::lazy_list::traits::link_checker; typedef cds::details::compare_wrapper< node_type, key_comparator, value_accessor > compare; }; diff --git a/cds/container/details/make_michael_list.h b/cds/container/details/make_michael_list.h index fd441b1c..e452ead1 100644 --- a/cds/container/details/make_michael_list.h +++ b/cds/container/details/make_michael_list.h @@ -67,7 +67,7 @@ namespace cds { namespace container { typedef intrusive::michael_list::base_hook< opt::gc > hook; typedef node_deallocator disposer; typedef cds::details::compare_wrapper< node_type, key_comparator, value_accessor > compare; - static const opt::link_check_type link_checker = intrusive::michael_list::traits::link_checker; + static CDS_CONSTEXPR const opt::link_check_type link_checker = cds::intrusive::lazy_list::traits::link_checker; }; typedef intrusive::MichaelList type; diff --git a/cds/container/details/make_split_list_set.h b/cds/container/details/make_split_list_set.h index fce37e08..d1915c67 100644 --- a/cds/container/details/make_split_list_set.h +++ b/cds/container/details/make_split_list_set.h @@ -24,11 +24,11 @@ namespace cds { namespace container { { typedef GC gc; typedef T value_type; - typedef Traits original_type_traits; + typedef Traits original_traits; typedef typename cds::opt::select_default< - typename original_type_traits::ordered_list_traits, - cds::container::michael_list::type_traits + typename original_traits::ordered_list_traits, + cds::container::michael_list::traits >::type original_ordered_list_traits; typedef cds::intrusive::split_list::node< cds::intrusive::michael_list::node > primary_node_type; @@ -49,11 +49,11 @@ namespace cds { namespace container { }; typedef typename cds::opt::select_default< - typename original_type_traits::ordered_list_traits, - typename original_type_traits::allocator, + typename original_traits::ordered_list_traits, + typename original_traits::allocator, typename cds::opt::select_default< - typename original_type_traits::ordered_list_traits::allocator, - typename original_type_traits::allocator + typename original_traits::ordered_list_traits::allocator, + typename original_traits::allocator >::type >::type node_allocator_; @@ -70,7 +70,7 @@ namespace cds { namespace container { typedef typename opt::details::make_comparator< value_type, original_ordered_list_traits >::type key_comparator; - typedef typename original_type_traits::key_accessor key_accessor; + typedef typename original_traits::key_accessor key_accessor; struct value_accessor { @@ -90,16 +90,17 @@ namespace cds { namespace container { typedef cds::intrusive::michael_list::base_hook< opt::gc > hook; - typedef atomicity::empty_item_counter item_counter; - typedef node_deallocator disposer; + typedef cds::atomicity::empty_item_counter item_counter; + typedef node_deallocator disposer; typedef cds::details::compare_wrapper< node_type, key_comparator, value_accessor > compare; + static CDS_CONSTEXPR const opt::link_check_type link_checker = cds::intrusive::michael_list::traits::link_checker; }; - struct type_traits: public original_type_traits + struct traits: public original_traits { - struct hash: public original_type_traits::hash + struct hash: public original_traits::hash { - typedef typename original_type_traits::hash base_class; + typedef typename original_traits::hash base_class; size_t operator()(node_type const& v ) const { @@ -110,12 +111,11 @@ namespace cds { namespace container { { return base_class::operator()( k ); } - //using base_class::operator(); }; }; - typedef cds::intrusive::MichaelList< gc, node_type, ordered_list_traits > ordered_list; - typedef cds::intrusive::SplitListSet< gc, ordered_list, type_traits > type; + typedef cds::intrusive::MichaelList< gc, node_type, ordered_list_traits > ordered_list; + typedef cds::intrusive::SplitListSet< gc, ordered_list, traits > type; }; #endif // ifdef __CDS_CONTAINER_DETAILS_MICHAEL_LIST_BASE_H @@ -126,16 +126,16 @@ namespace cds { namespace container { { typedef GC gc; typedef T value_type; - typedef Traits original_type_traits; + typedef Traits original_traits; typedef typename cds::opt::select_default< - typename original_type_traits::ordered_list_traits, - cds::container::lazy_list::type_traits + typename original_traits::ordered_list_traits, + cds::container::lazy_list::traits >::type original_ordered_list_traits; typedef typename cds::opt::select_default< typename original_ordered_list_traits::lock_type, - typename cds::container::lazy_list::type_traits::lock_type + typename cds::container::lazy_list::traits::lock_type >::type lock_type; typedef cds::intrusive::split_list::node< cds::intrusive::lazy_list::node > primary_node_type; @@ -157,11 +157,11 @@ namespace cds { namespace container { }; typedef typename cds::opt::select_default< - typename original_type_traits::ordered_list_traits, - typename original_type_traits::allocator, + typename original_traits::ordered_list_traits, + typename original_traits::allocator, typename cds::opt::select_default< - typename original_type_traits::ordered_list_traits::allocator, - typename original_type_traits::allocator + typename original_traits::ordered_list_traits::allocator, + typename original_traits::allocator >::type >::type node_allocator_; @@ -178,7 +178,7 @@ namespace cds { namespace container { typedef typename opt::details::make_comparator< value_type, original_ordered_list_traits >::type key_comparator; - typedef typename original_type_traits::key_accessor key_accessor; + typedef typename original_traits::key_accessor key_accessor; struct value_accessor { @@ -199,16 +199,17 @@ namespace cds { namespace container { opt::gc ,opt::lock_type< lock_type > > hook; - typedef atomicity::empty_item_counter item_counter; + typedef cds::atomicity::empty_item_counter item_counter; typedef node_deallocator disposer; typedef cds::details::compare_wrapper< node_type, key_comparator, value_accessor > compare; + static CDS_CONSTEXPR const opt::link_check_type link_checker = cds::intrusive::lazy_list::traits::link_checker; }; - struct type_traits: public original_type_traits + struct traits: public original_traits { - struct hash: public original_type_traits::hash + struct hash: public original_traits::hash { - typedef typename original_type_traits::hash base_class; + typedef typename original_traits::hash base_class; size_t operator()(node_type const& v ) const { @@ -219,12 +220,11 @@ namespace cds { namespace container { { return base_class::operator()( k ); } - //using base_class::operator(); }; }; typedef cds::intrusive::LazyList< gc, node_type, ordered_list_traits > ordered_list; - typedef cds::intrusive::SplitListSet< gc, ordered_list, type_traits > type; + typedef cds::intrusive::SplitListSet< gc, ordered_list, traits > type; }; #endif // ifdef __CDS_CONTAINER_DETAILS_LAZY_LIST_BASE_H diff --git a/cds/container/details/split_list_base.h b/cds/container/details/split_list_base.h index b52b860a..ba74ecff 100644 --- a/cds/container/details/split_list_base.h +++ b/cds/container/details/split_list_base.h @@ -14,7 +14,19 @@ namespace cds { namespace container { /** @ingroup cds_nonintrusive_helper */ namespace split_list { - using intrusive::split_list::dynamic_bucket_table; + /// Internal statistics, see \p cds::intrusive::split_list::stat + template ::counter_type > + using stat = cds::intrusive::split_list::stat; + + /// Disabled internal statistics, see \p cds::intrusive::split_list::empty_stat + typedef cds::intrusive::split_list::empty_stat empty_stat; + + /// Selector of bucket table implementation =- typedef for \p intrusive::split_list::dynamic_bucket_table + template + using dynamic_bucket_table = cds::intrusive::split_list::dynamic_bucket_table; + + using cds::intrusive::split_list::static_bucket_table; + using cds::intrusive::split_list::expandable_bucket_table; //@cond namespace details { @@ -70,30 +82,26 @@ namespace cds { namespace container { //@endcond - /// Type traits for SplitListSet class - /** - Note, the SplitListSet type traits is based on intrusive::split_list::traits. - Any member declared in intrusive::split_list::traits is also applied to - container::split_list::traits. - */ - struct type_traits: public intrusive::split_list::type_traits + /// SplitListSet traits + struct traits: public intrusive::split_list::traits { // Ordered list implementation /** - This option selects appropriate ordered-list implementation for split-list. - It may be \ref michael_list_tag or \ref lazy_list_tag. + Selects appropriate ordered-list implementation for split-list. + Supported types are: + - \p michael_list_tag - for MichaelList + - \p lazy_list_tag - for LazyList */ typedef michael_list_tag ordered_list; // Ordered list traits /** - With this option you can specify type traits for selected ordered list class. - If this option is opt::none, the ordered list traits is combined with default - ordered list traits and split-list traits. - - For \p michael_list_tag, the default traits is \p container::michael_list::traits. + Specifyes traits for selected ordered list type, default type: + - for \p michael_list_tag: \p container::michael_list::traits. + - for \p lazy_list_tag: \p container::lazy_list::traits. - For \p lazy_list_tag, the default traits is \p container::lazy_list::traits. + If this type is \p opt::none, the ordered list traits is combined with default + ordered list traits above and split-list traits. */ typedef opt::none ordered_list_traits; @@ -105,7 +113,7 @@ namespace cds { namespace container { /// Option to select ordered list class for split-list /** This option selects appropriate ordered list class for containers based on split-list. - Template parameter \p Type may be \ref michael_list_tag or \ref lazy_list_tag. + Template parameter \p Type may be \p michael_list_tag or \p lazy_list_tag. */ template struct ordered_list @@ -137,25 +145,24 @@ namespace cds { namespace container { /// Metafunction converting option list to traits struct /** Available \p Options: - - split_list::ordered_list - a tag for ordered list implementation. - See split_list::ordered_list for possible values. - - split_list::ordered_list_traits - type traits for ordered list implementation. - For MichaelList use \p container::michael_list::traits, - for LazyList use \p container::lazy_list::traits. - - plus any option from intrusive::split_list::make_traits + - \p split_list::ordered_list - a tag for ordered list implementation. + - \p split_list::ordered_list_traits - type traits for ordered list implementation. + For \p MichaelList use \p container::michael_list::traits or derivatives, + for \p LazyList use \p container::lazy_list::traits or derivatives. + - plus any option from \p intrusive::split_list::make_traits */ template struct make_traits { - typedef typename cds::opt::make_options< type_traits, Options...>::type type ; ///< Result of metafunction + typedef typename cds::opt::make_options< traits, Options...>::type type ; ///< Result of metafunction }; } // namespace split_list //@cond // Forward declarations - template + template class SplitListSet; - template + template class SplitListMap; //@endcond diff --git a/cds/container/split_list_set.h b/cds/container/split_list_set.h index b353cdd7..e272e8e3 100644 --- a/cds/container/split_list_set.h +++ b/cds/container/split_list_set.h @@ -16,13 +16,13 @@ namespace cds { namespace container { - [2003] Ori Shalev, Nir Shavit "Split-Ordered Lists - Lock-free Resizable Hash Tables" - [2008] Nir Shavit "The Art of Multiprocessor Programming" - See intrusive::SplitListSet for a brief description of the split-list algorithm. + See \p intrusive::SplitListSet for a brief description of the split-list algorithm. Template parameters: - \p GC - Garbage collector used - - \p T - type stored in the split-list. The type must be default- and copy-constructible. - - \p Traits - type traits, default is split_list::type_traits. Instead of declaring split_list::type_traits -based - struct you may apply option-based notation with split_list::make_traits metafunction. + - \p T - type to be stored in the split-list. + - \p Traits - type traits, default is \p split_list::traits. Instead of declaring \p split_list::traits -based + struct you may apply option-based notation with \p split_list::make_traits metafunction. There are the specializations: - for \ref cds_urcu_desc "RCU" - declared in cd/container/split_list_set_rcu.h, @@ -32,9 +32,11 @@ namespace cds { namespace container { \par Usage - You should decide what garbage collector you want, and what ordered list you want to use. Split-ordered list - is original data structure based on an ordered list. Suppose, you want construct split-list set based on gc::DHP GC - and LazyList as ordered list implementation. So, you beginning your program with following include: + You should decide what garbage collector you want, and what ordered list you want to use as a base. Split-ordered list + is original data structure based on an ordered list. + + Suppose, you want construct split-list set based on \p gc::DHP GC + and \p LazyList as ordered list implementation. So, you beginning your program with following include: \code #include #include @@ -54,7 +56,7 @@ namespace cds { namespace container { Note that we define several function in foo_hash and foo_less functors for different argument types since we want call our \p %SplitListSet object by the key of type int and by the value of type foo. - The second attention: instead of using \p %LazyList in \p %SplitListSet traits we use a tag cds::contaner::lazy_list_tag for the lazy list. + The second attention: instead of using \p %LazyList in \p %SplitListSet traits we use a tag \p cds::contaner::lazy_list_tag for the lazy list. The split-list requires significant support from underlying ordered list class and it is not good idea to dive you into deep implementation details of split-list and ordered list interrelations. The tag paradigm simplifies split-list interface. @@ -73,13 +75,13 @@ namespace cds { namespace container { }; // SplitListSet traits - struct foo_set_traits: public cc::split_list::type_traits + struct foo_set_traits: public cc::split_list::traits { - typedef cc::lazy_list_tag ordered_list ; // what type of ordered list we want to use - typedef foo_hash hash ; // hash functor for our data stored in split-list set + typedef cc::lazy_list_tag ordered_list; // what type of ordered list we want to use + typedef foo_hash hash; // hash functor for our data stored in split-list set // Type traits for our LazyList class - struct ordered_list_traits: public cc::lazy_list::type_traits + struct ordered_list_traits: public cc::lazy_list::traits { typedef foo_less less ; // use our foo_less as comparator to order list nodes }; @@ -91,17 +93,17 @@ namespace cds { namespace container { typedef cc::SplitListSet< cds::gc::PTB, foo, foo_set_traits > foo_set; \endcode - You may use the modern option-based declaration instead of classic type-traits-based one: + You may use the modern option-based declaration instead of classic traits-based one: \code typedef cc:SplitListSet< cs::gc::PTB // GC used ,foo // type of data stored ,cc::split_list::make_traits< // metafunction to build split-list traits - cc::split_list::ordered_list // tag for underlying ordered list implementation + cc::split_list::ordered_list // tag for underlying ordered list implementation ,cc::opt::hash< foo_hash > // hash functor ,cc::split_list::ordered_list_traits< // ordered list traits desired - cc::lazy_list::make_traits< // metafunction to build lazy list traits - cc::opt::less< foo_less > // less-based compare functor + cc::lazy_list::make_traits< // metafunction to build lazy list traits + cc::opt::less< foo_less > // less-based compare functor >::type > >::type @@ -112,16 +114,15 @@ namespace cds { namespace container { Now, the set of type \p foo_set is ready to use in your program. - Note that in this example we show only mandatory type_traits parts, optional ones is the default and they are inherited - from cds::container::split_list::type_traits. - The cds library contains many other options for deep tuning of behavior of the split-list and - ordered-list containers. + Note that in this example we show only mandatory \p traits parts, optional ones is the default and they are inherited + from \p cds::container::split_list::traits. + There are many other options for deep tuning the split-list and ordered-list containers. */ template < class GC, class T, #ifdef CDS_DOXYGEN_INVOKED - class Traits = split_list::type_traits + class Traits = split_list::traits #else class Traits #endif @@ -140,15 +141,15 @@ namespace cds { namespace container { //@endcond public: - typedef Traits options ; ///< \p Traits template argument - typedef typename maker::gc gc ; ///< Garbage collector - typedef typename maker::value_type value_type ; ///< type of value stored in the list - typedef typename maker::ordered_list ordered_list ; ///< Underlying ordered list class + typedef GC gc; ///< Garbage collector + typedef T value_type; ///< Type of vlue to be stored in split-list + typedef Traits traits; ///< \p Traits template argument + typedef typename maker::ordered_list ordered_list; ///< Underlying ordered list class typedef typename base_class::key_comparator key_comparator; ///< key compare functor /// Hash functor for \p %value_type and all its derivatives that you use - typedef typename base_class::hash hash; - typedef typename base_class::item_counter item_counter ; ///< Item counter type + typedef typename base_class::hash hash; + typedef typename base_class::item_counter item_counter; ///< Item counter type protected: //@cond @@ -168,6 +169,17 @@ namespace cds { namespace container { return cxx_node_allocator().New( v ); } + template + static node_type * alloc_node( Args&&... args ) + { + return cxx_node_allocator().MoveNew( std::forward( args )... ); + } + + static void free_node( node_type * pNode ) + { + cxx_node_allocator().Delete( pNode ); + } + template bool find_( Q& val, Func f ) { @@ -181,17 +193,6 @@ namespace cds { namespace container { [&f]( node_type& item, Q& val ) { f(item.m_Value, val) ; } ); } - template - static node_type * alloc_node( Args&&... args ) - { - return cxx_node_allocator().MoveNew( std::forward(args)...); - } - - static void free_node( node_type * pNode ) - { - cxx_node_allocator().Delete( pNode ); - } - struct node_disposer { void operator()( node_type * pNode ) { @@ -209,7 +210,6 @@ namespace cds { namespace container { p.release(); return true; } - return false; } @@ -305,8 +305,8 @@ namespace cds { namespace container { /// Initializes split-ordered list of default capacity /** The default capacity is defined in bucket table constructor. - See intrusive::split_list::expandable_bucket_table, intrusive::split_list::static_bucket_table - which selects by intrusive::split_list::dynamic_bucket_table option. + See \p intrusive::split_list::expandable_bucket_table, \p intrusive::split_list::static_bucket_table + which selects by \p split_list::dynamic_bucket_table option. */ SplitListSet() : base_class() @@ -314,8 +314,8 @@ namespace cds { namespace container { /// Initializes split-ordered list SplitListSet( - size_t nItemCount ///< estimate average of item count - , size_t nLoadFactor = 1 ///< load factor - average item count per bucket. Small integer up to 8, default is 1. + size_t nItemCount ///< estimated average of item count + , size_t nLoadFactor = 1 ///< the load factor - average item count per bucket. Small integer up to 8, default is 1. ) : base_class( nItemCount, nLoadFactor ) {} @@ -388,10 +388,13 @@ namespace cds { namespace container { \code void func( value_type& val ); \endcode - where \p val is the item inserted. User-defined functor \p f should guarantee that during changing - \p val no any other changes could be made on this set's item by concurrent threads. - The user-defined functor is called only if the inserting is success. It may be passed by reference - using \p std::ref + where \p val is the item inserted. + + The user-defined functor is called only if the inserting is success. + + @warning For \ref cds_intrusive_MichaelList_hp "MichaelList" as the bucket see \ref cds_intrusive_item_creating "insert item troubleshooting". + \ref cds_intrusive_LazyList_hp "LazyList" provides exclusive access to inserted item and does not require any node-level + synchronization. */ template bool insert( Q const& val, Func f ) @@ -405,7 +408,7 @@ namespace cds { namespace container { return false; } - /// Inserts data of type \p %value_type constructed with std::forward(args)... + /// Inserts data of type \p value_type created from \p args /** Returns \p true if inserting successful, \p false otherwise. */ @@ -437,14 +440,15 @@ namespace cds { namespace container { - \p item - item of the set - \p val - argument \p val passed into the \p ensure function - The functor may change non-key fields of the \p item; however, \p func must guarantee - that during changing no any other modifications could be made on this item by concurrent threads. - - You may pass \p func argument by reference using \p std::ref + The functor may change non-key fields of the \p item. Returns std::pair where \p first is true if operation is successfull, \p second is true if new item has been added or \p false if the item with \p key already is in the set. + + @warning For \ref cds_intrusive_MichaelList_hp "MichaelList" as the bucket see \ref cds_intrusive_item_creating "insert item troubleshooting". + \ref cds_intrusive_LazyList_hp "LazyList" provides exclusive access to inserted item and does not require any node-level + synchronization. */ template std::pair ensure( Q const& val, Func func ) @@ -500,9 +504,8 @@ namespace cds { namespace container { void operator()(value_type const& val); }; \endcode - The functor may be passed by reference using boost:ref - Since the key of SplitListSet's \p value_type is not explicitly specified, + Since the key of split-list \p value_type is not explicitly specified, template parameter \p Q defines the key type searching in the list. The list item comparator should be able to compare the values of the type \p value_type and the type \p Q. @@ -576,17 +579,17 @@ namespace cds { namespace container { return extract_with_( dest.guard(), key, pred ); } - /// Finds the key \p val + /// Finds the key \p key /** \anchor cds_nonintrusive_SplitListSet_find_func - The function searches the item with key equal to \p val and calls the functor \p f for item found. + The function searches the item with key equal to \p key and calls the functor \p f for item found. The interface of \p Func functor is: \code struct functor { - void operator()( value_type& item, Q& val ); + void operator()( value_type& item, Q& key ); }; \endcode - where \p item is the item found, \p val is the find function argument. + where \p item is the item found, \p key is the find function argument. You may pass \p f argument by reference using \p std::ref. @@ -595,21 +598,21 @@ namespace cds { namespace container { The functor does not serialize simultaneous access to the set's \p item. If such access is possible you must provide your own synchronization schema on item level to exclude unsafe item modifications. - The \p val argument is non-const since it can be used as \p f functor destination i.e., the functor + The \p key argument is non-const since it can be used as \p f functor destination i.e., the functor may modify both arguments. Note the hash functor specified for class \p Traits template parameter should accept a parameter of type \p Q that can be not the same as \p value_type. - The function returns \p true if \p val is found, \p false otherwise. + The function returns \p true if \p key is found, \p false otherwise. */ template - bool find( Q& val, Func f ) + bool find( Q& key, Func f ) { - return find_( val, f ); + return find_( key, f ); } - /// Finds the key \p val using \p pred predicate for searching + /// Finds the key \p key using \p pred predicate for searching /** The function is an analog of \ref cds_nonintrusive_SplitListSet_find_func "find(Q&, Func)" but \p pred is used for key comparing. @@ -617,70 +620,27 @@ namespace cds { namespace container { \p Less must imply the same element order as the comparator used for building the set. */ template - bool find_with( Q& val, Less pred, Func f ) - { - return find_with_( val, pred, f ); - } - - /// Finds the key \p val - /** \anchor cds_nonintrusive_SplitListSet_find_cfunc - - The function searches the item with key equal to \p val and calls the functor \p f for item found. - The interface of \p Func functor is: - \code - struct functor { - void operator()( value_type& item, Q const& val ); - }; - \endcode - where \p item is the item found, \p val is the find function argument. - - You may pass \p f argument by reference using \p std::ref. - - The functor may change non-key fields of \p item. Note that the functor is only guarantee - that \p item cannot be disposed during functor is executing. - The functor does not serialize simultaneous access to the set's \p item. If such access is - possible you must provide your own synchronization schema on item level to exclude unsafe item modifications. - - Note the hash functor specified for class \p Traits template parameter - should accept a parameter of type \p Q that can be not the same as \p value_type. - - The function returns \p true if \p val is found, \p false otherwise. - */ - template - bool find( Q const& val, Func f ) - { - return find_( val, f ); - } - - /// Finds the key \p val using \p pred predicate for searching - /** - The function is an analog of \ref cds_nonintrusive_SplitListSet_find_cfunc "find(Q const&, Func)" - but \p pred is used for key comparing. - \p Less functor has the interface like \p std::less. - \p Less must imply the same element order as the comparator used for building the set. - */ - template - bool find_with( Q const& val, Less pred, Func f ) + bool find_with( Q& key, Less pred, Func f ) { - return find_with_( val, pred, f ); + return find_with_( key, pred, f ); } - /// Finds the key \p val + /// Finds the key \p key /** \anchor cds_nonintrusive_SplitListSet_find_val - The function searches the item with key equal to \p val + The function searches the item with key equal to \p key and returns \p true if it is found, and \p false otherwise. Note the hash functor specified for class \p Traits template parameter should accept a parameter of type \p Q that can be not the same as \ref value_type. */ template - bool find( Q const& val ) + bool find( Q const& key ) { - return base_class::find( val ); + return base_class::find( key ); } - /// Finds the key \p val using \p pred predicate for searching + /// Finds the key \p key using \p pred predicate for searching /** The function is an analog of \ref cds_nonintrusive_SplitListSet_find_val "find(Q const&)" but \p pred is used for key comparing. @@ -688,9 +648,9 @@ namespace cds { namespace container { \p Less must imply the same element order as the comparator used for building the set. */ template - bool find_with( Q const& val, Less pred ) + bool find_with( Q const& key, Less pred ) { - return base_class::find_with( val, typename maker::template predicate_wrapper::type() ); + return base_class::find_with( key, typename maker::template predicate_wrapper::type() ); } /// Finds the key \p key and return the item found @@ -741,11 +701,7 @@ namespace cds { namespace container { return get_with_( ptr.guard(), key, pred ); } - /// Clears the set (non-atomic) - /** - The function unlink all items from the set. - The function is not atomic and not lock-free and should be used for debugging only. - */ + /// Clears the set (not atomic) void clear() { base_class::clear(); diff --git a/cds/container/split_list_set_nogc.h b/cds/container/split_list_set_nogc.h index 7a133a5f..879eb59a 100644 --- a/cds/container/split_list_set_nogc.h +++ b/cds/container/split_list_set_nogc.h @@ -10,21 +10,24 @@ namespace cds { namespace container { - /// Split-ordered list set (template specialization for gc::nogc) + /// Split-ordered list set (template specialization for \p gc::nogc) /** @ingroup cds_nonintrusive_set \anchor cds_nonintrusive_SplitListSet_nogc - This specialization is intended for so-called persistent usage when no item + This specialization is so-called append-only container when no item reclamation may be performed. The class does not support deleting of list item. See \ref cds_nonintrusive_SplitListSet_hp "SplitListSet" for description of template parameters. - The interface of the specialization is a slightly different. + @warning Many member functions return an iterator pointing to an item. + The iterator can be used to set up field of the item, + but you should provide an exclusive access to it, + see \ref cds_intrusive_item_creating "insert item troubleshooting". */ template < class T, #ifdef CDS_DOXYGEN_INVOKED - class Traits = split_list::type_traits + class Traits = split_list::traits #else class Traits #endif @@ -38,24 +41,26 @@ namespace cds { namespace container { { protected: //@cond - typedef details::make_split_list_set< cds::gc::nogc, T, typename Traits::ordered_list, split_list::details::wrap_set_traits > options; - typedef typename options::type base_class; + typedef details::make_split_list_set< cds::gc::nogc, T, typename Traits::ordered_list, split_list::details::wrap_set_traits > maker; + typedef typename maker::type base_class; //@endcond public: - typedef typename options::gc gc ; ///< Garbage collector - typedef typename options::value_type value_type ; ///< type of value stored in the list - typedef typename options::ordered_list ordered_list ; ///< Underlying ordered list class - typedef typename base_class::key_comparator key_comparator ; ///< key comparison functor + typedef cds::gc::nogc gc; ///< Garbage collector + typedef T value_type; ///< type of value to be stored in the list + typedef Traits traits; ///< List traits + + typedef typename maker::ordered_list ordered_list; ///< Underlying ordered list class + typedef typename base_class::key_comparator key_comparator; ///< key comparison functor /// Hash functor for \ref value_type and all its derivatives that you use typedef typename base_class::hash hash; - typedef typename base_class::item_counter item_counter ; ///< Item counter type + typedef typename base_class::item_counter item_counter; ///< Item counter type protected: //@cond - typedef typename options::cxx_node_allocator cxx_node_allocator; - typedef typename options::node_type node_type; + typedef typename maker::cxx_node_allocator cxx_node_allocator; + typedef typename maker::node_type node_type; template static node_type * alloc_node(Q const& v ) @@ -87,8 +92,8 @@ namespace cds { namespace container { /// Initialize split-ordered list of default capacity /** The default capacity is defined in bucket table constructor. - See intrusive::split_list::expandable_bucket_table, intrusive::split_list::static_ducket_table - which selects by intrusive::split_list::dynamic_bucket_table option. + See \p intrusive::split_list::expandable_bucket_table, \p intrusive::split_list::static_bucket_table + which selects by \p split_list::dynamic_bucket_table option. */ SplitListSet() : base_class() @@ -96,7 +101,7 @@ namespace cds { namespace container { /// Initialize split-ordered list SplitListSet( - size_t nItemCount ///< estimate average of item count + size_t nItemCount ///< estimated average of item count , size_t nLoadFactor = 1 ///< load factor - average item count per bucket. Small integer up to 10, default is 1. ) : base_class( nItemCount, nLoadFactor ) @@ -244,9 +249,9 @@ namespace cds { namespace container { /** The function inserts \p val in the set if it does not contain an item with key equal to \p val. - The \ref value_type should be constructible from a value of type \p Q. + The \p value_type should be constructible from a value of type \p Q. - Return an iterator pointing to inserted item if success \ref end() otherwise + Return an iterator pointing to inserted item if success \p end() otherwise */ template iterator insert( const Q& val ) @@ -254,9 +259,9 @@ namespace cds { namespace container { return insert_node( alloc_node( val ) ); } - /// Inserts data of type \ref value_type constructed with std::forward(args)... + /// Inserts data of type \p value_type created from \p args /** - Return an iterator pointing to inserted item if success \ref end() otherwise + Return an iterator pointing to inserted item if success \p end() otherwise */ template iterator emplace( Args&&... args ) @@ -270,7 +275,7 @@ namespace cds { namespace container { Otherwise, the function returns an iterator that points to item found. The \p value_type should be constructible from a value of type \p Q. - Returns std::pair where \p first is an iterator pointing to + Returns std::pair where \p first is an iterator pointing to item found or inserted, \p second is true if new item has been added or \p false if the item already is in the set. */ @@ -288,12 +293,12 @@ namespace cds { namespace container { return std::make_pair( iterator(ret.first), ret.second ); } - /// Find the key \p val + /// Find the key \p key /** \anchor cds_nonintrusive_SplitListSet_nogc_find The function searches the item with key equal to \p key and returns an iterator pointed to item found if the key is found, - and \ref end() otherwise + and \ref end() otherwise. */ template iterator find( Q const& key ) @@ -301,7 +306,7 @@ namespace cds { namespace container { return iterator( base_class::find_( key )); } - /// Finds the key \p val using \p pred predicate for searching + /// Finds the key \p key using \p pred predicate for searching /** The function is an analog of \ref cds_nonintrusive_SplitListSet_nogc_find "find(Q const&)" but \p pred is used for key comparing. @@ -311,7 +316,7 @@ namespace cds { namespace container { template iterator find_with( Q const& key, Less pred ) { - return iterator( base_class::find_with_( key, typename options::template predicate_wrapper::type() )); + return iterator( base_class::find_with_( key, typename maker::template predicate_wrapper::type() )); } /// Checks if the set is empty diff --git a/cds/container/split_list_set_rcu.h b/cds/container/split_list_set_rcu.h index 8ecd00c0..51d64583 100644 --- a/cds/container/split_list_set_rcu.h +++ b/cds/container/split_list_set_rcu.h @@ -16,26 +16,23 @@ namespace cds { namespace container { - [2003] Ori Shalev, Nir Shavit "Split-Ordered Lists - Lock-free Resizable Hash Tables" - [2008] Nir Shavit "The Art of Multiprocessor Programming" - See intrusive::SplitListSet for a brief description of the split-list algorithm. + See \p intrusive::SplitListSet for a brief description of the split-list algorithm. Template parameters: - \p RCU - one of \ref cds_urcu_gc "RCU type" - - \p T - type stored in the split-list. The type must be default- and copy-constructible. - - \p Traits - type traits, default is split_list::type_traits. Instead of declaring split_list::type_traits -based - struct you may apply option-based notation with split_list::make_traits metafunction. + - \p T - type of the value to be stored in the split-list. + - \p Traits - type traits, default is \p split_list::traits. Instead of declaring \p split_list::traits -based + struct you can apply option-based notation with \p split_list::make_traits metafunction. Iterators The class supports a forward iterator (\ref iterator and \ref const_iterator). - The iteration is ordered. + The iteration is unordered. You may iterate over split-list set items only under RCU lock. Only in this case the iterator is thread-safe since while RCU is locked any set's item cannot be reclaimed. - The requirement of RCU lock during iterating means that deletion of the elements (i.e. \ref erase) - is not possible. - @warning The iterator object cannot be passed between threads \warning Due to concurrent nature of skip-list set it is not guarantee that you can iterate @@ -65,13 +62,13 @@ namespace cds { namespace container { bool operator !=(iterator const& i ) const; }; \endcode - Note, the iterator object returned by \ref end, \p cend member functions points to \p nullptr and should not be dereferenced. + Note, the iterator object returned by \p end(), \p cend() member functions points to \p nullptr and should not be dereferenced. \par Usage You should decide what garbage collector you want, and what ordered list you want to use. Split-ordered list - is an original data structure based on an ordered list. Suppose, you want construct split-list set based on cds::urcu::general_buffered<> GC - and LazyList as ordered list implementation. So, you beginning your program with following include: + is an original data structure based on an ordered list. Suppose, you want construct split-list set based on \p cds::urcu::general_buffered<> GC + and \p LazyList as ordered list implementation. So, you beginning your program with following include: \code #include #include @@ -91,10 +88,10 @@ namespace cds { namespace container { - then, the header for RCU-based split-list set cds/container/split_list_set_rcu.h. Now, you should declare traits for split-list set. The main parts of traits are a hash functor for the set and a comparing functor for ordered list. - Note that we define several function in foo_hash and foo_less functors for different argument types since we want call our \p %SplitListSet - object by the key of type int and by the value of type foo. + Note that we define several function in \p foo_hash and \p foo_less functors for different argument types since we want call our \p %SplitListSet + object by the key of type \p int and by the value of type \p foo. - The second attention: instead of using LazyList in SplitListSet traits we use a tag cds::contaner::lazy_list_tag for the lazy list. + The second attention: instead of using \p %LazyList in \p %SplitListSet traits we use \p cds::contaner::lazy_list_tag tag for the lazy list. The split-list requires significant support from underlying ordered list class and it is not good idea to dive you into deep implementation details of split-list and ordered list interrelations. The tag paradigm simplifies split-list interface. @@ -113,13 +110,13 @@ namespace cds { namespace container { }; // SplitListSet traits - struct foo_set_traits: public cc::split_list::type_traits + struct foo_set_traits: public cc::split_list::traits { typedef cc::lazy_list_tag ordered_list ; // what type of ordered list we want to use typedef foo_hash hash ; // hash functor for our data stored in split-list set // Type traits for our LazyList class - struct ordered_list_traits: public cc::lazy_list::type_traits + struct ordered_list_traits: public cc::lazy_list::traits { typedef foo_less less ; // use our foo_less as comparator to order list nodes }; @@ -139,29 +136,28 @@ namespace cds { namespace container { ,cc::split_list::make_traits< // metafunction to build split-list traits cc::split_list::ordered_list // tag for underlying ordered list implementation ,cc::opt::hash< foo_hash > // hash functor - ,cc::split_list::ordered_list_traits< // ordered list traits desired + ,cc::split_list::ordered_list_traits< // ordered list traits cc::lazy_list::make_traits< // metafunction to build lazy list traits - cc::opt::less< foo_less > // less-based compare functor + cc::opt::less< foo_less > // less-based compare functor >::type > >::type > foo_set; \endcode - In case of option-based declaration using split_list::make_traits metafunction + In case of option-based declaration using \p split_list::make_traits metafunction the struct \p foo_set_traits is not required. Now, the set of type \p foo_set is ready to use in your program. - Note that in this example we show only mandatory type_traits parts, optional ones is the default and they are inherited - from cds::container::split_list::type_traits. - The cds library contains many other options for deep tuning of behavior of the split-list and - ordered-list containers. + Note that in this example we show only mandatory \p traits parts, optional ones is the default and they are inherited + from \p container::split_list::traits. + There are many other options for deep tuning of the split-list and ordered-list containers. */ template < class RCU, class T, #ifdef CDS_DOXYGEN_INVOKED - class Traits = split_list::type_traits + class Traits = split_list::traits #else class Traits #endif @@ -180,15 +176,16 @@ namespace cds { namespace container { //@endcond public: - typedef Traits options ; ///< \p Traits template argument - typedef typename maker::gc gc ; ///< Garbage collector - typedef typename maker::value_type value_type ; ///< type of value stored in the list - typedef typename maker::ordered_list ordered_list ; ///< Underlying ordered list class + typedef cds::urcu::gc< RCU > gc; ///< RCU-based garbage collector + typedef T value_type; ///< Type of value to be storedin the set + typedef Traits traits; ///< \p Traits template argument + + typedef typename maker::ordered_list ordered_list; ///< Underlying ordered list class typedef typename base_class::key_comparator key_comparator; ///< key compare functor /// Hash functor for \ref value_type and all its derivatives that you use typedef typename base_class::hash hash; - typedef typename base_class::item_counter item_counter ; ///< Item counter type + typedef typename base_class::item_counter item_counter; ///< Item counter type typedef typename base_class::rcu_lock rcu_lock ; ///< RCU scoped lock /// Group of \p extract_xxx functions require external locking if underlying ordered list requires that @@ -206,13 +203,6 @@ namespace cds { namespace container { protected: //@cond - - template - static node_type * alloc_node(Q const& v ) - { - return cxx_node_allocator().New( v ); - } - template bool find_( Q& val, Func f ) { @@ -226,6 +216,11 @@ namespace cds { namespace container { [&f]( node_type& item, Q& val ) { f(item.m_Value, val) ; } ); } + template + static node_type * alloc_node( Q const& v ) + { + return cxx_node_allocator().New( v ); + } template static node_type * alloc_node( Args&&... args ) @@ -350,8 +345,8 @@ namespace cds { namespace container { /// Initializes split-ordered list of default capacity /** The default capacity is defined in bucket table constructor. - See intrusive::split_list::expandable_bucket_table, intrusive::split_list::static_bucket_table - which selects by intrusive::split_list::dynamic_bucket_table option. + See \p intrusive::split_list::expandable_bucket_table, \p intrusive::split_list::static_bucket_table + which selects by \p container::split_list::dynamic_bucket_table option. */ SplitListSet() : base_class() @@ -359,7 +354,7 @@ namespace cds { namespace container { /// Initializes split-ordered list SplitListSet( - size_t nItemCount ///< estimate average of item count + size_t nItemCount ///< estimated average of item count , size_t nLoadFactor = 1 ///< load factor - average item count per bucket. Small integer up to 8, default is 1. ) : base_class( nItemCount, nLoadFactor ) @@ -434,15 +429,14 @@ namespace cds { namespace container { \endcode where \p val is the item inserted. User-defined functor \p f should guarantee that during changing \p val no any other changes could be made on this set's item by concurrent threads. - The user-defined functor is called only if the inserting is success. It may be passed by reference - using \p std::ref + The user-defined functor is called only if the inserting is success. The function applies RCU lock internally. */ template - bool insert( Q const& val, Func f ) + bool insert( Q const& key, Func f ) { - scoped_node_ptr pNode( alloc_node( val )); + scoped_node_ptr pNode( alloc_node( key )); if ( base_class::insert( *pNode, [&f](node_type& node) { f( node.m_Value ) ; } )) { pNode.release(); @@ -451,7 +445,7 @@ namespace cds { namespace container { return false; } - /// Inserts data of type \p value_type constructed with std::forward(args)... + /// Inserts data of type \p value_type created from \p args /** Returns \p true if inserting successful, \p false otherwise. @@ -463,17 +457,13 @@ namespace cds { namespace container { return insert_node( alloc_node( std::forward(args)...)); } - /// Ensures that the \p item exists in the set + /// Ensures that the \p val exists in the set /** The operation performs inserting or changing data with lock-free manner. If the \p val key not found in the set, then the new item created from \p val is inserted into the set. Otherwise, the functor \p func is called with the item found. - The functor \p Func should be a function with signature: - \code - void func( bool bNew, value_type& item, const Q& val ); - \endcode - or a functor: + The functor \p Func signature is: \code struct my_functor { void operator()( bool bNew, value_type& item, const Q& val ); @@ -483,13 +473,11 @@ namespace cds { namespace container { with arguments: - \p bNew - \p true if the item has been inserted, \p false otherwise - \p item - item of the set - - \p val - argument \p val passed into the \p ensure function + - \p val - argument \p val passed into the \p %ensure() function The functor may change non-key fields of the \p item; however, \p func must guarantee that during changing no any other modifications could be made on this item by concurrent threads. - You may pass \p func argument by reference using \p std::ref - The function applies RCU lock internally. Returns std::pair where \p first is true if operation is successfull, @@ -513,8 +501,7 @@ namespace cds { namespace container { /// Deletes \p key from the set /** \anchor cds_nonintrusive_SplitListSet_rcu_erase_val - Since the key of SplitListSet's item type \p value_type is not explicitly specified, - template parameter \p Q defines the key type searching in the list. + Template parameter of type \p Q defines the key type searching in the list. The set item comparator should be able to compare the values of type \p value_type and the type \p Q. @@ -553,10 +540,8 @@ namespace cds { namespace container { void operator()(value_type const& val); }; \endcode - The functor may be passed by reference using boost:ref - Since the key of SplitListSet's \p value_type is not explicitly specified, - template parameter \p Q defines the key type searching in the list. + Template parameter of type \p Q defines the key type searching in the list. The list item comparator should be able to compare the values of the type \p value_type and the type \p Q. @@ -586,9 +571,9 @@ namespace cds { namespace container { /// Extracts an item from the set /** \anchor cds_nonintrusive_SplitListSet_rcu_extract - The function searches an item with key equal to \p val in the set, + The function searches an item with key equal to \p key in the set, unlinks it from the set, places item pointer into \p dest argument, and returns \p true. - If the item with the key equal to \p val is not found the function return \p false. + If the item with the key equal to \p key is not found the function return \p false. @note The function does NOT call RCU read-side lock or synchronization, and does NOT dispose the item found. It just excludes the item from the set @@ -622,9 +607,9 @@ namespace cds { namespace container { \endcode */ template - bool extract( exempt_ptr& dest, Q const& val ) + bool extract( exempt_ptr& dest, Q const& key ) { - node_type * pNode = base_class::extract_( val, key_comparator() ); + node_type * pNode = base_class::extract_( key, key_comparator() ); if ( pNode ) { dest = pNode; return true; @@ -640,9 +625,9 @@ namespace cds { namespace container { \p pred must imply the same element order as the comparator used for building the set. */ template - bool extract_with( exempt_ptr& dest, Q const& val, Less pred ) + bool extract_with( exempt_ptr& dest, Q const& key, Less pred ) { - node_type * pNode = base_class::extract_with_( val, typename maker::template predicate_wrapper::type()); + node_type * pNode = base_class::extract_with_( key, typename maker::template predicate_wrapper::type()); if ( pNode ) { dest = pNode; return true; @@ -650,42 +635,37 @@ namespace cds { namespace container { return false; } - /// Finds the key \p val + /// Finds the key \p key /** \anchor cds_nonintrusive_SplitListSet_rcu_find_func - The function searches the item with key equal to \p val and calls the functor \p f for item found. + The function searches the item with key equal to \p key and calls the functor \p f for item found. The interface of \p Func functor is: \code struct functor { - void operator()( value_type& item, Q& val ); + void operator()( value_type& item, Q& key ); }; \endcode - where \p item is the item found, \p val is the find function argument. - - You may pass \p f argument by reference using \p std::ref. + where \p item is the item found, \p key is the find function argument. The functor may change non-key fields of \p item. Note that the functor is only guarantee that \p item cannot be disposed during functor is executing. The functor does not serialize simultaneous access to the set's \p item. If such access is possible you must provide your own synchronization schema on item level to exclude unsafe item modifications. - The \p val argument is non-const since it can be used as \p f functor destination i.e., the functor - may modify both arguments. - Note the hash functor specified for class \p Traits template parameter should accept a parameter of type \p Q that can be not the same as \p value_type. The function makes RCU lock internally. - The function returns \p true if \p val is found, \p false otherwise. + The function returns \p true if \p key is found, \p false otherwise. */ template - bool find( Q& val, Func f ) + bool find( Q& key, Func f ) { - return find_( val, f ); + return find_( key, f ); } - /// Finds the key \p val using \p pred predicate for searching + /// Finds the key \p key using \p pred predicate for searching /** The function is an analog of \ref cds_nonintrusive_SplitListSet_rcu_find_func "find(Q&, Func)" but \p pred is used for key comparing. @@ -693,60 +673,15 @@ namespace cds { namespace container { \p Less must imply the same element order as the comparator used for building the set. */ template - bool find_with( Q& val, Less pred, Func f ) - { - return find_with_( val, pred, f ); - } - - /// Find the key \p val - /** \anchor cds_nonintrusive_SplitListSet_rcu_find_cfunc - - The function searches the item with key equal to \p val and calls the functor \p f for item found. - The interface of \p Func functor is: - \code - struct functor { - void operator()( value_type& item, Q const& val ); - }; - \endcode - where \p item is the item found, \p val is the find function argument. - - You may pass \p f argument by reference using \p std::ref. - - The functor may change non-key fields of \p item. Note that the functor is only guarantee - that \p item cannot be disposed during functor is executing. - The functor does not serialize simultaneous access to the set's \p item. If such access is - possible you must provide your own synchronization schema on item level to exclude unsafe item modifications. - - Note the hash functor specified for class \p Traits template parameter - should accept a parameter of type \p Q that can be not the same as \p value_type. - - The function makes RCU lock internally. - - The function returns \p true if \p val is found, \p false otherwise. - */ - template - bool find( Q const& val, Func f ) - { - return find_( val, f ); - } - - /// Finds the key \p val using \p pred predicate for searching - /** - The function is an analog of \ref cds_nonintrusive_SplitListSet_rcu_find_cfunc "find(Q const&, Func)" - but \p pred is used for key comparing. - \p Less functor has the interface like \p std::less. - \p Less must imply the same element order as the comparator used for building the set. - */ - template - bool find_with( Q const& val, Less pred, Func f ) + bool find_with( Q& key, Less pred, Func f ) { - return find_with_( val, pred, f ); + return find_with_( key, pred, f ); } - /// Finds the key \p val + /// Finds the key \p key /** \anchor cds_nonintrusive_SplitListSet_rcu_find_val - The function searches the item with key equal to \p val + The function searches the item with key equal to \p key and returns \p true if it is found, and \p false otherwise. Note the hash functor specified for class \p Traits template parameter @@ -755,12 +690,12 @@ namespace cds { namespace container { The function makes RCU lock internally. */ template - bool find( Q const& val ) + bool find( Q const& key ) { - return base_class::find( val ); + return base_class::find( key ); } - /// Finds the key \p val using \p pred predicate for searching + /// Finds the key \p key using \p pred predicate for searching /** The function is an analog of \ref cds_nonintrusive_SplitListSet_rcu_find_val "find(Q const&)" but \p pred is used for key comparing. @@ -768,15 +703,15 @@ namespace cds { namespace container { \p Less must imply the same element order as the comparator used for building the set. */ template - bool find_with( Q const& val, Less pred ) + bool find_with( Q const& key, Less pred ) { - return base_class::find_with( val, typename maker::template predicate_wrapper::type() ); + return base_class::find_with( key, typename maker::template predicate_wrapper::type() ); } - /// Finds the key \p val and return the item found + /// Finds the key \p key and return the item found /** \anchor cds_nonintrusive_SplitListSet_rcu_get - The function searches the item with key equal to \p val and returns the pointer to item found. - If \p val is not found it returns \p nullptr. + The function searches the item with key equal to \p key and returns the pointer to item found. + If \p key is not found it returns \p nullptr. Note the compare functor should accept a parameter of type \p Q that can be not the same as \p value_type. @@ -802,13 +737,13 @@ namespace cds { namespace container { \endcode */ template - value_type * get( Q const& val ) + value_type * get( Q const& key ) { - node_type * pNode = base_class::get( val ); + node_type * pNode = base_class::get( key ); return pNode ? &pNode->m_Value : nullptr; } - /// Finds the key \p val and return the item found + /// Finds the key \p key and return the item found /** The function is an analog of \ref cds_nonintrusive_SplitListSet_rcu_get "get(Q const&)" but \p pred is used for comparing the keys. @@ -818,19 +753,13 @@ namespace cds { namespace container { \p pred must imply the same element order as the comparator used for building the set. */ template - value_type * get_with( Q const& val, Less pred ) + value_type * get_with( Q const& key, Less pred ) { - node_type * pNode = base_class::get_with( val, typename maker::template predicate_wrapper::type()); + node_type * pNode = base_class::get_with( key, typename maker::template predicate_wrapper::type()); return pNode ? &pNode->m_Value : nullptr; } - /// Clears the set (non-atomic) - /** - The function unlink all items from the set. - The function is not atomic and not lock-free and should be used for debugging only. - - RCU \p synchronize method can be called. RCU should not be locked. - */ + /// Clears the set (not atomic) void clear() { base_class::clear(); @@ -852,8 +781,6 @@ namespace cds { namespace container { return base_class::size(); } }; - - }} // namespace cds::container #endif // #ifndef __CDS_CONTAINER_SPLIT_LIST_SET_RCU_H diff --git a/tests/test-hdr/set/hdr_set.h b/tests/test-hdr/set/hdr_set.h index 997be244..72c7a0e5 100644 --- a/tests/test-hdr/set/hdr_set.h +++ b/tests/test-hdr/set/hdr_set.h @@ -888,10 +888,12 @@ namespace set { void Split_HP_cmp(); void Split_HP_less(); void Split_HP_cmpmix(); + void Split_HP_cmpmix_stat(); void Split_DHP_cmp(); void Split_DHP_less(); void Split_DHP_cmpmix(); + void Split_DHP_cmpmix_stat(); void Split_RCU_GPI_cmp(); void Split_RCU_GPI_less(); @@ -916,15 +918,18 @@ namespace set { void Split_nogc_cmp(); void Split_nogc_less(); void Split_nogc_cmpmix(); + void Split_nogc_cmpmix_stat(); void Split_Lazy_HP_cmp(); void Split_Lazy_HP_less(); void Split_Lazy_HP_cmpmix(); + void Split_Lazy_HP_cmpmix_stat(); void Split_Lazy_DHP_cmp(); void Split_Lazy_DHP_less(); void Split_Lazy_DHP_cmpmix(); + void Split_Lazy_DHP_cmpmix_stat(); void Split_Lazy_RCU_GPI_cmp(); void Split_Lazy_RCU_GPI_less(); @@ -949,6 +954,7 @@ namespace set { void Split_Lazy_nogc_cmp(); void Split_Lazy_nogc_less(); void Split_Lazy_nogc_cmpmix(); + void Split_Lazy_nogc_cmpmix_stat(); CPPUNIT_TEST_SUITE(HashSetHdrTest) CPPUNIT_TEST(Michael_HP_cmp) @@ -1018,10 +1024,12 @@ namespace set { CPPUNIT_TEST(Split_HP_cmp) CPPUNIT_TEST(Split_HP_less) CPPUNIT_TEST(Split_HP_cmpmix) + CPPUNIT_TEST( Split_HP_cmpmix_stat ) CPPUNIT_TEST(Split_DHP_cmp) CPPUNIT_TEST(Split_DHP_less) CPPUNIT_TEST(Split_DHP_cmpmix) + CPPUNIT_TEST( Split_DHP_cmpmix_stat ) CPPUNIT_TEST(Split_RCU_GPI_cmp) CPPUNIT_TEST(Split_RCU_GPI_less) @@ -1046,14 +1054,17 @@ namespace set { CPPUNIT_TEST(Split_nogc_cmp) CPPUNIT_TEST(Split_nogc_less) CPPUNIT_TEST(Split_nogc_cmpmix) + CPPUNIT_TEST( Split_nogc_cmpmix_stat ) CPPUNIT_TEST(Split_Lazy_HP_cmp) CPPUNIT_TEST(Split_Lazy_HP_less) CPPUNIT_TEST(Split_Lazy_HP_cmpmix) + CPPUNIT_TEST( Split_Lazy_HP_cmpmix_stat ) CPPUNIT_TEST(Split_Lazy_DHP_cmp) CPPUNIT_TEST(Split_Lazy_DHP_less) CPPUNIT_TEST(Split_Lazy_DHP_cmpmix) + CPPUNIT_TEST( Split_Lazy_DHP_cmpmix_stat ) CPPUNIT_TEST(Split_Lazy_RCU_GPI_cmp) CPPUNIT_TEST(Split_Lazy_RCU_GPI_less) @@ -1078,6 +1089,7 @@ namespace set { CPPUNIT_TEST(Split_Lazy_nogc_cmp) CPPUNIT_TEST(Split_Lazy_nogc_less) CPPUNIT_TEST(Split_Lazy_nogc_cmpmix) + CPPUNIT_TEST( Split_Lazy_nogc_cmpmix_stat ) CPPUNIT_TEST_SUITE_END() diff --git a/tests/test-hdr/set/hdr_splitlist_set_dhp.cpp b/tests/test-hdr/set/hdr_splitlist_set_dhp.cpp index 058c9469..c4746985 100644 --- a/tests/test-hdr/set/hdr_splitlist_set_dhp.cpp +++ b/tests/test-hdr/set/hdr_splitlist_set_dhp.cpp @@ -7,7 +7,7 @@ namespace set { namespace { - struct PTB_cmp_traits: public cc::split_list::type_traits + struct DHP_cmp_traits: public cc::split_list::traits { typedef cc::michael_list_tag ordered_list; typedef HashSetHdrTest::hash_int hash; @@ -15,13 +15,13 @@ namespace set { typedef cc::opt::v::relaxed_ordering memory_model; enum { dynamic_bucket_table = false }; - struct ordered_list_traits: public cc::michael_list::type_traits + struct ordered_list_traits: public cc::michael_list::traits { typedef HashSetHdrTest::cmp compare; }; }; - struct PTB_less_traits: public cc::split_list::type_traits + struct DHP_less_traits: public cc::split_list::traits { typedef cc::michael_list_tag ordered_list; typedef HashSetHdrTest::hash_int hash; @@ -29,35 +29,40 @@ namespace set { typedef cc::opt::v::sequential_consistent memory_model; enum { dynamic_bucket_table = false }; - struct ordered_list_traits: public cc::michael_list::type_traits + struct ordered_list_traits: public cc::michael_list::traits { typedef HashSetHdrTest::less less; }; }; - struct PTB_cmpmix_traits: public cc::split_list::type_traits + struct DHP_cmpmix_traits: public cc::split_list::traits { typedef cc::michael_list_tag ordered_list; typedef HashSetHdrTest::hash_int hash; typedef HashSetHdrTest::simple_item_counter item_counter; - struct ordered_list_traits: public cc::michael_list::type_traits + struct ordered_list_traits: public cc::michael_list::traits { typedef HashSetHdrTest::cmp compare; typedef HashSetHdrTest::less less; }; }; + + struct DHP_cmpmix_stat_traits : public DHP_cmpmix_traits + { + typedef cc::split_list::stat<> stat; + }; } - void HashSetHdrTest::Split_PTB_cmp() + void HashSetHdrTest::Split_DHP_cmp() { // traits-based version - typedef cc::SplitListSet< cds::gc::PTB, item, PTB_cmp_traits > set; + typedef cc::SplitListSet< cds::gc::DHP, item, DHP_cmp_traits > set; test_int< set >(); // option-based version - typedef cc::SplitListSet< cds::gc::PTB, item, + typedef cc::SplitListSet< cds::gc::DHP, item, cc::split_list::make_traits< cc::split_list::ordered_list ,cc::opt::hash< hash_int > @@ -74,15 +79,15 @@ namespace set { test_int< opt_set >(); } - void HashSetHdrTest::Split_PTB_less() + void HashSetHdrTest::Split_DHP_less() { // traits-based version - typedef cc::SplitListSet< cds::gc::PTB, item, PTB_less_traits > set; + typedef cc::SplitListSet< cds::gc::DHP, item, DHP_less_traits > set; test_int< set >(); // option-based version - typedef cc::SplitListSet< cds::gc::PTB, item, + typedef cc::SplitListSet< cds::gc::DHP, item, cc::split_list::make_traits< cc::split_list::ordered_list ,cc::opt::hash< hash_int > @@ -99,14 +104,37 @@ namespace set { test_int< opt_set >(); } - void HashSetHdrTest::Split_PTB_cmpmix() + void HashSetHdrTest::Split_DHP_cmpmix() + { + // traits-based version + typedef cc::SplitListSet< cds::gc::DHP, item, DHP_cmpmix_traits > set; + test_int< set >(); + + // option-based version + typedef cc::SplitListSet< cds::gc::DHP, item, + cc::split_list::make_traits< + cc::split_list::ordered_list + ,cc::opt::hash< hash_int > + ,cc::opt::item_counter< simple_item_counter > + ,cc::split_list::ordered_list_traits< + cc::michael_list::make_traits< + cc::opt::less< less > + ,cc::opt::compare< cmp > + >::type + > + >::type + > opt_set; + test_int< opt_set >(); + } + + void HashSetHdrTest::Split_DHP_cmpmix_stat() { // traits-based version - typedef cc::SplitListSet< cds::gc::PTB, item, PTB_cmpmix_traits > set; + typedef cc::SplitListSet< cds::gc::DHP, item, DHP_cmpmix_stat_traits > set; test_int< set >(); // option-based version - typedef cc::SplitListSet< cds::gc::PTB, item, + typedef cc::SplitListSet< cds::gc::DHP, item, cc::split_list::make_traits< cc::split_list::ordered_list ,cc::opt::hash< hash_int > @@ -117,6 +145,7 @@ namespace set { ,cc::opt::compare< cmp > >::type > + ,cds::opt::stat< cc::split_list::stat<> > >::type > opt_set; test_int< opt_set >(); diff --git a/tests/test-hdr/set/hdr_splitlist_set_hp.cpp b/tests/test-hdr/set/hdr_splitlist_set_hp.cpp index 67e8c49c..ec74138b 100644 --- a/tests/test-hdr/set/hdr_splitlist_set_hp.cpp +++ b/tests/test-hdr/set/hdr_splitlist_set_hp.cpp @@ -7,7 +7,7 @@ namespace set { namespace { - struct HP_cmp_traits: public cc::split_list::type_traits + struct HP_cmp_traits: public cc::split_list::traits { typedef cc::michael_list_tag ordered_list; typedef HashSetHdrTest::hash_int hash; @@ -15,13 +15,13 @@ namespace set { typedef cc::opt::v::relaxed_ordering memory_model; enum { dynamic_bucket_table = false }; - struct ordered_list_traits: public cc::michael_list::type_traits + struct ordered_list_traits: public cc::michael_list::traits { typedef HashSetHdrTest::cmp compare; }; }; - struct HP_less_traits: public cc::split_list::type_traits + struct HP_less_traits: public cc::split_list::traits { typedef cc::michael_list_tag ordered_list; typedef HashSetHdrTest::hash_int hash; @@ -29,24 +29,29 @@ namespace set { typedef cc::opt::v::sequential_consistent memory_model; enum { dynamic_bucket_table = false }; - struct ordered_list_traits: public cc::michael_list::type_traits + struct ordered_list_traits: public cc::michael_list::traits { typedef HashSetHdrTest::less less; }; }; - struct HP_cmpmix_traits: public cc::split_list::type_traits + struct HP_cmpmix_traits: public cc::split_list::traits { typedef cc::michael_list_tag ordered_list; typedef HashSetHdrTest::hash_int hash; typedef HashSetHdrTest::simple_item_counter item_counter; - struct ordered_list_traits: public cc::michael_list::type_traits + struct ordered_list_traits: public cc::michael_list::traits { typedef HashSetHdrTest::cmp compare; typedef HashSetHdrTest::less less; }; }; + + struct HP_cmpmix_stat_traits : public HP_cmpmix_traits + { + typedef cc::split_list::stat<> stat; + }; } void HashSetHdrTest::Split_HP_cmp() @@ -122,6 +127,29 @@ namespace set { test_int< opt_set >(); } + void HashSetHdrTest::Split_HP_cmpmix_stat() + { + // traits-based version + typedef cc::SplitListSet< cds::gc::HP, item, HP_cmpmix_stat_traits > set; + test_int< set >(); + + // option-based version + typedef cc::SplitListSet< cds::gc::HP, item, + cc::split_list::make_traits< + cc::split_list::ordered_list + ,cc::opt::hash< hash_int > + ,cc::opt::item_counter< simple_item_counter > + ,cc::split_list::ordered_list_traits< + cc::michael_list::make_traits< + cc::opt::less< less > + ,cc::opt::compare< cmp > + >::type + > + ,cds::opt::stat< cc::split_list::stat<> > + >::type + > opt_set; + test_int< opt_set >(); + } } // namespace set diff --git a/tests/test-hdr/set/hdr_splitlist_set_lazy_dhp.cpp b/tests/test-hdr/set/hdr_splitlist_set_lazy_dhp.cpp index 6195103d..b6151241 100644 --- a/tests/test-hdr/set/hdr_splitlist_set_lazy_dhp.cpp +++ b/tests/test-hdr/set/hdr_splitlist_set_lazy_dhp.cpp @@ -7,7 +7,7 @@ namespace set { namespace { - struct PTB_cmp_traits: public cc::split_list::type_traits + struct DHP_cmp_traits: public cc::split_list::traits { typedef cc::lazy_list_tag ordered_list; typedef HashSetHdrTest::hash_int hash; @@ -15,13 +15,13 @@ namespace set { typedef cc::opt::v::relaxed_ordering memory_model; enum { dynamic_bucket_table = false }; - struct ordered_list_traits: public cc::lazy_list::type_traits + struct ordered_list_traits: public cc::lazy_list::traits { typedef HashSetHdrTest::cmp compare; }; }; - struct PTB_less_traits: public cc::split_list::type_traits + struct DHP_less_traits: public cc::split_list::traits { typedef cc::lazy_list_tag ordered_list; typedef HashSetHdrTest::hash_int hash; @@ -29,35 +29,40 @@ namespace set { typedef cc::opt::v::sequential_consistent memory_model; enum { dynamic_bucket_table = false }; - struct ordered_list_traits: public cc::lazy_list::type_traits + struct ordered_list_traits: public cc::lazy_list::traits { typedef HashSetHdrTest::less less; }; }; - struct PTB_cmpmix_traits: public cc::split_list::type_traits + struct DHP_cmpmix_traits: public cc::split_list::traits { typedef cc::lazy_list_tag ordered_list; typedef HashSetHdrTest::hash_int hash; typedef HashSetHdrTest::simple_item_counter item_counter; - struct ordered_list_traits: public cc::lazy_list::type_traits + struct ordered_list_traits: public cc::lazy_list::traits { typedef HashSetHdrTest::cmp compare; typedef HashSetHdrTest::less less; }; }; + + struct DHP_cmpmix_stat_traits : public DHP_cmpmix_traits + { + typedef cc::split_list::stat<> stat; + }; } - void HashSetHdrTest::Split_Lazy_PTB_cmp() + void HashSetHdrTest::Split_Lazy_DHP_cmp() { // traits-based version - typedef cc::SplitListSet< cds::gc::PTB, item, PTB_cmp_traits > set; + typedef cc::SplitListSet< cds::gc::DHP, item, DHP_cmp_traits > set; test_int< set >(); // option-based version - typedef cc::SplitListSet< cds::gc::PTB, item, + typedef cc::SplitListSet< cds::gc::DHP, item, cc::split_list::make_traits< cc::split_list::ordered_list ,cc::opt::hash< hash_int > @@ -74,15 +79,15 @@ namespace set { test_int< opt_set >(); } - void HashSetHdrTest::Split_Lazy_PTB_less() + void HashSetHdrTest::Split_Lazy_DHP_less() { // traits-based version - typedef cc::SplitListSet< cds::gc::PTB, item, PTB_less_traits > set; + typedef cc::SplitListSet< cds::gc::DHP, item, DHP_less_traits > set; test_int< set >(); // option-based version - typedef cc::SplitListSet< cds::gc::PTB, item, + typedef cc::SplitListSet< cds::gc::DHP, item, cc::split_list::make_traits< cc::split_list::ordered_list ,cc::opt::hash< hash_int > @@ -99,14 +104,14 @@ namespace set { test_int< opt_set >(); } - void HashSetHdrTest::Split_Lazy_PTB_cmpmix() + void HashSetHdrTest::Split_Lazy_DHP_cmpmix() { // traits-based version - typedef cc::SplitListSet< cds::gc::PTB, item, PTB_cmpmix_traits > set; + typedef cc::SplitListSet< cds::gc::DHP, item, DHP_cmpmix_traits > set; test_int< set >(); // option-based version - typedef cc::SplitListSet< cds::gc::PTB, item, + typedef cc::SplitListSet< cds::gc::DHP, item, cc::split_list::make_traits< cc::split_list::ordered_list ,cc::opt::hash< hash_int > @@ -122,6 +127,29 @@ namespace set { test_int< opt_set >(); } + void HashSetHdrTest::Split_Lazy_DHP_cmpmix_stat() + { + // traits-based version + typedef cc::SplitListSet< cds::gc::DHP, item, DHP_cmpmix_stat_traits > set; + test_int< set >(); + + // option-based version + typedef cc::SplitListSet< cds::gc::DHP, item, + cc::split_list::make_traits< + cc::split_list::ordered_list + ,cc::opt::hash< hash_int > + ,cc::opt::item_counter< simple_item_counter > + ,cc::split_list::ordered_list_traits< + cc::lazy_list::make_traits< + cc::opt::less< less > + ,cc::opt::compare< cmp > + >::type + > + ,cds::opt::stat< cc::split_list::stat<> > + >::type + > opt_set; + test_int< opt_set >(); + } } // namespace set diff --git a/tests/test-hdr/set/hdr_splitlist_set_lazy_hp.cpp b/tests/test-hdr/set/hdr_splitlist_set_lazy_hp.cpp index dfad981f..26b25a24 100644 --- a/tests/test-hdr/set/hdr_splitlist_set_lazy_hp.cpp +++ b/tests/test-hdr/set/hdr_splitlist_set_lazy_hp.cpp @@ -7,7 +7,7 @@ namespace set { namespace { - struct HP_cmp_traits: public cc::split_list::type_traits + struct HP_cmp_traits: public cc::split_list::traits { typedef cc::lazy_list_tag ordered_list; typedef HashSetHdrTest::hash_int hash; @@ -15,13 +15,13 @@ namespace set { typedef cc::opt::v::relaxed_ordering memory_model; enum { dynamic_bucket_table = false }; - struct ordered_list_traits: public cc::lazy_list::type_traits + struct ordered_list_traits: public cc::lazy_list::traits { typedef HashSetHdrTest::cmp compare; }; }; - struct HP_less_traits: public cc::split_list::type_traits + struct HP_less_traits: public cc::split_list::traits { typedef cc::lazy_list_tag ordered_list; typedef HashSetHdrTest::hash_int hash; @@ -29,24 +29,29 @@ namespace set { typedef cc::opt::v::sequential_consistent memory_model; enum { dynamic_bucket_table = false }; - struct ordered_list_traits: public cc::lazy_list::type_traits + struct ordered_list_traits: public cc::lazy_list::traits { typedef HashSetHdrTest::less less; }; }; - struct HP_cmpmix_traits: public cc::split_list::type_traits + struct HP_cmpmix_traits: public cc::split_list::traits { typedef cc::lazy_list_tag ordered_list; typedef HashSetHdrTest::hash_int hash; typedef HashSetHdrTest::simple_item_counter item_counter; - struct ordered_list_traits: public cc::lazy_list::type_traits + struct ordered_list_traits: public cc::lazy_list::traits { typedef HashSetHdrTest::cmp compare; typedef HashSetHdrTest::less less; }; }; + + struct HP_cmpmix_stat_traits : public HP_cmpmix_traits + { + typedef cc::split_list::stat<> stat; + }; } void HashSetHdrTest::Split_Lazy_HP_cmp() @@ -122,6 +127,29 @@ namespace set { test_int< opt_set >(); } + void HashSetHdrTest::Split_Lazy_HP_cmpmix_stat() + { + // traits-based version + typedef cc::SplitListSet< cds::gc::HP, item, HP_cmpmix_stat_traits > set; + test_int< set >(); + + // option-based version + typedef cc::SplitListSet< cds::gc::HP, item, + cc::split_list::make_traits< + cc::split_list::ordered_list + ,cc::opt::hash< hash_int > + ,cc::opt::item_counter< simple_item_counter > + ,cds::opt::stat< cc::split_list::stat<> > + ,cc::split_list::ordered_list_traits< + cc::lazy_list::make_traits< + cc::opt::less< less > + ,cc::opt::compare< cmp > + >::type + > + >::type + > opt_set; + test_int< opt_set >(); + } } // namespace set diff --git a/tests/test-hdr/set/hdr_splitlist_set_lazy_nogc.cpp b/tests/test-hdr/set/hdr_splitlist_set_lazy_nogc.cpp index ce9fa493..1c532fce 100644 --- a/tests/test-hdr/set/hdr_splitlist_set_lazy_nogc.cpp +++ b/tests/test-hdr/set/hdr_splitlist_set_lazy_nogc.cpp @@ -7,7 +7,7 @@ namespace set { namespace { - struct nogc_cmp_traits: public cc::split_list::type_traits + struct nogc_cmp_traits: public cc::split_list::traits { typedef cc::lazy_list_tag ordered_list; typedef HashSetHdrTest::hash_int hash; @@ -15,13 +15,13 @@ namespace set { typedef cc::opt::v::relaxed_ordering memory_model; enum { dynamic_bucket_table = false }; - struct ordered_list_traits: public cc::lazy_list::type_traits + struct ordered_list_traits: public cc::lazy_list::traits { typedef HashSetHdrTest::cmp compare; }; }; - struct nogc_less_traits: public cc::split_list::type_traits + struct nogc_less_traits: public cc::split_list::traits { typedef cc::lazy_list_tag ordered_list; typedef HashSetHdrTest::hash_int hash; @@ -29,24 +29,29 @@ namespace set { typedef cc::opt::v::sequential_consistent memory_model; enum { dynamic_bucket_table = false }; - struct ordered_list_traits: public cc::lazy_list::type_traits + struct ordered_list_traits: public cc::lazy_list::traits { typedef HashSetHdrTest::less less; }; }; - struct nogc_cmpmix_traits: public cc::split_list::type_traits + struct nogc_cmpmix_traits: public cc::split_list::traits { typedef cc::lazy_list_tag ordered_list; typedef HashSetHdrTest::hash_int hash; typedef HashSetHdrTest::simple_item_counter item_counter; - struct ordered_list_traits: public cc::lazy_list::type_traits + struct ordered_list_traits: public cc::lazy_list::traits { typedef HashSetHdrTest::cmp compare; typedef HashSetHdrTest::less less; }; }; + + struct nogc_cmpmix_stat_traits : public nogc_cmpmix_traits + { + typedef cc::split_list::stat<> stat; + }; } void HashSetHdrTest::Split_Lazy_nogc_cmp() @@ -122,6 +127,29 @@ namespace set { test_int_nogc< opt_set >(); } + void HashSetHdrTest::Split_Lazy_nogc_cmpmix_stat() + { + // traits-based version + typedef cc::SplitListSet< cds::gc::nogc, item, nogc_cmpmix_stat_traits > set; + test_int_nogc< set >(); + + // option-based version + typedef cc::SplitListSet< cds::gc::nogc, item, + cc::split_list::make_traits< + cc::split_list::ordered_list + ,cc::opt::hash< hash_int > + ,cds::opt::stat< cc::split_list::stat<>> + ,cc::opt::item_counter< simple_item_counter > + ,cc::split_list::ordered_list_traits< + cc::lazy_list::make_traits< + cc::opt::less< less > + ,cc::opt::compare< cmp > + >::type + > + >::type + > opt_set; + test_int_nogc< opt_set >(); + } } // namespace set diff --git a/tests/test-hdr/set/hdr_splitlist_set_nogc.cpp b/tests/test-hdr/set/hdr_splitlist_set_nogc.cpp index c03b4a30..37cafd9a 100644 --- a/tests/test-hdr/set/hdr_splitlist_set_nogc.cpp +++ b/tests/test-hdr/set/hdr_splitlist_set_nogc.cpp @@ -7,7 +7,7 @@ namespace set { namespace { - struct nogc_cmp_traits: public cc::split_list::type_traits + struct nogc_cmp_traits: public cc::split_list::traits { typedef cc::michael_list_tag ordered_list; typedef HashSetHdrTest::hash_int hash; @@ -15,13 +15,13 @@ namespace set { typedef cc::opt::v::relaxed_ordering memory_model; enum { dynamic_bucket_table = false }; - struct ordered_list_traits: public cc::michael_list::type_traits + struct ordered_list_traits: public cc::michael_list::traits { typedef HashSetHdrTest::cmp compare; }; }; - struct nogc_less_traits: public cc::split_list::type_traits + struct nogc_less_traits: public cc::split_list::traits { typedef cc::michael_list_tag ordered_list; typedef HashSetHdrTest::hash_int hash; @@ -29,24 +29,29 @@ namespace set { typedef cc::opt::v::sequential_consistent memory_model; enum { dynamic_bucket_table = false }; - struct ordered_list_traits: public cc::michael_list::type_traits + struct ordered_list_traits: public cc::michael_list::traits { typedef HashSetHdrTest::less less; }; }; - struct nogc_cmpmix_traits: public cc::split_list::type_traits + struct nogc_cmpmix_traits: public cc::split_list::traits { typedef cc::michael_list_tag ordered_list; typedef HashSetHdrTest::hash_int hash; typedef HashSetHdrTest::simple_item_counter item_counter; - struct ordered_list_traits: public cc::michael_list::type_traits + struct ordered_list_traits: public cc::michael_list::traits { typedef HashSetHdrTest::cmp compare; typedef HashSetHdrTest::less less; }; }; + + struct nogc_cmpmix_stat_traits : public nogc_cmpmix_traits + { + typedef cc::split_list::stat<> stat; + }; } void HashSetHdrTest::Split_nogc_cmp() @@ -122,6 +127,29 @@ namespace set { test_int_nogc< opt_set >(); } + void HashSetHdrTest::Split_nogc_cmpmix_stat() + { + // traits-based version + typedef cc::SplitListSet< cds::gc::nogc, item, nogc_cmpmix_stat_traits > set; + test_int_nogc< set >(); + + // option-based version + typedef cc::SplitListSet< cds::gc::nogc, item, + cc::split_list::make_traits< + cc::split_list::ordered_list + ,cc::opt::hash< hash_int > + ,cc::opt::item_counter< simple_item_counter > + ,cc::opt::stat< cc::split_list::stat<>> + ,cc::split_list::ordered_list_traits< + cc::michael_list::make_traits< + cc::opt::less< less > + ,cc::opt::compare< cmp > + >::type + > + >::type + > opt_set; + test_int_nogc< opt_set >(); + } } // namespace set