Extending intrusive MichaelSet<HP> to IterableList
authorkhizmax <libcds.dev@gmail.com>
Wed, 27 Jul 2016 20:49:50 +0000 (23:49 +0300)
committerkhizmax <libcds.dev@gmail.com>
Wed, 27 Jul 2016 20:49:50 +0000 (23:49 +0300)
25 files changed:
cds/intrusive/details/iterable_list_base.h
cds/intrusive/details/lazy_list_base.h
cds/intrusive/details/michael_list_base.h
cds/intrusive/details/michael_set_base.h
cds/intrusive/impl/iterable_list.h
cds/intrusive/impl/lazy_list.h
cds/intrusive/impl/michael_list.h
cds/intrusive/lazy_list_nogc.h
cds/intrusive/lazy_list_rcu.h
cds/intrusive/michael_list_nogc.h
cds/intrusive/michael_list_rcu.h
cds/intrusive/michael_set.h
cds/intrusive/michael_set_nogc.h
cds/intrusive/michael_set_rcu.h
projects/Win/vc14/gtest-intrusive-set.vcxproj
test/unit/intrusive-set/intrusive_michael_iterable_dhp.cpp
test/unit/intrusive-set/intrusive_michael_iterable_hp.cpp
test/unit/intrusive-set/intrusive_michael_lazy_dhp.cpp
test/unit/intrusive-set/intrusive_michael_lazy_hp.cpp
test/unit/intrusive-set/intrusive_michael_lazy_nogc.cpp
test/unit/intrusive-set/intrusive_michael_michael_dhp.cpp
test/unit/intrusive-set/intrusive_michael_michael_hp.cpp
test/unit/intrusive-set/intrusive_michael_michael_nogc.cpp
test/unit/intrusive-set/test_intrusive_michael_lazy_rcu.h
test/unit/intrusive-set/test_intrusive_michael_michael_rcu.h

index 824d239..3ddaa07 100644 (file)
@@ -237,6 +237,33 @@ namespace cds { namespace intrusive {
 #   endif
         };
 
+
+        //@cond
+        template <typename Stat>
+        struct select_stat_wrapper
+        {
+            typedef Stat stat;
+            typedef iterable_list::wrapped_stat<Stat> wrapped_stat;
+            enum {
+                empty = false
+            };
+        };
+
+        template <>
+        struct select_stat_wrapper< empty_stat >
+        {
+            typedef empty_stat stat;
+            typedef empty_stat wrapped_stat;
+            enum {
+                empty = true
+            };
+        };
+
+        template <typename Stat>
+        struct select_stat_wrapper< iterable_list::wrapped_stat<Stat>>: public select_stat_wrapper<Stat>
+        {};
+        //@endcond
+
     } // namespace iterable_list
 
     //@cond
index e170bf6..441a106 100644 (file)
@@ -419,6 +419,32 @@ namespace cds { namespace intrusive {
 #   endif
         };
 
+        //@cond
+        template <typename Stat>
+        struct select_stat_wrapper
+        {
+            typedef Stat stat;
+            typedef lazy_list::wrapped_stat<Stat> wrapped_stat;
+            enum {
+                empty = false
+            };
+        };
+
+        template <>
+        struct select_stat_wrapper< empty_stat >
+        {
+            typedef empty_stat stat;
+            typedef empty_stat wrapped_stat;
+            enum {
+                empty = true
+            };
+        };
+
+        template <typename Stat>
+        struct select_stat_wrapper< lazy_list::wrapped_stat<Stat>>: public select_stat_wrapper< Stat >
+        {};
+        //@endcond
+
     } // namespace lazy_list
 
     //@cond
index 6b68442..a51275a 100644 (file)
@@ -381,6 +381,34 @@ namespace cds { namespace intrusive {
 #   endif
         };
 
+
+        //@cond
+        template <typename Stat>
+        struct select_stat_wrapper
+        {
+            typedef Stat stat;
+            typedef michael_list::wrapped_stat<Stat> wrapped_stat;
+            enum {
+                empty = false
+            };
+        };
+
+        template <>
+        struct select_stat_wrapper< empty_stat >
+        {
+            typedef empty_stat stat;
+            typedef empty_stat wrapped_stat;
+            enum {
+                empty = true
+            };
+        };
+
+        template <typename Stat>
+        struct select_stat_wrapper< michael_list::wrapped_stat<Stat>>: public select_stat_wrapper< Stat >
+        {};
+
+        //@endcond
+
     } // namespace michael_list
 
     //@cond
index 64c08d2..bc8490e 100644 (file)
@@ -120,7 +120,8 @@ namespace cds { namespace intrusive {
             template <typename OrderedList, bool IsConst>
             class iterator
             {
-                friend class iterator < OrderedList, !IsConst >;
+                friend class iterator< OrderedList, !IsConst >;
+
             protected:
                 typedef OrderedList bucket_type;
                 typedef typename list_iterator_selector< bucket_type, IsConst>::bucket_ptr bucket_ptr;
index 21f3d5f..723b6b2 100644 (file)
@@ -153,6 +153,10 @@ namespace cds { namespace intrusive {
                 , typename cds::opt::make_options< traits, Options...>::type
             > type;
         };
+
+        // Stat selector
+        template <typename Stat>
+        using select_stat_wrapper = iterable_list::select_stat_wrapper< Stat >;
         //@endcond
 
     protected:
index abe6ef4..dc0b54f 100644 (file)
@@ -222,6 +222,10 @@ namespace cds { namespace intrusive {
                 , typename cds::opt::make_options< traits, Options...>::type
             > type;
         };
+
+        // Stat selector
+        template <typename Stat>
+        using select_stat_wrapper = lazy_list::select_stat_wrapper< Stat >;
         //@endcond
 
     protected:
index 97bf868..8e58bf4 100644 (file)
@@ -224,6 +224,10 @@ namespace cds { namespace intrusive {
                 , typename cds::opt::make_options< traits, Options...>::type
             >   type;
         };
+
+        // Stat selector
+        template <typename Stat>
+        using select_stat_wrapper = michael_list::select_stat_wrapper< Stat >;
         //@endcond
 
     protected:
index 17a7deb..4018362 100644 (file)
@@ -135,6 +135,10 @@ namespace cds { namespace intrusive {
                 , typename cds::opt::make_options< traits, Options...>::type
             >   type;
         };
+
+        // Stat selector
+        template <typename Stat>
+        using select_stat_wrapper = lazy_list::select_stat_wrapper< Stat >;
         //@endcond
 
     protected:
index d5bec4b..935c294 100644 (file)
@@ -154,6 +154,10 @@ namespace cds { namespace intrusive {
                 , typename cds::opt::make_options< traits, Options...>::type
             >   type;
         };
+
+        // Stat selector
+        template <typename Stat>
+        using select_stat_wrapper = lazy_list::select_stat_wrapper< Stat >;
         //@endcond
 
     protected:
index e7378a7..2fa260c 100644 (file)
@@ -112,6 +112,10 @@ namespace cds { namespace intrusive {
                 , typename cds::opt::make_options< traits, Options...>::type
             >   type;
         };
+
+        // Stat selector
+        template <typename Stat>
+        using select_stat_wrapper = michael_list::select_stat_wrapper< Stat >;
         //@endcond
 
     protected:
index 5267426..230b22c 100644 (file)
@@ -138,6 +138,10 @@ namespace cds { namespace intrusive {
                 , typename cds::opt::make_options< traits, Options...>::type
             >   type;
         };
+
+        // Stat selector
+        template <typename Stat>
+        using select_stat_wrapper = michael_list::select_stat_wrapper< Stat >;
         //@endcond
 
     protected:
index 327f09a..b264bb1 100644 (file)
@@ -32,7 +32,6 @@
 #define CDSLIB_INTRUSIVE_MICHAEL_SET_H
 
 #include <cds/intrusive/details/michael_set_base.h>
-#include <cds/details/allocator.h>
 #include <cds/intrusive/details/iterable_list_base.h>
 
 namespace cds { namespace intrusive {
@@ -51,7 +50,7 @@ namespace cds { namespace intrusive {
 
         Template parameters are:
         - \p GC - Garbage collector used. Note the \p GC must be the same as the GC used for \p OrderedList
-        - \p OrderedList - ordered list implementation used as bucket for hash set, for example, \p MichaelList, \p LazyList.
+        - \p OrderedList - ordered list implementation used as bucket for hash set, for example, \p MichaelList, \p LazyList, \p IterableList.
             The intrusive ordered list implementation specifies the type \p T stored in the hash-set, the reclamation
             schema \p GC used by hash-set, the comparison functor for the type \p T and other features specific for
             the ordered list.
@@ -72,7 +71,7 @@ namespace cds { namespace intrusive {
         \code
         // Our node type
         struct Foo {
-            std::string     key_; // key field
+            std::string key_; // key field
             // ... other fields
         };
 
@@ -249,50 +248,46 @@ namespace cds { namespace intrusive {
     public:
         typedef GC           gc;            ///< Garbage collector
         typedef OrderedList  ordered_list;  ///< type of ordered list used as a bucket implementation
-        typedef ordered_list bucket_type;   ///< bucket type
-        typedef Traits       traits;       ///< Set traits
+        typedef Traits       traits;        ///< Set traits
 
-        typedef typename ordered_list::value_type       value_type      ;   ///< type of value to be stored in the set
-        typedef typename ordered_list::key_comparator   key_comparator  ;   ///< key comparing functor
-        typedef typename ordered_list::disposer         disposer        ;   ///< Node disposer functor
+        typedef typename ordered_list::value_type       value_type      ; ///< type of value to be stored in the set
+        typedef typename ordered_list::key_comparator   key_comparator  ; ///< key comparing functor
+        typedef typename ordered_list::disposer         disposer        ; ///< Node disposer functor
+        typedef typename ordered_list::stat             stat            ; ///< Internal statistics
 
         /// Hash functor for \p value_type and all its derivatives that you use
         typedef typename cds::opt::v::hash_selector< typename traits::hash >::type hash;
         typedef typename traits::item_counter item_counter;   ///< Item counter type
+        typedef typename traits::allocator    allocator;      ///< Bucket table allocator
 
         typedef typename ordered_list::guarded_ptr guarded_ptr; ///< Guarded pointer
 
-        /// Bucket table allocator
-        typedef cds::details::Allocator< bucket_type, typename traits::allocator > bucket_table_allocator;
-
         /// Count of hazard pointer required for the algorithm
         static CDS_CONSTEXPR const size_t c_nHazardPtrCount = ordered_list::c_nHazardPtrCount;
 
-    protected:
-        item_counter    m_ItemCounter;   ///< Item counter
-        hash            m_HashFunctor;   ///< Hash functor
-        bucket_type *   m_Buckets;      ///< bucket table
+        // GC and OrderedList::gc must be the same
+        static_assert(std::is_same<gc, typename ordered_list::gc>::value, "GC and OrderedList::gc must be the same");
 
-    private:
-        //@cond
-        const size_t    m_nHashBitmask;
-        //@endcond
+        // atomicity::empty_item_counter is not allowed as a item counter
+        static_assert(!std::is_same<item_counter, atomicity::empty_item_counter>::value,
+            "cds::atomicity::empty_item_counter is not allowed as a item counter");
 
     protected:
         //@cond
-        /// Calculates hash value of \p key
-        template <typename Q>
-        size_t hash_value( const Q& key ) const
-        {
-            return m_HashFunctor( key ) & m_nHashBitmask;
-        }
+        typedef typename ordered_list::template select_stat_wrapper< typename ordered_list::stat > bucket_stat;
 
-        /// Returns the bucket (ordered list) for \p key
-        template <typename Q>
-        bucket_type&    bucket( const Q& key )
-        {
-            return m_Buckets[ hash_value( key ) ];
-        }
+        typedef typename ordered_list::template rebind_traits<
+            cds::opt::item_counter< cds::atomicity::empty_item_counter >
+            , cds::opt::stat< typename bucket_stat::wrapped_stat >
+        >::type internal_bucket_type;
+
+        typedef typename allocator::template rebind< internal_bucket_type >::other bucket_table_allocator;
+
+        hash                        m_HashFunctor;   ///< Hash functor
+        size_t const                m_nHashBitmask;
+        internal_bucket_type*       m_Buckets;       ///< bucket table
+        item_counter                m_ItemCounter;   ///< Item counter
+        typename bucket_stat::stat  m_Stat;          ///< Internal statistics
         //@endcond
 
     public:
@@ -314,13 +309,13 @@ namespace cds { namespace intrusive {
             - for \p IterableList: iterator is thread-safe. You may use it freely in concurrent environment.
               
         */
-        typedef michael_set::details::iterator< bucket_type, false > iterator;
+        typedef michael_set::details::iterator< internal_bucket_type, false > iterator;
 
         /// Const forward iterator
         /**
             For iterator's features and requirements see \ref iterator
         */
-        typedef michael_set::details::iterator< bucket_type, true > const_iterator;
+        typedef michael_set::details::iterator< internal_bucket_type, true > const_iterator;
 
         /// Returns a forward iterator addressing the first element in a set
         /**
@@ -339,7 +334,7 @@ namespace cds { namespace intrusive {
         */
         iterator end()
         {
-            return iterator( m_Buckets[bucket_count() - 1].end(), bucket_end() + 1, bucket_end() );
+            return iterator( bucket_end()[-1].end(), bucket_end() - 1, bucket_end() );
         }
 
         /// Returns a forward const iterator addressing the first element in a set
@@ -367,28 +362,6 @@ namespace cds { namespace intrusive {
         }
     //@}
 
-    private:
-        //@cond
-        bucket_type * bucket_begin() const
-        {
-            return m_Buckets;
-        }
-
-        bucket_type * bucket_end() const
-        {
-            return m_Buckets + bucket_count();
-        }
-
-        const_iterator get_const_begin() const
-        {
-            return const_iterator( m_Buckets[0].cbegin(), bucket_begin(), bucket_end() );
-        }
-        const_iterator get_const_end() const
-        {
-            return const_iterator( m_Buckets[bucket_count() - 1].cend(), bucket_end() - 1, bucket_end() );
-        }
-        //@endcond
-
     public:
         /// Initializes hash set
         /** @anchor cds_intrusive_MichaelHashSet_hp_ctor
@@ -402,22 +375,20 @@ namespace cds { namespace intrusive {
             size_t nMaxItemCount,   ///< estimation of max item count in the hash set
             size_t nLoadFactor      ///< load factor: estimation of max number of items in the bucket. Small integer up to 10.
         ) : m_nHashBitmask( michael_set::details::init_hash_bitmask( nMaxItemCount, nLoadFactor ))
+          , m_Buckets( bucket_table_allocator().allocate( bucket_count()))
         {
-            // GC and OrderedList::gc must be the same
-            static_assert( std::is_same<gc, typename bucket_type::gc>::value, "GC and OrderedList::gc must be the same");
-
-            // atomicity::empty_item_counter is not allowed as a item counter
-            static_assert( !std::is_same<item_counter, atomicity::empty_item_counter>::value,
-                           "cds::atomicity::empty_item_counter is not allowed as a item counter");
-
-            m_Buckets = bucket_table_allocator().NewArray( bucket_count() );
+            for ( auto it = m_Buckets, itEnd = m_Buckets + bucket_count(); it != itEnd; ++it )
+                construct_bucket<bucket_stat>( it );
         }
 
         /// Clears hash set object and destroys it
         ~MichaelHashSet()
         {
             clear();
-            bucket_table_allocator().Delete( m_Buckets, bucket_count() );
+
+            for ( auto it = m_Buckets, itEnd = m_Buckets + bucket_count(); it != itEnd; ++it )
+                it->~internal_bucket_type();
+            bucket_table_allocator().deallocate( m_Buckets, bucket_count() );
         }
 
         /// Inserts new node
@@ -750,8 +721,8 @@ namespace cds { namespace intrusive {
 #endif
         find( Q& key )
         {
-            bucket_type& b = bucket( key );
-            typename ordered_list::iterator it = b.find( key );
+            internal_bucket_type& b = bucket( key );
+            typename internal_bucket_type::iterator it = b.find( key );
             if ( it == b.end() )
                 return end();
             return iterator( it, &b, bucket_end());
@@ -761,8 +732,8 @@ namespace cds { namespace intrusive {
         typename std::enable_if< std::is_same<Q, Q>::value && is_iterable_list< ordered_list >::value, iterator >::type
         find( Q const& key )
         {
-            bucket_type& b = bucket( key );
-            typename ordered_list::iterator it = b.find( key );
+            internal_bucket_type& b = bucket( key );
+            typename internal_bucket_type::iterator it = b.find( key );
             if ( it == b.end() )
                 return end();
             return iterator( it, &b, bucket_end() );
@@ -808,8 +779,8 @@ namespace cds { namespace intrusive {
 #endif
         find_with( Q& key, Less pred )
         {
-            bucket_type& b = bucket( key );
-            typename ordered_list::iterator it = b.find_with( key, pred );
+            internal_bucket_type& b = bucket( key );
+            typename internal_bucket_type::iterator it = b.find_with( key, pred );
             if ( it == b.end() )
                 return end();
             return iterator( it, &b, bucket_end() );
@@ -819,8 +790,8 @@ namespace cds { namespace intrusive {
         typename std::enable_if< std::is_same<Q, Q>::value && is_iterable_list< ordered_list >::value, iterator >::type
         find_with( Q const& key, Less pred )
         {
-            bucket_type& b = bucket( key );
-            typename ordered_list::iterator it = b.find_with( key, pred );
+            internal_bucket_type& b = bucket( key );
+            typename internal_bucket_type::iterator it = b.find_with( key, pred );
             if ( it == b.end() )
                 return end();
             return iterator( it, &b, bucket_end() );
@@ -934,6 +905,12 @@ namespace cds { namespace intrusive {
             return m_ItemCounter;
         }
 
+        /// Returns const reference to internal statistics
+        stat const& statistics() const
+        {
+            return m_Stat;
+        }
+
         /// Returns the size of hash table
         /**
             Since \p %MichaelHashSet cannot dynamically extend the hash table size,
@@ -944,6 +921,54 @@ namespace cds { namespace intrusive {
         {
             return m_nHashBitmask + 1;
         }
+
+    private:
+        //@cond
+        internal_bucket_type * bucket_begin() const
+        {
+            return m_Buckets;
+        }
+
+        internal_bucket_type * bucket_end() const
+        {
+            return m_Buckets + bucket_count();
+        }
+
+        const_iterator get_const_begin() const
+        {
+            return const_iterator( m_Buckets[0].cbegin(), bucket_begin(), bucket_end() );
+        }
+        const_iterator get_const_end() const
+        {
+            return const_iterator( bucket_end()[-1].cend(), bucket_end() - 1, bucket_end() );
+        }
+
+        template <typename Stat>
+        typename std::enable_if< Stat::empty >::type construct_bucket( internal_bucket_type * bucket )
+        {
+            new (bucket) internal_bucket_type;
+        }
+
+        template <typename Stat>
+        typename std::enable_if< !Stat::empty >::type construct_bucket( internal_bucket_type * bucket )
+        {
+            new (bucket) internal_bucket_type( m_Stat );
+        }
+
+        /// Calculates hash value of \p key
+        template <typename Q>
+        size_t hash_value( const Q& key ) const
+        {
+            return m_HashFunctor( key ) & m_nHashBitmask;
+        }
+
+        /// Returns the bucket (ordered list) for \p key
+        template <typename Q>
+        internal_bucket_type& bucket( const Q& key )
+        {
+            return m_Buckets[hash_value( key )];
+        }
+        //@endcond
     };
 
 }}  // namespace cds::intrusive
index 8899845..51ea022 100644 (file)
@@ -25,7 +25,7 @@
     SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
     CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
     OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.     
+    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
 #ifndef CDSLIB_INTRUSIVE_MICHAEL_SET_NOGC_H
@@ -33,7 +33,6 @@
 
 #include <cds/intrusive/details/michael_set_base.h>
 #include <cds/gc/nogc.h>
-#include <cds/details/allocator.h>
 
 namespace cds { namespace intrusive {
 
@@ -59,29 +58,43 @@ namespace cds { namespace intrusive {
     class MichaelHashSet< cds::gc::nogc, OrderedList, Traits >
     {
     public:
-        typedef cds::gc::nogc gc;        ///< Garbage collector
-        typedef OrderedList bucket_type; ///< Type of ordered list to be used as buckets
-        typedef Traits      traits;     ///< Set traits
+        typedef cds::gc::nogc gc;           ///< Garbage collector
+        typedef OrderedList   ordered_list; ///< type of ordered list used as a bucket implementation
+        typedef Traits        traits;       ///< Set traits
 
-        typedef typename bucket_type::value_type     value_type;     ///< type of value to be stored in the set
-        typedef typename bucket_type::key_comparator key_comparator; ///< key comparing functor
-        typedef typename bucket_type::disposer       disposer;       ///< Node disposer functor
+        typedef typename ordered_list::value_type     value_type;     ///< type of value to be stored in the set
+        typedef typename ordered_list::key_comparator key_comparator; ///< key comparing functor
+        typedef typename ordered_list::disposer       disposer;       ///< Node disposer functor
+        typedef typename ordered_list::stat           stat;           ///< Internal statistics
 
         /// Hash functor for \p value_type and all its derivatives that you use
         typedef typename cds::opt::v::hash_selector< typename traits::hash >::type hash;
         typedef typename traits::item_counter item_counter; ///< Item counter type
+        typedef typename traits::allocator    allocator;    ///< Bucket table allocator
 
-        /// Bucket table allocator
-        typedef cds::details::Allocator< bucket_type, typename traits::allocator > bucket_table_allocator;
+        // GC and OrderedList::gc must be the same
+        static_assert(std::is_same<gc, typename ordered_list::gc>::value, "GC and OrderedList::gc must be the same");
 
-    protected:
-        item_counter    m_ItemCounter; ///< Item counter
-        hash            m_HashFunctor; ///< Hash functor
-        bucket_type *   m_Buckets;     ///< bucket table
+        // atomicity::empty_item_counter is not allowed as a item counter
+        static_assert(!std::is_same<item_counter, atomicity::empty_item_counter>::value,
+            "atomicity::empty_item_counter is not allowed as a item counter");
 
-    private:
+    protected:
         //@cond
-        const size_t    m_nHashBitmask;
+        typedef typename ordered_list::template select_stat_wrapper< typename ordered_list::stat > bucket_stat;
+
+        typedef typename ordered_list::template rebind_traits<
+            cds::opt::item_counter< cds::atomicity::empty_item_counter >
+            , cds::opt::stat< typename bucket_stat::wrapped_stat >
+        >::type internal_bucket_type;
+
+        typedef typename allocator::template rebind< internal_bucket_type >::other bucket_table_allocator;
+
+        hash                        m_HashFunctor; ///< Hash functor
+        const size_t                m_nHashBitmask;
+        internal_bucket_type *      m_Buckets;     ///< bucket table
+        item_counter                m_ItemCounter; ///< Item counter
+        typename bucket_stat::stat  m_Stat;        ///< Internal statistics
         //@endcond
 
     protected:
@@ -95,7 +108,7 @@ namespace cds { namespace intrusive {
 
         /// Returns the bucket (ordered list) for \p key
         template <typename Q>
-        bucket_type&    bucket( Q const & key )
+        internal_bucket_type&    bucket( Q const & key )
         {
             return m_Buckets[ hash_value( key ) ];
         }
@@ -138,13 +151,13 @@ namespace cds { namespace intrusive {
             };
             \endcode
         */
-        typedef michael_set::details::iterator< bucket_type, false >    iterator;
+        typedef michael_set::details::iterator< internal_bucket_type, false >    iterator;
 
         /// Const forward iterator
         /**
             For iterator's features and requirements see \ref iterator
         */
-        typedef michael_set::details::iterator< bucket_type, true >     const_iterator;
+        typedef michael_set::details::iterator< internal_bucket_type, true >     const_iterator;
 
         /// Returns a forward iterator addressing the first element in a set
         /**
@@ -202,22 +215,20 @@ namespace cds { namespace intrusive {
             size_t nMaxItemCount,   ///< estimation of max item count in the hash set
             size_t nLoadFactor      ///< load factor: estimation of max number of items in the bucket
         ) : m_nHashBitmask( michael_set::details::init_hash_bitmask( nMaxItemCount, nLoadFactor ))
+          , m_Buckets( bucket_table_allocator().allocate( bucket_count() ) )
         {
-            // GC and OrderedList::gc must be the same
-            static_assert( std::is_same<gc, typename bucket_type::gc>::value, "GC and OrderedList::gc must be the same");
-
-            // atomicity::empty_item_counter is not allowed as a item counter
-            static_assert( !std::is_same<item_counter, atomicity::empty_item_counter>::value,
-                           "atomicity::empty_item_counter is not allowed as a item counter");
-
-            m_Buckets = bucket_table_allocator().NewArray( bucket_count() );
+            for ( auto it = m_Buckets, itEnd = m_Buckets + bucket_count(); it != itEnd; ++it )
+                construct_bucket<bucket_stat>( it );
         }
 
         /// Clears hash set object and destroys it
         ~MichaelHashSet()
         {
             clear();
-            bucket_table_allocator().Delete( m_Buckets, bucket_count() );
+
+            for ( auto it = m_Buckets, itEnd = m_Buckets + bucket_count(); it != itEnd; ++it )
+                it->~internal_bucket_type();
+            bucket_table_allocator().deallocate( m_Buckets, bucket_count() );
         }
 
         /// Inserts new node
@@ -425,6 +436,26 @@ namespace cds { namespace intrusive {
             return m_nHashBitmask + 1;
         }
 
+        /// Returns const reference to internal statistics
+        stat const& statistics() const
+        {
+            return m_Stat;
+        }
+
+    private:
+        //@cond
+        template <typename Stat>
+        typename std::enable_if< Stat::empty >::type construct_bucket( internal_bucket_type * bucket )
+        {
+            new (bucket) internal_bucket_type;
+        }
+
+        template <typename Stat>
+        typename std::enable_if< !Stat::empty >::type construct_bucket( internal_bucket_type * bucket )
+        {
+            new (bucket) internal_bucket_type( m_Stat );
+        }
+        //@endcond
     };
 
 }} // namespace cds::intrusive
index 2a5df07..75e0921 100644 (file)
     SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
     CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
     OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.     
+    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
 #ifndef CDSLIB_INTRUSIVE_MICHAEL_SET_RCU_H
 #define CDSLIB_INTRUSIVE_MICHAEL_SET_RCU_H
 
 #include <cds/intrusive/details/michael_set_base.h>
-#include <cds/details/allocator.h>
 
 namespace cds { namespace intrusive {
 
@@ -102,57 +101,54 @@ namespace cds { namespace intrusive {
     class MichaelHashSet< cds::urcu::gc< RCU >, OrderedList, Traits >
     {
     public:
-        typedef cds::urcu::gc< RCU > gc;   ///< RCU schema
-        typedef OrderedList bucket_type;   ///< type of ordered list used as a bucket implementation
-        typedef Traits traits;             ///< Set traits
+        typedef cds::urcu::gc< RCU > gc;            ///< RCU schema
+        typedef OrderedList          ordered_list;  ///< type of ordered list used as a bucket implementation
+        typedef Traits               traits;        ///< Set traits
 
-        typedef typename bucket_type::value_type        value_type      ;   ///< type of value stored in the list
-        typedef typename bucket_type::key_comparator    key_comparator  ;   ///< key comparing functor
-        typedef typename bucket_type::disposer          disposer        ;   ///< Node disposer functor
+        typedef typename ordered_list::value_type     value_type;       ///< type of value stored in the list
+        typedef typename ordered_list::key_comparator key_comparator;   ///< key comparing functor
+        typedef typename ordered_list::disposer       disposer;         ///< Node disposer functor
+        typedef typename ordered_list::stat           stat;             ///< Internal statistics
 
         /// Hash functor for \ref value_type and all its derivatives that you use
         typedef typename cds::opt::v::hash_selector< typename traits::hash >::type hash;
         typedef typename traits::item_counter item_counter;   ///< Item counter type
+        typedef typename traits::allocator    allocator;      ///< Bucket table allocator
 
-        /// Bucket table allocator
-        typedef cds::details::Allocator< bucket_type, typename traits::allocator >  bucket_table_allocator;
-
-        typedef typename bucket_type::rcu_lock    rcu_lock;   ///< RCU scoped lock
-        typedef typename bucket_type::exempt_ptr  exempt_ptr; ///< pointer to extracted node
-        typedef typename bucket_type::raw_ptr     raw_ptr;    ///< Return type of \p get() member function and its derivatives
+        typedef typename ordered_list::rcu_lock    rcu_lock;   ///< RCU scoped lock
         /// Group of \p extract_xxx functions require external locking if underlying ordered list requires that
-        static CDS_CONSTEXPR const bool c_bExtractLockExternal = bucket_type::c_bExtractLockExternal;
+        static CDS_CONSTEXPR const bool c_bExtractLockExternal = ordered_list::c_bExtractLockExternal;
 
-    protected:
-        item_counter    m_ItemCounter;   ///< Item counter
-        hash            m_HashFunctor;   ///< Hash functor
-        bucket_type *   m_Buckets;       ///< bucket table
+        // GC and OrderedList::gc must be the same
+        static_assert(std::is_same<gc, typename ordered_list::gc>::value, "GC and OrderedList::gc must be the same");
 
-    private:
-        //@cond
-        const size_t m_nHashBitmask;
-        //@endcond
+        // atomicity::empty_item_counter is not allowed as a item counter
+        static_assert(!std::is_same<item_counter, atomicity::empty_item_counter>::value,
+            "atomicity::empty_item_counter is not allowed as a item counter");
 
     protected:
         //@cond
-        /// Calculates hash value of \p key
-        template <typename Q>
-        size_t hash_value( Q const& key ) const
-        {
-            return m_HashFunctor( key ) & m_nHashBitmask;
-        }
+        typedef typename ordered_list::template select_stat_wrapper< typename ordered_list::stat > bucket_stat;
 
-        /// Returns the bucket (ordered list) for \p key
-        template <typename Q>
-        bucket_type& bucket( Q const& key )
-        {
-            return m_Buckets[ hash_value( key ) ];
-        }
-        template <typename Q>
-        bucket_type const& bucket( Q const& key ) const
-        {
-            return m_Buckets[ hash_value( key ) ];
-        }
+        typedef typename ordered_list::template rebind_traits<
+            cds::opt::item_counter< cds::atomicity::empty_item_counter >
+            , cds::opt::stat< typename bucket_stat::wrapped_stat >
+        >::type internal_bucket_type;
+
+        typedef typename allocator::template rebind< internal_bucket_type >::other bucket_table_allocator;
+        //@endcond
+
+    public:
+        typedef typename internal_bucket_type::exempt_ptr  exempt_ptr; ///< pointer to extracted node
+        typedef typename internal_bucket_type::raw_ptr     raw_ptr;    ///< Return type of \p get() member function and its derivatives
+
+    private:
+        //@cond
+        hash                        m_HashFunctor;   ///< Hash functor
+        size_t const                m_nHashBitmask;
+        internal_bucket_type*       m_Buckets;       ///< bucket table
+        item_counter                m_ItemCounter;   ///< Item counter
+        typename bucket_stat::stat  m_Stat;          ///< Internal statistics
         //@endcond
 
     public:
@@ -195,13 +191,13 @@ namespace cds { namespace intrusive {
             };
             \endcode
         */
-        typedef michael_set::details::iterator< bucket_type, false >    iterator;
+        typedef michael_set::details::iterator< internal_bucket_type, false >    iterator;
 
         /// Const forward iterator
         /**
             For iterator's features and requirements see \ref iterator
         */
-        typedef michael_set::details::iterator< bucket_type, true >     const_iterator;
+        typedef michael_set::details::iterator< internal_bucket_type, true >     const_iterator;
 
         /// Returns a forward iterator addressing the first element in a set
         /**
@@ -261,22 +257,20 @@ namespace cds { namespace intrusive {
             size_t nMaxItemCount,   ///< estimation of max item count in the hash set
             size_t nLoadFactor      ///< load factor: average size of the bucket
         ) : m_nHashBitmask( michael_set::details::init_hash_bitmask( nMaxItemCount, nLoadFactor ))
+          , m_Buckets( bucket_table_allocator().allocate( bucket_count() ) )
         {
-            // GC and OrderedList::gc must be the same
-            static_assert( std::is_same<gc, typename bucket_type::gc>::value, "GC and OrderedList::gc must be the same");
-
-            // atomicity::empty_item_counter is not allowed as a item counter
-            static_assert( !std::is_same<item_counter, atomicity::empty_item_counter>::value,
-                "atomicity::empty_item_counter is not allowed as a item counter");
-
-            m_Buckets = bucket_table_allocator().NewArray( bucket_count() );
+            for ( auto it = m_Buckets, itEnd = m_Buckets + bucket_count(); it != itEnd; ++it )
+                construct_bucket<bucket_stat>( it );
         }
 
         /// Clear hash set and destroy it
         ~MichaelHashSet()
         {
             clear();
-            bucket_table_allocator().Delete( m_Buckets, bucket_count() );
+
+            for ( auto it = m_Buckets, itEnd = m_Buckets + bucket_count(); it != itEnd; ++it )
+                it->~internal_bucket_type();
+            bucket_table_allocator().deallocate( m_Buckets, bucket_count() );
         }
 
         /// Inserts new node
@@ -470,7 +464,7 @@ namespace cds { namespace intrusive {
             unlinks it from the set, and returns \ref cds::urcu::exempt_ptr "exempt_ptr" pointer to the item found.
             If the item with the key equal to \p key is not found the function returns an empty \p exempt_ptr.
 
-            Depends on \p bucket_type you should or should not lock RCU before calling of this function:
+            Depends on \p ordered_list you should or should not lock RCU before calling of this function:
             - for the set based on \ref cds_intrusive_MichaelList_rcu "MichaelList" RCU should not be locked
             - for the set based on \ref cds_intrusive_LazyList_rcu "LazyList" RCU should be locked
 
@@ -633,7 +627,7 @@ namespace cds { namespace intrusive {
         /** \anchor cds_intrusive_MichaelHashSet_rcu_get
             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 type of returned value depends on underlying \p bucket_type.
+            Note the type of returned value depends on underlying \p ordered_list.
             For details, see documentation of ordered list you use.
 
             Note the compare functor should accept a parameter of type \p Q that can be not the same as \p value_type.
@@ -726,9 +720,47 @@ namespace cds { namespace intrusive {
             return m_nHashBitmask + 1;
         }
 
+        /// Returns const reference to internal statistics
+        stat const& statistics() const
+        {
+            return m_Stat;
+        }
+
+    private:
+        //@cond
+        template <typename Stat>
+        typename std::enable_if< Stat::empty >::type construct_bucket( internal_bucket_type * bucket )
+        {
+            new (bucket) internal_bucket_type;
+        }
+
+        template <typename Stat>
+        typename std::enable_if< !Stat::empty >::type construct_bucket( internal_bucket_type * bucket )
+        {
+            new (bucket) internal_bucket_type( m_Stat );
+        }
+
+        /// Calculates hash value of \p key
+        template <typename Q>
+        size_t hash_value( Q const& key ) const
+        {
+            return m_HashFunctor( key ) & m_nHashBitmask;
+        }
+
+        /// Returns the bucket (ordered list) for \p key
+        template <typename Q>
+        internal_bucket_type& bucket( Q const& key )
+        {
+            return m_Buckets[hash_value( key )];
+        }
+        template <typename Q>
+        internal_bucket_type const& bucket( Q const& key ) const
+        {
+            return m_Buckets[hash_value( key )];
+        }
+        //@endcond
     };
 
 }} // namespace cds::intrusive
 
 #endif // #ifndef CDSLIB_INTRUSIVE_MICHAEL_SET_NOGC_H
-
index 603fe7b..912c132 100644 (file)
       <Optimization>Disabled</Optimization>\r
       <PreprocessorDefinitions>_ENABLE_ATOMIC_ALIGNMENT_FIX;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
       <AdditionalIncludeDirectories>$(SolutionDir)..\..\..;$(GTEST_ROOT)/include;$(SolutionDir)..\..\..\test\include;$(BOOST_PATH);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
+      <AdditionalOptions>/bigobj %(AdditionalOptions)</AdditionalOptions>\r
+      <DisableSpecificWarnings>4503</DisableSpecificWarnings>\r
     </ClCompile>\r
     <Link>\r
       <SubSystem>Console</SubSystem>\r
       <Optimization>Disabled</Optimization>\r
       <PreprocessorDefinitions>_ENABLE_ATOMIC_ALIGNMENT_FIX;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
       <AdditionalIncludeDirectories>$(SolutionDir)..\..\..;$(GTEST_ROOT)/include;$(SolutionDir)..\..\..\test\include;$(BOOST_PATH);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
+      <AdditionalOptions>/bigobj %(AdditionalOptions)</AdditionalOptions>\r
+      <DisableSpecificWarnings>4503</DisableSpecificWarnings>\r
     </ClCompile>\r
     <Link>\r
       <SubSystem>Console</SubSystem>\r
       <Optimization>Disabled</Optimization>\r
       <PreprocessorDefinitions>_ENABLE_ATOMIC_ALIGNMENT_FIX;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
       <AdditionalIncludeDirectories>$(SolutionDir)..\..\..;$(GTEST_ROOT)/include;$(SolutionDir)..\..\..\test\include;$(BOOST_PATH);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
+      <AdditionalOptions>/bigobj %(AdditionalOptions)</AdditionalOptions>\r
+      <DisableSpecificWarnings>4503</DisableSpecificWarnings>\r
     </ClCompile>\r
     <Link>\r
       <SubSystem>Console</SubSystem>\r
       <Optimization>Disabled</Optimization>\r
       <PreprocessorDefinitions>_ENABLE_ATOMIC_ALIGNMENT_FIX;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
       <AdditionalIncludeDirectories>$(SolutionDir)..\..\..;$(GTEST_ROOT)/include;$(SolutionDir)..\..\..\test\include;$(BOOST_PATH);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
+      <AdditionalOptions>/bigobj %(AdditionalOptions)</AdditionalOptions>\r
+      <DisableSpecificWarnings>4503</DisableSpecificWarnings>\r
     </ClCompile>\r
     <Link>\r
       <SubSystem>Console</SubSystem>\r
       <IntrinsicFunctions>true</IntrinsicFunctions>\r
       <PreprocessorDefinitions>_ENABLE_ATOMIC_ALIGNMENT_FIX;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
       <AdditionalIncludeDirectories>$(SolutionDir)..\..\..;$(GTEST_ROOT)/include;$(SolutionDir)..\..\..\test\include;$(BOOST_PATH);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
+      <AdditionalOptions>/bigobj %(AdditionalOptions)</AdditionalOptions>\r
+      <DisableSpecificWarnings>4503</DisableSpecificWarnings>\r
     </ClCompile>\r
     <Link>\r
       <SubSystem>Console</SubSystem>\r
       <IntrinsicFunctions>true</IntrinsicFunctions>\r
       <PreprocessorDefinitions>_ENABLE_ATOMIC_ALIGNMENT_FIX;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
       <AdditionalIncludeDirectories>$(SolutionDir)..\..\..;$(GTEST_ROOT)/include;$(SolutionDir)..\..\..\test\include;$(BOOST_PATH);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
+      <AdditionalOptions>/bigobj %(AdditionalOptions)</AdditionalOptions>\r
+      <DisableSpecificWarnings>4503</DisableSpecificWarnings>\r
     </ClCompile>\r
     <Link>\r
       <SubSystem>Console</SubSystem>\r
index 6a2b89a..527a2f0 100644 (file)
@@ -123,4 +123,46 @@ namespace {
         test( s );
     }
 
+    TEST_F( IntrusiveMichaelIterableSet_DHP, stat )
+    {
+        struct list_traits: public ci::iterable_list::traits
+        {
+            typedef base_class::less<item_type> less;
+            typedef mock_disposer disposer;
+            typedef ci::iterable_list::stat<> stat;
+        };
+        typedef ci::IterableList< gc_type, item_type, list_traits > bucket_type;
+
+        struct set_traits: public ci::michael_set::traits
+        {
+            typedef hash_int hash;
+            typedef simple_item_counter item_counter;
+        };
+        typedef ci::MichaelHashSet< gc_type, bucket_type, set_traits > set_type;
+
+        set_type s( kSize, 2 );
+        test( s );
+    }
+
+    TEST_F( IntrusiveMichaelIterableSet_DHP, wrapped_stat )
+    {
+        struct list_traits: public ci::iterable_list::traits
+        {
+            typedef base_class::less<item_type> less;
+            typedef mock_disposer disposer;
+            typedef ci::iterable_list::wrapped_stat<> stat;
+        };
+        typedef ci::IterableList< gc_type, item_type, list_traits > bucket_type;
+
+        struct set_traits: public ci::michael_set::traits
+        {
+            typedef hash_int hash;
+            typedef simple_item_counter item_counter;
+        };
+        typedef ci::MichaelHashSet< gc_type, bucket_type, set_traits > set_type;
+
+        set_type s( kSize, 2 );
+        test( s );
+    }
+
 } // namespace
index 4498172..98af775 100644 (file)
@@ -124,4 +124,48 @@ namespace {
         test( s );
     }
 
+    TEST_F( IntrusiveMichaelIterableSet_HP, stat )
+    {
+        struct list_traits: public ci::iterable_list::traits
+        {
+            typedef base_class::less<item_type> less;
+            typedef cmp<item_type> compare;
+            typedef mock_disposer disposer;
+            typedef ci::iterable_list::stat<> stat;
+        };
+        typedef ci::IterableList< gc_type, item_type, list_traits > bucket_type;
+
+        struct set_traits: public ci::michael_set::traits
+        {
+            typedef hash_int hash;
+            typedef simple_item_counter item_counter;
+        };
+        typedef ci::MichaelHashSet< gc_type, bucket_type, set_traits > set_type;
+
+        set_type s( kSize, 2 );
+        test( s );
+    }
+
+    TEST_F( IntrusiveMichaelIterableSet_HP, wrapped_stat )
+    {
+        struct list_traits: public ci::iterable_list::traits
+        {
+            typedef base_class::less<item_type> less;
+            typedef cmp<item_type> compare;
+            typedef mock_disposer disposer;
+            typedef ci::iterable_list::wrapped_stat<> stat;
+        };
+        typedef ci::IterableList< gc_type, item_type, list_traits > bucket_type;
+
+        struct set_traits: public ci::michael_set::traits
+        {
+            typedef hash_int hash;
+            typedef simple_item_counter item_counter;
+        };
+        typedef ci::MichaelHashSet< gc_type, bucket_type, set_traits > set_type;
+
+        set_type s( kSize, 2 );
+        test( s );
+    }
+
 } // namespace
index 4b2a2ce..5931528 100644 (file)
@@ -158,6 +158,49 @@ namespace {
         test( s );
     }
 
+    TEST_F( IntrusiveMichaelLazySet_DHP, base_stat )
+    {
+        struct list_traits: public ci::lazy_list::traits
+        {
+            typedef ci::lazy_list::base_hook< ci::opt::gc<gc_type>> hook;
+            typedef base_class::less<base_item_type> less;
+            typedef mock_disposer disposer;
+            typedef ci::lazy_list::stat<> stat;
+        };
+        typedef ci::LazyList< gc_type, base_item_type, list_traits > bucket_type;
+
+        struct set_traits: public ci::michael_set::traits
+        {
+            typedef hash_int hash;
+            typedef simple_item_counter item_counter;
+        };
+        typedef ci::MichaelHashSet< gc_type, bucket_type, set_traits > set_type;
+
+        set_type s( kSize, 2 );
+        test( s );
+    }
+
+    TEST_F( IntrusiveMichaelLazySet_DHP, base_wrapped_stat )
+    {
+        struct list_traits: public ci::lazy_list::traits
+        {
+            typedef ci::lazy_list::base_hook< ci::opt::gc<gc_type>> hook;
+            typedef base_class::less<base_item_type> less;
+            typedef mock_disposer disposer;
+            typedef ci::lazy_list::wrapped_stat<> stat;
+        };
+        typedef ci::LazyList< gc_type, base_item_type, list_traits > bucket_type;
+
+        struct set_traits: public ci::michael_set::traits
+        {
+            typedef hash_int hash;
+            typedef simple_item_counter item_counter;
+        };
+        typedef ci::MichaelHashSet< gc_type, bucket_type, set_traits > set_type;
+
+        set_type s( kSize, 2 );
+        test( s );
+    }
 
     TEST_F( IntrusiveMichaelLazySet_DHP, member_cmp )
     {
@@ -251,4 +294,48 @@ namespace {
         test( s );
     }
 
+    TEST_F( IntrusiveMichaelLazySet_DHP, member_stat )
+    {
+        struct list_traits: public ci::lazy_list::traits
+        {
+            typedef ci::lazy_list::member_hook< offsetof( member_item_type, hMember ), ci::opt::gc<gc_type>> hook;
+            typedef cmp<member_item_type> compare;
+            typedef mock_disposer disposer;
+            typedef ci::lazy_list::stat<> stat;
+        };
+        typedef ci::LazyList< gc_type, member_item_type, list_traits > bucket_type;
+
+        struct set_traits: public ci::michael_set::traits
+        {
+            typedef hash_int hash;
+            typedef simple_item_counter item_counter;
+        };
+        typedef ci::MichaelHashSet< gc_type, bucket_type, set_traits > set_type;
+
+        set_type s( kSize, 2 );
+        test( s );
+    }
+
+    TEST_F( IntrusiveMichaelLazySet_DHP, member_wrapped_stat )
+    {
+        struct list_traits: public ci::lazy_list::traits
+        {
+            typedef ci::lazy_list::member_hook< offsetof( member_item_type, hMember ), ci::opt::gc<gc_type>> hook;
+            typedef cmp<member_item_type> compare;
+            typedef mock_disposer disposer;
+            typedef ci::lazy_list::wrapped_stat<> stat;
+        };
+        typedef ci::LazyList< gc_type, member_item_type, list_traits > bucket_type;
+
+        struct set_traits: public ci::michael_set::traits
+        {
+            typedef hash_int hash;
+            typedef simple_item_counter item_counter;
+        };
+        typedef ci::MichaelHashSet< gc_type, bucket_type, set_traits > set_type;
+
+        set_type s( kSize, 2 );
+        test( s );
+    }
+
 } // namespace
index 6583d32..1379e83 100644 (file)
@@ -25,7 +25,7 @@
     SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
     CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
     OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.     
+    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
 #include "test_intrusive_set_hp.h"
@@ -159,6 +159,50 @@ namespace {
         test( s );
     }
 
+    TEST_F( IntrusiveMichaelLazySet_HP, base_stat )
+    {
+        struct list_traits: public ci::lazy_list::traits
+        {
+            typedef ci::lazy_list::base_hook< ci::opt::gc<gc_type>, ci::opt::lock_type<std::mutex>> hook;
+            typedef cmp<base_mutex_item_type> compare;
+            typedef mock_disposer disposer;
+            typedef ci::lazy_list::stat<> stat;
+        };
+        typedef ci::LazyList< gc_type, base_mutex_item_type, list_traits > bucket_type;
+
+        struct set_traits: public ci::michael_set::traits
+        {
+            typedef hash_int hash;
+            typedef simple_item_counter item_counter;
+        };
+        typedef ci::MichaelHashSet< gc_type, bucket_type, set_traits > set_type;
+
+        set_type s( kSize, 2 );
+        test( s );
+    }
+
+    TEST_F( IntrusiveMichaelLazySet_HP, base_wrapped_stat )
+    {
+        struct list_traits: public ci::lazy_list::traits
+        {
+            typedef ci::lazy_list::base_hook< ci::opt::gc<gc_type>> hook;
+            typedef cmp<base_item_type> compare;
+            typedef mock_disposer disposer;
+            typedef ci::lazy_list::wrapped_stat<> stat;
+        };
+        typedef ci::LazyList< gc_type, base_item_type, list_traits > bucket_type;
+
+        struct set_traits: public ci::michael_set::traits
+        {
+            typedef hash_int hash;
+            typedef simple_item_counter item_counter;
+        };
+        typedef ci::MichaelHashSet< gc_type, bucket_type, set_traits > set_type;
+
+        set_type s( kSize, 2 );
+        test( s );
+    }
+
 
     TEST_F( IntrusiveMichaelLazySet_HP, member_cmp )
     {
@@ -252,4 +296,48 @@ namespace {
         test( s );
     }
 
+    TEST_F( IntrusiveMichaelLazySet_HP, member_stat )
+    {
+        struct list_traits: public ci::lazy_list::traits
+        {
+            typedef ci::lazy_list::member_hook< offsetof( member_item_type, hMember ), ci::opt::gc<gc_type>> hook;
+            typedef base_class::less<member_item_type> less;
+            typedef mock_disposer disposer;
+            typedef ci::lazy_list::stat<> stat;
+        };
+        typedef ci::LazyList< gc_type, member_item_type, list_traits > bucket_type;
+
+        struct set_traits: public ci::michael_set::traits
+        {
+            typedef hash_int hash;
+            typedef simple_item_counter item_counter;
+        };
+        typedef ci::MichaelHashSet< gc_type, bucket_type, set_traits > set_type;
+
+        set_type s( kSize, 2 );
+        test( s );
+    }
+
+    TEST_F( IntrusiveMichaelLazySet_HP, member_wrapped_stat )
+    {
+        struct list_traits: public ci::lazy_list::traits
+        {
+            typedef ci::lazy_list::member_hook< offsetof( member_item_type, hMember ), ci::opt::gc<gc_type>> hook;
+            typedef base_class::less<member_item_type> less;
+            typedef mock_disposer disposer;
+            typedef ci::lazy_list::wrapped_stat<> stat;
+        };
+        typedef ci::LazyList< gc_type, member_item_type, list_traits > bucket_type;
+
+        struct set_traits: public ci::michael_set::traits
+        {
+            typedef hash_int hash;
+            typedef simple_item_counter item_counter;
+        };
+        typedef ci::MichaelHashSet< gc_type, bucket_type, set_traits > set_type;
+
+        set_type s( kSize, 2 );
+        test( s );
+    }
+
 } // namespace
index c183de4..0c282dd 100644 (file)
@@ -25,7 +25,7 @@
     SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
     CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
     OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.     
+    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
 #include "test_intrusive_set_nogc.h"
@@ -145,6 +145,49 @@ namespace {
         test( s );
     }
 
+    TEST_F( IntrusiveMichaelLazySet_NoGC, base_stat )
+    {
+        struct list_traits: public ci::lazy_list::traits
+        {
+            typedef ci::lazy_list::base_hook< ci::opt::gc<gc_type>> hook;
+            typedef base_class::less<base_item_type> less;
+            typedef mock_disposer disposer;
+            typedef ci::lazy_list::stat<> stat;
+        };
+        typedef ci::LazyList< gc_type, base_item_type, list_traits > bucket_type;
+
+        struct set_traits: public ci::michael_set::traits
+        {
+            typedef hash_int hash;
+            typedef simple_item_counter item_counter;
+        };
+        typedef ci::MichaelHashSet< gc_type, bucket_type, set_traits > set_type;
+
+        set_type s( kSize, 2 );
+        test( s );
+    }
+
+    TEST_F( IntrusiveMichaelLazySet_NoGC, base_wrapped_stat )
+    {
+        struct list_traits: public ci::lazy_list::traits
+        {
+            typedef ci::lazy_list::base_hook< ci::opt::gc<gc_type>> hook;
+            typedef base_class::less<base_item_type> less;
+            typedef mock_disposer disposer;
+            typedef ci::lazy_list::wrapped_stat<> stat;
+        };
+        typedef ci::LazyList< gc_type, base_item_type, list_traits > bucket_type;
+
+        struct set_traits: public ci::michael_set::traits
+        {
+            typedef hash_int hash;
+            typedef simple_item_counter item_counter;
+        };
+        typedef ci::MichaelHashSet< gc_type, bucket_type, set_traits > set_type;
+
+        set_type s( kSize, 2 );
+        test( s );
+    }
 
     TEST_F( IntrusiveMichaelLazySet_NoGC, member_cmp )
     {
@@ -238,4 +281,48 @@ namespace {
         test( s );
     }
 
+    TEST_F( IntrusiveMichaelLazySet_NoGC, member_stat )
+    {
+        struct list_traits: public ci::lazy_list::traits
+        {
+            typedef ci::lazy_list::member_hook< offsetof( member_item_type, hMember ), ci::opt::gc<gc_type>> hook;
+            typedef cmp<member_item_type> compare;
+            typedef mock_disposer disposer;
+            typedef ci::lazy_list::stat<> stat;
+        };
+        typedef ci::LazyList< gc_type, member_item_type, list_traits > bucket_type;
+
+        struct set_traits: public ci::michael_set::traits
+        {
+            typedef hash_int hash;
+            typedef simple_item_counter item_counter;
+        };
+        typedef ci::MichaelHashSet< gc_type, bucket_type, set_traits > set_type;
+
+        set_type s( kSize, 2 );
+        test( s );
+    }
+
+    TEST_F( IntrusiveMichaelLazySet_NoGC, member_wrapped_stat )
+    {
+        struct list_traits: public ci::lazy_list::traits
+        {
+            typedef ci::lazy_list::member_hook< offsetof( member_item_type, hMember ), ci::opt::gc<gc_type>> hook;
+            typedef cmp<member_item_type> compare;
+            typedef mock_disposer disposer;
+            typedef ci::lazy_list::wrapped_stat<> stat;
+        };
+        typedef ci::LazyList< gc_type, member_item_type, list_traits > bucket_type;
+
+        struct set_traits: public ci::michael_set::traits
+        {
+            typedef hash_int hash;
+            typedef simple_item_counter item_counter;
+        };
+        typedef ci::MichaelHashSet< gc_type, bucket_type, set_traits > set_type;
+
+        set_type s( kSize, 2 );
+        test( s );
+    }
+
 } // namespace
index f722718..77e0d25 100644 (file)
@@ -131,6 +131,51 @@ namespace {
         test( s );
     }
 
+    TEST_F( IntrusiveMichaelSet_DHP, base_stat )
+    {
+        struct list_traits: public ci::michael_list::traits
+        {
+            typedef ci::michael_list::base_hook< ci::opt::gc<gc_type>> hook;
+            typedef base_class::less<base_item_type> less;
+            typedef cmp<base_item_type> compare;
+            typedef mock_disposer disposer;
+            typedef ci::michael_list::stat<> stat;
+        };
+        typedef ci::MichaelList< gc_type, base_item_type, list_traits > bucket_type;
+
+        struct set_traits: public ci::michael_set::traits
+        {
+            typedef hash_int hash;
+            typedef simple_item_counter item_counter;
+        };
+        typedef ci::MichaelHashSet< gc_type, bucket_type, set_traits > set_type;
+
+        set_type s( kSize, 2 );
+        test( s );
+    }
+
+    TEST_F( IntrusiveMichaelSet_DHP, base_wrapped_stat )
+    {
+        struct list_traits: public ci::michael_list::traits
+        {
+            typedef ci::michael_list::base_hook< ci::opt::gc<gc_type>> hook;
+            typedef base_class::less<base_item_type> less;
+            typedef cmp<base_item_type> compare;
+            typedef mock_disposer disposer;
+            typedef ci::michael_list::wrapped_stat<> stat;
+        };
+        typedef ci::MichaelList< gc_type, base_item_type, list_traits > bucket_type;
+
+        struct set_traits: public ci::michael_set::traits
+        {
+            typedef hash_int hash;
+            typedef simple_item_counter item_counter;
+        };
+        typedef ci::MichaelHashSet< gc_type, bucket_type, set_traits > set_type;
+
+        set_type s( kSize, 2 );
+        test( s );
+    }
 
     TEST_F( IntrusiveMichaelSet_DHP, member_cmp )
     {
@@ -202,4 +247,50 @@ namespace {
         test( s );
     }
 
+    TEST_F( IntrusiveMichaelSet_DHP, member_stat )
+    {
+        struct list_traits: public ci::michael_list::traits
+        {
+            typedef ci::michael_list::member_hook< offsetof( member_item_type, hMember ), ci::opt::gc<gc_type>> hook;
+            typedef base_class::less<member_item_type> less;
+            typedef cmp<member_item_type> compare;
+            typedef mock_disposer disposer;
+            typedef ci::michael_list::stat<> stat;
+        };
+        typedef ci::MichaelList< gc_type, member_item_type, list_traits > bucket_type;
+
+        struct set_traits: public ci::michael_set::traits
+        {
+            typedef hash_int hash;
+            typedef simple_item_counter item_counter;
+        };
+        typedef ci::MichaelHashSet< gc_type, bucket_type, set_traits > set_type;
+
+        set_type s( kSize, 2 );
+        test( s );
+    }
+
+    TEST_F( IntrusiveMichaelSet_DHP, member_wrapped_stat )
+    {
+        struct list_traits: public ci::michael_list::traits
+        {
+            typedef ci::michael_list::member_hook< offsetof( member_item_type, hMember ), ci::opt::gc<gc_type>> hook;
+            typedef base_class::less<member_item_type> less;
+            typedef cmp<member_item_type> compare;
+            typedef mock_disposer disposer;
+            typedef ci::michael_list::wrapped_stat<> stat;
+        };
+        typedef ci::MichaelList< gc_type, member_item_type, list_traits > bucket_type;
+
+        struct set_traits: public ci::michael_set::traits
+        {
+            typedef hash_int hash;
+            typedef simple_item_counter item_counter;
+        };
+        typedef ci::MichaelHashSet< gc_type, bucket_type, set_traits > set_type;
+
+        set_type s( kSize, 2 );
+        test( s );
+    }
+
 } // namespace
index f408b47..92e000d 100644 (file)
@@ -133,6 +133,50 @@ namespace {
     }
 
 
+    TEST_F( IntrusiveMichaelSet_HP, base_stat )
+    {
+        struct list_traits: public ci::michael_list::traits
+        {
+            typedef ci::michael_list::base_hook< ci::opt::gc<gc_type>> hook;
+            typedef cmp<base_item_type> compare;
+            typedef mock_disposer disposer;
+            typedef ci::michael_list::stat<> stat;
+        };
+        typedef ci::MichaelList< gc_type, base_item_type, list_traits > bucket_type;
+
+        struct set_traits: public ci::michael_set::traits
+        {
+            typedef hash_int hash;
+            typedef simple_item_counter item_counter;
+        };
+        typedef ci::MichaelHashSet< gc_type, bucket_type, set_traits > set_type;
+
+        set_type s( kSize, 2 );
+        test( s );
+    }
+
+    TEST_F( IntrusiveMichaelSet_HP, base_wrapped_stat )
+    {
+        struct list_traits: public ci::michael_list::traits
+        {
+            typedef ci::michael_list::base_hook< ci::opt::gc<gc_type>> hook;
+            typedef base_class::less<base_item_type> less;
+            typedef mock_disposer disposer;
+            typedef ci::michael_list::wrapped_stat<> stat;
+        };
+        typedef ci::MichaelList< gc_type, base_item_type, list_traits > bucket_type;
+
+        struct set_traits: public ci::michael_set::traits
+        {
+            typedef hash_int hash;
+            typedef simple_item_counter item_counter;
+        };
+        typedef ci::MichaelHashSet< gc_type, bucket_type, set_traits > set_type;
+
+        set_type s( kSize, 2 );
+        test( s );
+    }
+
     TEST_F( IntrusiveMichaelSet_HP, member_cmp )
     {
         typedef ci::MichaelList< gc_type
@@ -203,4 +247,50 @@ namespace {
         test( s );
     }
 
+    TEST_F( IntrusiveMichaelSet_HP, member_stat )
+    {
+        struct list_traits: public ci::michael_list::traits
+        {
+            typedef ci::michael_list::member_hook< offsetof( member_item_type, hMember ), ci::opt::gc<gc_type>> hook;
+            typedef base_class::less<member_item_type> less;
+            typedef cmp<member_item_type> compare;
+            typedef mock_disposer disposer;
+            typedef ci::michael_list::stat<> stat;
+        };
+        typedef ci::MichaelList< gc_type, member_item_type, list_traits > bucket_type;
+
+        struct set_traits: public ci::michael_set::traits
+        {
+            typedef hash_int hash;
+            typedef simple_item_counter item_counter;
+        };
+        typedef ci::MichaelHashSet< gc_type, bucket_type, set_traits > set_type;
+
+        set_type s( kSize, 2 );
+        test( s );
+    }
+
+    TEST_F( IntrusiveMichaelSet_HP, member_wrapped_stat )
+    {
+        struct list_traits: public ci::michael_list::traits
+        {
+            typedef ci::michael_list::member_hook< offsetof( member_item_type, hMember ), ci::opt::gc<gc_type>> hook;
+            typedef base_class::less<member_item_type> less;
+            typedef cmp<member_item_type> compare;
+            typedef mock_disposer disposer;
+            typedef ci::michael_list::wrapped_stat<> stat;
+        };
+        typedef ci::MichaelList< gc_type, member_item_type, list_traits > bucket_type;
+
+        struct set_traits: public ci::michael_set::traits
+        {
+            typedef hash_int hash;
+            typedef simple_item_counter item_counter;
+        };
+        typedef ci::MichaelHashSet< gc_type, bucket_type, set_traits > set_type;
+
+        set_type s( kSize, 2 );
+        test( s );
+    }
+
 } // namespace
index 2ce9e2b..02ab228 100644 (file)
@@ -25,7 +25,7 @@
     SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
     CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
     OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.     
+    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
 #include "test_intrusive_set_nogc.h"
@@ -118,6 +118,49 @@ namespace {
         test( s );
     }
 
+    TEST_F( IntrusiveMichaelSet_NoGC, base_stat )
+    {
+        struct list_traits: public ci::michael_list::traits
+        {
+            typedef ci::michael_list::base_hook< ci::opt::gc<gc_type>> hook;
+            typedef base_class::less<base_item_type> less;
+            typedef mock_disposer disposer;
+            typedef ci::michael_list::stat<> stat;
+        };
+        typedef ci::MichaelList< gc_type, base_item_type, list_traits > bucket_type;
+
+        struct set_traits: public ci::michael_set::traits
+        {
+            typedef hash_int hash;
+            typedef simple_item_counter item_counter;
+        };
+        typedef ci::MichaelHashSet< gc_type, bucket_type, set_traits > set_type;
+
+        set_type s( kSize, 2 );
+        test( s );
+    }
+
+    TEST_F( IntrusiveMichaelSet_NoGC, base_wrapped_stat )
+    {
+        struct list_traits: public ci::michael_list::traits
+        {
+            typedef ci::michael_list::base_hook< ci::opt::gc<gc_type>> hook;
+            typedef base_class::less<base_item_type> less;
+            typedef mock_disposer disposer;
+            typedef ci::michael_list::wrapped_stat<> stat;
+        };
+        typedef ci::MichaelList< gc_type, base_item_type, list_traits > bucket_type;
+
+        struct set_traits: public ci::michael_set::traits
+        {
+            typedef hash_int hash;
+            typedef simple_item_counter item_counter;
+        };
+        typedef ci::MichaelHashSet< gc_type, bucket_type, set_traits > set_type;
+
+        set_type s( kSize, 2 );
+        test( s );
+    }
 
     TEST_F( IntrusiveMichaelSet_NoGC, member_cmp )
     {
@@ -189,4 +232,48 @@ namespace {
         test( s );
     }
 
+    TEST_F( IntrusiveMichaelSet_NoGC, member_stat )
+    {
+        struct list_traits: public ci::michael_list::traits
+        {
+            typedef ci::michael_list::member_hook< offsetof( member_item_type, hMember ), ci::opt::gc<gc_type>> hook;
+            typedef cmp<member_item_type> compare;
+            typedef mock_disposer disposer;
+            typedef ci::michael_list::stat<> stat;
+        };
+        typedef ci::MichaelList< gc_type, member_item_type, list_traits > bucket_type;
+
+        struct set_traits: public ci::michael_set::traits
+        {
+            typedef hash_int hash;
+            typedef simple_item_counter item_counter;
+        };
+        typedef ci::MichaelHashSet< gc_type, bucket_type, set_traits > set_type;
+
+        set_type s( kSize, 2 );
+        test( s );
+    }
+
+    TEST_F( IntrusiveMichaelSet_NoGC, member_wrapped_stat )
+    {
+        struct list_traits: public ci::michael_list::traits
+        {
+            typedef ci::michael_list::member_hook< offsetof( member_item_type, hMember ), ci::opt::gc<gc_type>> hook;
+            typedef cmp<member_item_type> compare;
+            typedef mock_disposer disposer;
+            typedef ci::michael_list::wrapped_stat<> stat;
+        };
+        typedef ci::MichaelList< gc_type, member_item_type, list_traits > bucket_type;
+
+        struct set_traits: public ci::michael_set::traits
+        {
+            typedef hash_int hash;
+            typedef simple_item_counter item_counter;
+        };
+        typedef ci::MichaelHashSet< gc_type, bucket_type, set_traits > set_type;
+
+        set_type s( kSize, 2 );
+        test( s );
+    }
+
 } // namespace
index c32fdb6..13d9591 100644 (file)
@@ -25,7 +25,7 @@
     SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
     CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
     OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.     
+    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 #ifndef CDSUNIT_SET_TEST_INTRUSIVE_MICHAEL_LAZY_RCU_H
 #define CDSUNIT_SET_TEST_INTRUSIVE_MICHAEL_LAZY_RCU_H
@@ -171,6 +171,59 @@ TYPED_TEST_P( IntrusiveMichaelLazySet, base_mutex )
     this->test( s );
 }
 
+TYPED_TEST_P( IntrusiveMichaelLazySet, base_stat )
+{
+    typedef typename TestFixture::rcu_type rcu_type;
+    typedef typename TestFixture::base_item_type base_item_type;
+    typedef typename TestFixture::mock_disposer mock_disposer;
+    typedef typename TestFixture::hash_int hash_int;
+
+    struct list_traits: public ci::lazy_list::traits
+    {
+        typedef ci::lazy_list::base_hook< ci::opt::gc<rcu_type>> hook;
+        typedef typename TestFixture::template less<base_item_type> less;
+        typedef mock_disposer disposer;
+        typedef ci::lazy_list::stat<> stat;
+    };
+    typedef ci::LazyList< rcu_type, base_item_type, list_traits > bucket_type;
+
+    struct set_traits: public ci::michael_set::traits
+    {
+        typedef hash_int hash;
+        typedef typename TestFixture::simple_item_counter item_counter;
+    };
+    typedef ci::MichaelHashSet< rcu_type, bucket_type, set_traits > set_type;
+
+    set_type s( TestFixture::kSize, 2 );
+    this->test( s );
+}
+
+TYPED_TEST_P( IntrusiveMichaelLazySet, base_wrapped_stat )
+{
+    typedef typename TestFixture::rcu_type rcu_type;
+    typedef typename TestFixture::base_item_type base_item_type;
+    typedef typename TestFixture::mock_disposer mock_disposer;
+    typedef typename TestFixture::hash_int hash_int;
+
+    struct list_traits: public ci::lazy_list::traits
+    {
+        typedef ci::lazy_list::base_hook< ci::opt::gc<rcu_type>> hook;
+        typedef typename TestFixture::template less<base_item_type> less;
+        typedef mock_disposer disposer;
+        typedef ci::lazy_list::wrapped_stat<> stat;
+    };
+    typedef ci::LazyList< rcu_type, base_item_type, list_traits > bucket_type;
+
+    struct set_traits: public ci::michael_set::traits
+    {
+        typedef hash_int hash;
+        typedef typename TestFixture::simple_item_counter item_counter;
+    };
+    typedef ci::MichaelHashSet< rcu_type, bucket_type, set_traits > set_type;
+
+    set_type s( TestFixture::kSize, 2 );
+    this->test( s );
+}
 
 TYPED_TEST_P( IntrusiveMichaelLazySet, member_cmp )
 {
@@ -286,11 +339,64 @@ TYPED_TEST_P( IntrusiveMichaelLazySet, member_mutex )
     this->test( s );
 }
 
+TYPED_TEST_P( IntrusiveMichaelLazySet, member_stat )
+{
+    typedef typename TestFixture::rcu_type rcu_type;
+    typedef typename TestFixture::member_item_type member_item_type;
+    typedef typename TestFixture::mock_disposer mock_disposer;
+    typedef typename TestFixture::hash_int hash_int;
+
+    struct list_traits: public ci::lazy_list::traits
+    {
+        typedef ci::lazy_list::member_hook< offsetof( member_item_type, hMember ), ci::opt::gc<rcu_type>> hook;
+        typedef typename TestFixture::template cmp<member_item_type> compare;
+        typedef mock_disposer disposer;
+        typedef ci::lazy_list::stat<> stat;
+    };
+    typedef ci::LazyList< rcu_type, member_item_type, list_traits > bucket_type;
+
+    struct set_traits: public ci::michael_set::traits
+    {
+        typedef hash_int hash;
+        typedef typename TestFixture::simple_item_counter item_counter;
+    };
+    typedef ci::MichaelHashSet< rcu_type, bucket_type, set_traits > set_type;
+
+    set_type s( TestFixture::kSize, 2 );
+    this->test( s );
+}
+
+TYPED_TEST_P( IntrusiveMichaelLazySet, member_wrapped_stat )
+{
+    typedef typename TestFixture::rcu_type rcu_type;
+    typedef typename TestFixture::member_item_type member_item_type;
+    typedef typename TestFixture::mock_disposer mock_disposer;
+    typedef typename TestFixture::hash_int hash_int;
+
+    struct list_traits: public ci::lazy_list::traits
+    {
+        typedef ci::lazy_list::member_hook< offsetof( member_item_type, hMember ), ci::opt::gc<rcu_type>> hook;
+        typedef typename TestFixture::template cmp<member_item_type> compare;
+        typedef mock_disposer disposer;
+        typedef ci::lazy_list::wrapped_stat<> stat;
+    };
+    typedef ci::LazyList< rcu_type, member_item_type, list_traits > bucket_type;
+
+    struct set_traits: public ci::michael_set::traits
+    {
+        typedef hash_int hash;
+        typedef typename TestFixture::simple_item_counter item_counter;
+    };
+    typedef ci::MichaelHashSet< rcu_type, bucket_type, set_traits > set_type;
+
+    set_type s( TestFixture::kSize, 2 );
+    this->test( s );
+}
 
 // GCC 5: All test names should be written on single line, otherwise a runtime error will be encountered like as
 // "No test named <test_name> can be found in this test case"
 REGISTER_TYPED_TEST_CASE_P( IntrusiveMichaelLazySet,
-    base_cmp, base_less, base_cmpmix, base_mutex, member_cmp, member_less, member_cmpmix, member_mutex
+    base_cmp, base_less, base_cmpmix, base_mutex, base_stat, base_wrapped_stat, member_cmp, member_less, member_cmpmix, member_mutex, member_stat, member_wrapped_stat
 );
 
 
index 199fef5..a8b02e2 100644 (file)
@@ -25,7 +25,7 @@
     SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
     CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
     OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.     
+    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 #ifndef CDSUNIT_SET_TEST_INTRUSIVE_MICHAEL_MICHAEL_RCU_H
 #define CDSUNIT_SET_TEST_INTRUSIVE_MICHAEL_MICHAEL_RCU_H
@@ -142,6 +142,61 @@ TYPED_TEST_P( IntrusiveMichaelSet, base_cmpmix )
     this->test( s );
 }
 
+TYPED_TEST_P( IntrusiveMichaelSet, base_stat )
+{
+    typedef typename TestFixture::rcu_type rcu_type;
+    typedef typename TestFixture::base_item_type base_item_type;
+    typedef typename TestFixture::mock_disposer mock_disposer;
+    typedef typename TestFixture::hash_int hash_int;
+
+    struct list_traits: public ci::michael_list::traits
+    {
+        typedef ci::michael_list::base_hook< ci::opt::gc<rcu_type>> hook;
+        typedef typename TestFixture::template less<base_item_type> less;
+        typedef typename TestFixture::template cmp<base_item_type> compare;
+        typedef mock_disposer disposer;
+        typedef ci::michael_list::stat<> stat;
+    };
+    typedef ci::MichaelList< rcu_type, base_item_type, list_traits > bucket_type;
+
+    struct set_traits: public ci::michael_set::traits
+    {
+        typedef hash_int hash;
+        typedef typename TestFixture::simple_item_counter item_counter;
+    };
+    typedef ci::MichaelHashSet< rcu_type, bucket_type, set_traits > set_type;
+
+    set_type s( TestFixture::kSize, 2 );
+    this->test( s );
+}
+
+TYPED_TEST_P( IntrusiveMichaelSet, base_wrapped_stat )
+{
+    typedef typename TestFixture::rcu_type rcu_type;
+    typedef typename TestFixture::base_item_type base_item_type;
+    typedef typename TestFixture::mock_disposer mock_disposer;
+    typedef typename TestFixture::hash_int hash_int;
+
+    struct list_traits: public ci::michael_list::traits
+    {
+        typedef ci::michael_list::base_hook< ci::opt::gc<rcu_type>> hook;
+        typedef typename TestFixture::template less<base_item_type> less;
+        typedef typename TestFixture::template cmp<base_item_type> compare;
+        typedef mock_disposer disposer;
+        typedef ci::michael_list::wrapped_stat<> stat;
+    };
+    typedef ci::MichaelList< rcu_type, base_item_type, list_traits > bucket_type;
+
+    struct set_traits: public ci::michael_set::traits
+    {
+        typedef hash_int hash;
+        typedef typename TestFixture::simple_item_counter item_counter;
+    };
+    typedef ci::MichaelHashSet< rcu_type, bucket_type, set_traits > set_type;
+
+    set_type s( TestFixture::kSize, 2 );
+    this->test( s );
+}
 
 TYPED_TEST_P( IntrusiveMichaelSet, member_cmp )
 {
@@ -230,12 +285,64 @@ TYPED_TEST_P( IntrusiveMichaelSet, member_cmpmix )
     this->test( s );
 }
 
+TYPED_TEST_P( IntrusiveMichaelSet, member_stat )
+{
+    typedef typename TestFixture::rcu_type rcu_type;
+    typedef typename TestFixture::member_item_type member_item_type;
+    typedef typename TestFixture::mock_disposer mock_disposer;
+    typedef typename TestFixture::hash_int hash_int;
+
+    struct list_traits: public ci::michael_list::traits
+    {
+        typedef ci::michael_list::member_hook< offsetof( member_item_type, hMember ), ci::opt::gc<rcu_type>> hook;
+        typedef typename TestFixture::template cmp<member_item_type> compare;
+        typedef mock_disposer disposer;
+        typedef ci::michael_list::stat<> stat;
+    };
+    typedef ci::MichaelList< rcu_type, member_item_type, list_traits > bucket_type;
+
+    struct set_traits: public ci::michael_set::traits
+    {
+        typedef hash_int hash;
+        typedef typename TestFixture::simple_item_counter item_counter;
+    };
+    typedef ci::MichaelHashSet< rcu_type, bucket_type, set_traits > set_type;
+
+    set_type s( TestFixture::kSize, 2 );
+    this->test( s );
+}
 
+TYPED_TEST_P( IntrusiveMichaelSet, member_wrapped_stat )
+{
+    typedef typename TestFixture::rcu_type rcu_type;
+    typedef typename TestFixture::member_item_type member_item_type;
+    typedef typename TestFixture::mock_disposer mock_disposer;
+    typedef typename TestFixture::hash_int hash_int;
+
+    struct list_traits: public ci::michael_list::traits
+    {
+        typedef ci::michael_list::member_hook< offsetof( member_item_type, hMember ), ci::opt::gc<rcu_type>> hook;
+        typedef typename TestFixture::template cmp<member_item_type> compare;
+        typedef mock_disposer disposer;
+        typedef ci::michael_list::wrapped_stat<> stat;
+    };
+    typedef ci::MichaelList< rcu_type, member_item_type, list_traits > bucket_type;
+
+    struct set_traits: public ci::michael_set::traits
+    {
+        typedef hash_int hash;
+        typedef typename TestFixture::simple_item_counter item_counter;
+    };
+    typedef ci::MichaelHashSet< rcu_type, bucket_type, set_traits > set_type;
+
+    set_type s( TestFixture::kSize, 2 );
+    this->test( s );
+}
 
 // GCC 5: All test names should be written on single line, otherwise a runtime error will be encountered like as
 // "No test named <test_name> can be found in this test case"
 REGISTER_TYPED_TEST_CASE_P( IntrusiveMichaelSet,
-    base_cmp, base_less, base_cmpmix, member_cmp, member_less, member_cmpmix
+    base_cmp, base_less, base_cmpmix, base_stat, base_wrapped_stat, member_cmp, member_less, member_cmpmix, member_stat, member_wrapped_stat
 );