Merge branch 'dev'
authorkhizmax <khizmax@gmail.com>
Fri, 27 Mar 2015 14:14:50 +0000 (17:14 +0300)
committerkhizmax <khizmax@gmail.com>
Fri, 27 Mar 2015 14:14:50 +0000 (17:14 +0300)
162 files changed:
cds/container/impl/bronson_avltree_map_rcu.h
projects/Win/vc12/unit-map-delodd.vcxproj
projects/Win/vc12/unit-map-find.vcxproj
projects/Win/vc12/unit-map-find.vcxproj.filters [new file with mode: 0644]
projects/Win/vc12/unit-map-insdel.vcxproj
projects/Win/vc12/unit-map-insdel.vcxproj.filters [new file with mode: 0644]
projects/Win/vc12/unit-set-delodd.vcxproj
projects/Win/vc12/unit-set-insdel.vcxproj
projects/Win/vc12/unit-set-insdel.vcxproj.filters [new file with mode: 0644]
projects/source.unit.map.mk
projects/source.unit.set.mk
tests/cppunit/cppunit_mini.h
tests/unit/map2/map_delodd.cpp
tests/unit/map2/map_delodd.h [new file with mode: 0644]
tests/unit/map2/map_delodd_bronsonavltree.cpp [new file with mode: 0644]
tests/unit/map2/map_delodd_cuckoo.cpp [new file with mode: 0644]
tests/unit/map2/map_delodd_ellentree.cpp [new file with mode: 0644]
tests/unit/map2/map_delodd_michael.cpp [new file with mode: 0644]
tests/unit/map2/map_delodd_skip.cpp [new file with mode: 0644]
tests/unit/map2/map_delodd_split.cpp [new file with mode: 0644]
tests/unit/map2/map_find_int.cpp
tests/unit/map2/map_find_int.h [new file with mode: 0644]
tests/unit/map2/map_find_int_bronsonavltree.cpp [new file with mode: 0644]
tests/unit/map2/map_find_int_cuckoo.cpp [new file with mode: 0644]
tests/unit/map2/map_find_int_ellentree.cpp [new file with mode: 0644]
tests/unit/map2/map_find_int_michael.cpp [new file with mode: 0644]
tests/unit/map2/map_find_int_refinable.cpp [new file with mode: 0644]
tests/unit/map2/map_find_int_skip.cpp [new file with mode: 0644]
tests/unit/map2/map_find_int_split.cpp [new file with mode: 0644]
tests/unit/map2/map_find_int_std.cpp [new file with mode: 0644]
tests/unit/map2/map_find_int_striped.cpp [new file with mode: 0644]
tests/unit/map2/map_find_string.cpp
tests/unit/map2/map_find_string.h [new file with mode: 0644]
tests/unit/map2/map_find_string_bronsonavltree.cpp [new file with mode: 0644]
tests/unit/map2/map_find_string_cuckoo.cpp [new file with mode: 0644]
tests/unit/map2/map_find_string_ellentree.cpp [new file with mode: 0644]
tests/unit/map2/map_find_string_michael.cpp [new file with mode: 0644]
tests/unit/map2/map_find_string_refinable.cpp [new file with mode: 0644]
tests/unit/map2/map_find_string_skip.cpp [new file with mode: 0644]
tests/unit/map2/map_find_string_split.cpp [new file with mode: 0644]
tests/unit/map2/map_find_string_std.cpp [new file with mode: 0644]
tests/unit/map2/map_find_string_striped.cpp [new file with mode: 0644]
tests/unit/map2/map_insdel_func.cpp
tests/unit/map2/map_insdel_func2.cpp [deleted file]
tests/unit/map2/map_insdel_func3.cpp [deleted file]
tests/unit/map2/map_insdel_func4.cpp [deleted file]
tests/unit/map2/map_insdel_func5.cpp [deleted file]
tests/unit/map2/map_insdel_func6.cpp [deleted file]
tests/unit/map2/map_insdel_func7.cpp [deleted file]
tests/unit/map2/map_insdel_func8.cpp [deleted file]
tests/unit/map2/map_insdel_func_bronsonavltree.cpp [new file with mode: 0644]
tests/unit/map2/map_insdel_func_cuckoo.cpp [new file with mode: 0644]
tests/unit/map2/map_insdel_func_ellentree.cpp [new file with mode: 0644]
tests/unit/map2/map_insdel_func_michael.cpp [new file with mode: 0644]
tests/unit/map2/map_insdel_func_refinable.cpp [new file with mode: 0644]
tests/unit/map2/map_insdel_func_skip.cpp [new file with mode: 0644]
tests/unit/map2/map_insdel_func_split.cpp [new file with mode: 0644]
tests/unit/map2/map_insdel_func_striped.cpp [new file with mode: 0644]
tests/unit/map2/map_insdel_int.cpp
tests/unit/map2/map_insdel_int.h [new file with mode: 0644]
tests/unit/map2/map_insdel_int_bronsonavltree.cpp [new file with mode: 0644]
tests/unit/map2/map_insdel_int_cuckoo.cpp [new file with mode: 0644]
tests/unit/map2/map_insdel_int_ellentree.cpp [new file with mode: 0644]
tests/unit/map2/map_insdel_int_michael.cpp [new file with mode: 0644]
tests/unit/map2/map_insdel_int_refinable.cpp [new file with mode: 0644]
tests/unit/map2/map_insdel_int_skip.cpp [new file with mode: 0644]
tests/unit/map2/map_insdel_int_split.cpp [new file with mode: 0644]
tests/unit/map2/map_insdel_int_striped.cpp [new file with mode: 0644]
tests/unit/map2/map_insdel_item_int.cpp
tests/unit/map2/map_insdel_item_int.h [new file with mode: 0644]
tests/unit/map2/map_insdel_item_int_bronsonavltree.cpp [new file with mode: 0644]
tests/unit/map2/map_insdel_item_int_cuckoo.cpp [new file with mode: 0644]
tests/unit/map2/map_insdel_item_int_ellentree.cpp [new file with mode: 0644]
tests/unit/map2/map_insdel_item_int_michael.cpp [new file with mode: 0644]
tests/unit/map2/map_insdel_item_int_refinable.cpp [new file with mode: 0644]
tests/unit/map2/map_insdel_item_int_skip.cpp [new file with mode: 0644]
tests/unit/map2/map_insdel_item_int_split.cpp [new file with mode: 0644]
tests/unit/map2/map_insdel_item_int_striped.cpp [new file with mode: 0644]
tests/unit/map2/map_insdel_item_string.cpp
tests/unit/map2/map_insdel_item_string.h [new file with mode: 0644]
tests/unit/map2/map_insdel_item_string_bronsonavltree.cpp [new file with mode: 0644]
tests/unit/map2/map_insdel_item_string_cuckoo.cpp [new file with mode: 0644]
tests/unit/map2/map_insdel_item_string_ellentree.cpp [new file with mode: 0644]
tests/unit/map2/map_insdel_item_string_michael.cpp [new file with mode: 0644]
tests/unit/map2/map_insdel_item_string_refinable.cpp [new file with mode: 0644]
tests/unit/map2/map_insdel_item_string_skip.cpp [new file with mode: 0644]
tests/unit/map2/map_insdel_item_string_split.cpp [new file with mode: 0644]
tests/unit/map2/map_insdel_item_string_striped.cpp [new file with mode: 0644]
tests/unit/map2/map_insdel_string.cpp
tests/unit/map2/map_insdel_string.h [new file with mode: 0644]
tests/unit/map2/map_insdel_string_bronsonavltree.cpp [new file with mode: 0644]
tests/unit/map2/map_insdel_string_cuckoo.cpp [new file with mode: 0644]
tests/unit/map2/map_insdel_string_ellentree.cpp [new file with mode: 0644]
tests/unit/map2/map_insdel_string_michael.cpp [new file with mode: 0644]
tests/unit/map2/map_insdel_string_refinable.cpp [new file with mode: 0644]
tests/unit/map2/map_insdel_string_skip.cpp [new file with mode: 0644]
tests/unit/map2/map_insdel_string_split.cpp [new file with mode: 0644]
tests/unit/map2/map_insdel_string_std.cpp [new file with mode: 0644]
tests/unit/map2/map_insdel_string_striped.cpp [new file with mode: 0644]
tests/unit/map2/map_insdelfind.cpp
tests/unit/map2/map_insdelfind.h [new file with mode: 0644]
tests/unit/map2/map_insdelfind_bronsonavltree.cpp [new file with mode: 0644]
tests/unit/map2/map_insdelfind_cuckoo.cpp [new file with mode: 0644]
tests/unit/map2/map_insdelfind_ellentree.cpp [new file with mode: 0644]
tests/unit/map2/map_insdelfind_michael.cpp [new file with mode: 0644]
tests/unit/map2/map_insdelfind_refinable.cpp [new file with mode: 0644]
tests/unit/map2/map_insdelfind_skip.cpp [new file with mode: 0644]
tests/unit/map2/map_insdelfind_split.cpp [new file with mode: 0644]
tests/unit/map2/map_insdelfind_std.cpp [new file with mode: 0644]
tests/unit/map2/map_insdelfind_striped.cpp [new file with mode: 0644]
tests/unit/map2/map_insfind_int.cpp
tests/unit/map2/map_insfind_int.h [new file with mode: 0644]
tests/unit/map2/map_insfind_int_bronsonavltree.cpp [new file with mode: 0644]
tests/unit/map2/map_insfind_int_cuckoo.cpp [new file with mode: 0644]
tests/unit/map2/map_insfind_int_ellentree.cpp [new file with mode: 0644]
tests/unit/map2/map_insfind_int_michael.cpp [new file with mode: 0644]
tests/unit/map2/map_insfind_int_refinable.cpp [new file with mode: 0644]
tests/unit/map2/map_insfind_int_skip.cpp [new file with mode: 0644]
tests/unit/map2/map_insfind_int_split.cpp [new file with mode: 0644]
tests/unit/map2/map_insfind_int_std.cpp [new file with mode: 0644]
tests/unit/map2/map_insfind_int_striped.cpp [new file with mode: 0644]
tests/unit/map2/map_types.h
tests/unit/set2/set_delodd.cpp
tests/unit/set2/set_delodd.h [new file with mode: 0644]
tests/unit/set2/set_delodd_cuckoo.cpp [new file with mode: 0644]
tests/unit/set2/set_delodd_ellentree.cpp [new file with mode: 0644]
tests/unit/set2/set_delodd_michael.cpp [new file with mode: 0644]
tests/unit/set2/set_delodd_skip.cpp [new file with mode: 0644]
tests/unit/set2/set_delodd_split.cpp [new file with mode: 0644]
tests/unit/set2/set_insdel_func2.cpp [deleted file]
tests/unit/set2/set_insdel_func3.cpp [deleted file]
tests/unit/set2/set_insdel_func4.cpp [deleted file]
tests/unit/set2/set_insdel_func5.cpp [deleted file]
tests/unit/set2/set_insdel_func6.cpp [deleted file]
tests/unit/set2/set_insdel_func7.cpp [deleted file]
tests/unit/set2/set_insdel_func_cuckoo.cpp [new file with mode: 0644]
tests/unit/set2/set_insdel_func_ellentree.cpp [new file with mode: 0644]
tests/unit/set2/set_insdel_func_refinable.cpp [new file with mode: 0644]
tests/unit/set2/set_insdel_func_skip.cpp [new file with mode: 0644]
tests/unit/set2/set_insdel_func_split.cpp [new file with mode: 0644]
tests/unit/set2/set_insdel_func_striped.cpp [new file with mode: 0644]
tests/unit/set2/set_insdel_string.cpp
tests/unit/set2/set_insdel_string.h [new file with mode: 0644]
tests/unit/set2/set_insdel_string_cuckoo.cpp [new file with mode: 0644]
tests/unit/set2/set_insdel_string_ellentree.cpp [new file with mode: 0644]
tests/unit/set2/set_insdel_string_michael.cpp [new file with mode: 0644]
tests/unit/set2/set_insdel_string_refinable.cpp [new file with mode: 0644]
tests/unit/set2/set_insdel_string_skip.cpp [new file with mode: 0644]
tests/unit/set2/set_insdel_string_split.cpp [new file with mode: 0644]
tests/unit/set2/set_insdel_string_std.cpp [new file with mode: 0644]
tests/unit/set2/set_insdel_string_striped.cpp [new file with mode: 0644]
tests/unit/set2/set_insdelfind.cpp
tests/unit/set2/set_insdelfind.h [new file with mode: 0644]
tests/unit/set2/set_insdelfind_cuckoo.cpp [new file with mode: 0644]
tests/unit/set2/set_insdelfind_ellentree.cpp [new file with mode: 0644]
tests/unit/set2/set_insdelfind_michael.cpp [new file with mode: 0644]
tests/unit/set2/set_insdelfind_refinable.cpp [new file with mode: 0644]
tests/unit/set2/set_insdelfind_skip.cpp [new file with mode: 0644]
tests/unit/set2/set_insdelfind_split.cpp [new file with mode: 0644]
tests/unit/set2/set_insdelfind_std.cpp [new file with mode: 0644]
tests/unit/set2/set_insdelfind_striped.cpp [new file with mode: 0644]
tests/unit/set2/set_types.h

index 87a85f6af32fcd925ce2a6878c1897bded321e68..beecde366aea8b6def10d98fd27f6dbc9de2eb12 100644 (file)
@@ -152,12 +152,12 @@ namespace cds { namespace container {
             disposer()(pVal);
         }
 
-        static node_type * child( node_type * pNode, int nDir, atomics::memory_order order )
+        static node_type * child( node_type * pNode, int nDir, atomics::memory_order order = memory_model::memory_order_relaxed )
         {
             return pNode->child( nDir ).load( order );
         }
 
-        static node_type * parent( node_type * pNode, atomics::memory_order order )
+        static node_type * parent( node_type * pNode, atomics::memory_order order = memory_model::memory_order_relaxed )
         {
             return pNode->m_pParent.load( order );
         }
@@ -747,7 +747,7 @@ namespace cds { namespace container {
         template <typename Func>
         bool check_consistency( Func f ) const
         {
-            node_type * pChild = child( m_pRoot, right_child, memory_model::memory_order_relaxed );
+            node_type * pChild = child( m_pRoot, right_child );
             if ( pChild ) {
                 size_t nErrors = 0;
                 do_check_consistency( pChild, 1, f, nErrors );
@@ -762,8 +762,16 @@ namespace cds { namespace container {
         size_t do_check_consistency( node_type * pNode, size_t nLevel, Func f, size_t& nErrors ) const
         {
             if ( pNode ) {
-                size_t hLeft = do_check_consistency( child( pNode, left_child, memory_model::memory_order_relaxed ), nLevel + 1, f, nErrors );
-                size_t hRight = do_check_consistency( child( pNode, right_child, memory_model::memory_order_relaxed ), nLevel + 1, f, nErrors );
+                key_comparator cmp;
+                node_type * pLeft = child( pNode, left_child );
+                node_type * pRight = child( pNode, right_child );
+                if ( pLeft && cmp( pLeft->m_key, pNode->m_key ) > 0 )
+                    ++nErrors;
+                if (  pRight && cmp( pNode->m_key, pRight->m_key ) > 0 )
+                    ++nErrors;
+
+                size_t hLeft = do_check_consistency( pLeft, nLevel + 1, f, nErrors );
+                size_t hRight = do_check_consistency( pRight, nLevel + 1, f, nErrors );
 
                 if ( hLeft >= hRight ) {
                     if ( hLeft - hRight > 1 ) {
@@ -858,7 +866,7 @@ namespace cds { namespace container {
                     // get right child of root
                     node_type * pChild = child( m_pRoot, right_child, memory_model::memory_order_acquire );
                     if ( pChild ) {
-                        version_type nChildVersion = pChild->version( memory_model::memory_order_relaxed );
+                        version_type nChildVersion = pChild->version( memory_model::memory_order_acquire );
                         if ( nChildVersion & node_type::shrinking ) {
                             m_stat.onRemoveRootWaitShrinking();
                             pChild->template wait_until_shrink_completed<back_off>( memory_model::memory_order_relaxed );
@@ -896,11 +904,25 @@ namespace cds { namespace container {
             );
             return pExtracted;
         }
-
         //@endcond
 
     private:
         //@cond
+        static int height( node_type * pNode, atomics::memory_order order = memory_model::memory_order_relaxed )
+        {
+            assert( pNode );
+            return pNode->m_nHeight.load( order );
+        }
+        static void set_height( node_type * pNode, int h, atomics::memory_order order = memory_model::memory_order_relaxed )
+        {
+            assert( pNode );
+            pNode->m_nHeight.store( h, order );
+        }
+        static int height_null( node_type * pNode, atomics::memory_order order = memory_model::memory_order_relaxed )
+        {
+            return pNode ? height( pNode, order ) : 0;
+        }
+
         template <typename Q, typename Compare, typename Func>
         find_result try_find( Q const& key, Compare cmp, Func f, node_type * pNode, int nDir, version_type nVersion ) const
         {
@@ -908,7 +930,7 @@ namespace cds { namespace container {
             assert( pNode );
 
             while ( true ) {
-                node_type * pChild = child( pNode, nDir, memory_model::memory_order_relaxed );
+                node_type * pChild = child( pNode, nDir );
                 if ( !pChild ) {
                     if ( pNode->version( memory_model::memory_order_acquire ) != nVersion ) {
                         m_stat.onFindRetry();
@@ -947,7 +969,6 @@ namespace cds { namespace container {
                     }
                 }
                 else if ( nChildVersion != node_type::unlinked ) {
-
                     if ( pNode->version( memory_model::memory_order_acquire ) != nVersion ) {
                         m_stat.onFindRetry();
                         return find_result::retry;
@@ -957,6 +978,11 @@ namespace cds { namespace container {
                     if ( found != find_result::retry )
                         return found;
                 }
+
+                if ( pNode->version( memory_model::memory_order_acquire ) != nVersion ) {
+                    m_stat.onFindRetry();
+                    return find_result::retry;
+                }
             }
         }
 
@@ -970,7 +996,7 @@ namespace cds { namespace container {
                 // get right child of root
                 node_type * pChild = child( m_pRoot, right_child, memory_model::memory_order_acquire );
                 if ( pChild ) {
-                    version_type nChildVersion = pChild->version( memory_model::memory_order_relaxed );
+                    version_type nChildVersion = pChild->version( memory_model::memory_order_acquire );
                     if ( nChildVersion & node_type::shrinking ) {
                         m_stat.onUpdateRootWaitShrinking();
                         pChild->template wait_until_shrink_completed<back_off>( memory_model::memory_order_relaxed );
@@ -999,7 +1025,7 @@ namespace cds { namespace container {
                             pNew->m_pValue.store( pVal, memory_model::memory_order_release );
 
                             m_pRoot->child( pNew, right_child, memory_model::memory_order_relaxed );
-                            m_pRoot->height( 2, memory_model::memory_order_relaxed );
+                            set_height( m_pRoot, 2 );
                         }
 
                         ++m_ItemCounter;
@@ -1023,7 +1049,7 @@ namespace cds { namespace container {
                 // get right child of root
                 node_type * pChild = child( m_pRoot, right_child, memory_model::memory_order_acquire );
                 if ( pChild ) {
-                    version_type nChildVersion = pChild->version( memory_model::memory_order_relaxed );
+                    version_type nChildVersion = pChild->version( memory_model::memory_order_acquire );
                     if ( nChildVersion & node_type::shrinking ) {
                         m_stat.onRemoveRootWaitShrinking();
                         pChild->template wait_until_shrink_completed<back_off>( memory_model::memory_order_relaxed );
@@ -1059,7 +1085,7 @@ namespace cds { namespace container {
 
             int result;
             do {
-                node_type * pChild = child( pNode, nCmp, memory_model::memory_order_relaxed );
+                node_type * pChild = child( pNode, nCmp );
                 if ( pNode->version(memory_model::memory_order_acquire) != nVersion ) {
                     m_stat.onUpdateRetry();
                     return update_flags::retry;
@@ -1081,11 +1107,11 @@ namespace cds { namespace container {
                         pChild->template wait_until_shrink_completed<back_off>( memory_model::memory_order_relaxed );
                         // retry
                     }
-                    else if ( pChild == child( pNode, nCmp, memory_model::memory_order_relaxed )) {
+                    else if ( pChild == child( pNode, nCmp )) {
                         // this second read is important, because it is protected by nChildVersion
 
                         // validate the read that our caller took to get to node
-                        if ( pNode->version( memory_model::memory_order_relaxed ) != nVersion ) {
+                        if ( pNode->version( memory_model::memory_order_acquire ) != nVersion ) {
                             m_stat.onUpdateRetry();
                             return update_flags::retry;
                         }
@@ -1098,6 +1124,11 @@ namespace cds { namespace container {
                         result = try_update( key, cmp, nFlags, funcUpdate, pNode, pChild, nChildVersion, disp );
                     }
                 }
+
+                if ( result == update_flags::retry && pNode->version( memory_model::memory_order_acquire ) != nVersion ) {
+                    m_stat.onUpdateRetry();
+                    return update_flags::retry;
+                }
             } while ( result == update_flags::retry );
             return result;
         }
@@ -1114,7 +1145,7 @@ namespace cds { namespace container {
 
             int result;
             do {
-                node_type * pChild = child( pNode, nCmp, memory_model::memory_order_relaxed );
+                node_type * pChild = child( pNode, nCmp );
                 if ( pNode->version(memory_model::memory_order_acquire) != nVersion ) {
                     m_stat.onRemoveRetry();
                     return update_flags::retry;
@@ -1132,11 +1163,11 @@ namespace cds { namespace container {
                         pChild->template wait_until_shrink_completed<back_off>( memory_model::memory_order_relaxed );
                         // retry
                     }
-                    else if ( pChild == child( pNode, nCmp, memory_model::memory_order_relaxed )) {
+                    else if ( pChild == child( pNode, nCmp )) {
                         // this second read is important, because it is protected by nChildVersion
 
                         // validate the read that our caller took to get to node
-                        if ( pNode->version( memory_model::memory_order_relaxed ) != nVersion ) {
+                        if ( pNode->version( memory_model::memory_order_acquire ) != nVersion ) {
                             m_stat.onRemoveRetry();
                             return update_flags::retry;
                         }
@@ -1149,6 +1180,11 @@ namespace cds { namespace container {
                         result = try_remove( key, cmp, func, pNode, pChild, nChildVersion, disp );
                     }
                 }
+
+                if ( result == update_flags::retry && pNode->version( memory_model::memory_order_acquire ) != nVersion ) {
+                    m_stat.onRemoveRetry();
+                    return update_flags::retry;
+                }
             } while ( result == update_flags::retry );
             return result;
         }
@@ -1161,7 +1197,7 @@ namespace cds { namespace container {
 
             int result;
             do {
-                node_type * pChild = child( pNode, nDir, memory_model::memory_order_relaxed );
+                node_type * pChild = child( pNode, nDir );
                 if ( pNode->version(memory_model::memory_order_acquire) != nVersion ) {
                     m_stat.onRemoveRetry();
                     return update_flags::retry;
@@ -1179,11 +1215,11 @@ namespace cds { namespace container {
                         pChild->template wait_until_shrink_completed<back_off>( memory_model::memory_order_relaxed );
                         // retry
                     }
-                    else if ( pChild == child( pNode, nDir, memory_model::memory_order_relaxed )) {
+                    else if ( pChild == child( pNode, nDir )) {
                         // this second read is important, because it is protected by nChildVersion
 
                         // validate the read that our caller took to get to node
-                        if ( pNode->version( memory_model::memory_order_relaxed ) != nVersion ) {
+                        if ( pNode->version( memory_model::memory_order_acquire ) != nVersion ) {
                             m_stat.onRemoveRetry();
                             return update_flags::retry;
                         }
@@ -1196,6 +1232,11 @@ namespace cds { namespace container {
                         result = try_extract_minmax( nDir, func, pNode, pChild, nChildVersion, disp );
                     }
                 }
+
+                if ( result == update_flags::retry && pNode->version( memory_model::memory_order_acquire ) != nVersion ) {
+                    m_stat.onRemoveRetry();
+                    return update_flags::retry;
+                }
             } while ( result == update_flags::retry );
             return result;
         }
@@ -1213,7 +1254,7 @@ namespace cds { namespace container {
 
             if ( c_bRelaxedInsert ) {
                 if ( pNode->version( memory_model::memory_order_acquire ) != nVersion
-                     || child( pNode, nDir, memory_model::memory_order_relaxed ) != nullptr ) 
+                     || child( pNode, nDir ) != nullptr ) 
                 {
                     m_stat.onInsertRetry();
                     return update_flags::retry;
@@ -1227,8 +1268,8 @@ namespace cds { namespace container {
                 assert( pNode != nullptr );
                 node_scoped_lock l( m_Monitor, *pNode );
 
-                if ( pNode->version( memory_model::memory_order_relaxed ) != nVersion
-                     || child( pNode, nDir, memory_model::memory_order_relaxed ) != nullptr ) 
+                if ( pNode->version( memory_model::memory_order_acquire ) != nVersion
+                     || child( pNode, nDir ) != nullptr ) 
                 {
                     if ( c_bRelaxedInsert ) {
                         mapped_type pVal = pNew->m_pValue.load( memory_model::memory_order_relaxed );
@@ -1301,20 +1342,18 @@ namespace cds { namespace container {
             if ( !pNode->is_valued( atomics::memory_order_relaxed ) )
                 return update_flags::failed;
 
-            if ( child( pNode, left_child, memory_model::memory_order_relaxed ) == nullptr 
-              || child( pNode, right_child, memory_model::memory_order_relaxed ) == nullptr )
-            { 
+            if ( child( pNode, left_child ) == nullptr || child( pNode, right_child ) == nullptr ) { 
                 node_type * pDamaged;
                 mapped_type pOld;
                 {
                     node_scoped_lock lp( m_Monitor, *pParent );
-                    if ( pParent->is_unlinked( atomics::memory_order_relaxed ) || parent( pNode, memory_model::memory_order_relaxed ) != pParent )
+                    if ( pParent->is_unlinked( atomics::memory_order_relaxed ) || parent( pNode ) != pParent )
                         return update_flags::retry;
 
                     {
                         node_scoped_lock ln( m_Monitor, *pNode );
                         pOld = pNode->value( memory_model::memory_order_relaxed );
-                        if ( !( pNode->version( memory_model::memory_order_relaxed ) == nVersion
+                        if ( !( pNode->version( memory_model::memory_order_acquire ) == nVersion
                           && pOld 
                           && try_unlink_locked( pParent, pNode, disp )))
                         {
@@ -1342,7 +1381,7 @@ namespace cds { namespace container {
                 {
                     node_scoped_lock ln( m_Monitor, *pNode );
                     pOld = pNode->value( atomics::memory_order_relaxed );
-                    if ( pNode->version( atomics::memory_order_relaxed ) == nVersion && pOld ) {
+                    if ( pNode->version( atomics::memory_order_acquire ) == nVersion && pOld ) {
                         pNode->m_pValue.store( nullptr, atomics::memory_order_relaxed );
                         result = update_flags::result_removed;
                     }
@@ -1365,18 +1404,18 @@ namespace cds { namespace container {
             // pParent and pNode must be locked
             assert( !pParent->is_unlinked(memory_model::memory_order_relaxed) );
 
-            node_type * pParentLeft = child( pParent, left_child, memory_model::memory_order_relaxed );
-            node_type * pParentRight = child( pParent, right_child, memory_model::memory_order_relaxed );
+            node_type * pParentLeft = child( pParent, left_child );
+            node_type * pParentRight = child( pParent, right_child );
             if ( pNode != pParentLeft && pNode != pParentRight ) {
                 // node is no longer a child of parent
                 return false;
             }
 
             assert( !pNode->is_unlinked( memory_model::memory_order_relaxed ) );
-            assert( pParent == parent( pNode, memory_model::memory_order_relaxed));
+            assert( pParent == parent( pNode ));
 
-            node_type * pLeft = child( pNode, left_child, memory_model::memory_order_relaxed );
-            node_type * pRight = child( pNode, right_child, memory_model::memory_order_relaxed );
+            node_type * pLeft = child( pNode, left_child );
+            node_type * pRight = child( pNode, right_child );
             if ( pLeft != nullptr && pRight != nullptr ) {
                 // splicing is no longer possible
                 return false;
@@ -1409,15 +1448,15 @@ namespace cds { namespace container {
         //@cond
         int estimate_node_condition( node_type * pNode )
         {
-            node_type * pLeft = child( pNode, left_child, memory_model::memory_order_relaxed );
-            node_type * pRight = child( pNode, right_child, memory_model::memory_order_relaxed );
+            node_type * pLeft = child( pNode, left_child );
+            node_type * pRight = child( pNode, right_child );
 
             if ( (pLeft == nullptr || pRight == nullptr) && !pNode->is_valued( memory_model::memory_order_relaxed ))
                 return unlink_required;
 
-            int h = pNode->height( memory_model::memory_order_relaxed );
-            int hL = pLeft ? pLeft->height( memory_model::memory_order_relaxed ) : 0;
-            int hR = pRight ? pRight->height( memory_model::memory_order_relaxed ) : 0;
+            int h = height( pNode );
+            int hL = height_null( pLeft );
+            int hR = height_null( pRight );
 
             int hNew = 1 + std::max( hL, hR );
             int nBalance = hL - hR;
@@ -1446,14 +1485,14 @@ namespace cds { namespace container {
                 case nothing_required:
                     return nullptr;
                 default:
-                    pNode->height( h, memory_model::memory_order_relaxed );
-                    return parent( pNode, memory_model::memory_order_relaxed );
+                    set_height( pNode, h );
+                    return parent( pNode );
             }
         }
 
         void fix_height_and_rebalance( node_type * pNode, rcu_disposer& disp )
         {
-            while ( pNode && parent( pNode, memory_model::memory_order_relaxed )) {
+            while ( pNode && parent( pNode )) {
                 int nCond = estimate_node_condition( pNode );
                 if ( nCond == nothing_required || pNode->is_unlinked( memory_model::memory_order_relaxed ) )
                     return;
@@ -1461,13 +1500,11 @@ namespace cds { namespace container {
                 if ( nCond != unlink_required && nCond != rebalance_required )
                     pNode = fix_height( pNode );
                 else {
-                    node_type * pParent = parent( pNode, memory_model::memory_order_relaxed );
+                    node_type * pParent = parent( pNode );
                     assert( pParent != nullptr );
                     {
                         node_scoped_lock lp( m_Monitor, *pParent );
-                        if ( !pParent->is_unlinked( memory_model::memory_order_relaxed )
-                             && parent( pNode, memory_model::memory_order_relaxed ) == pParent ) 
-                        {
+                        if ( !pParent->is_unlinked( memory_model::memory_order_relaxed ) && parent( pNode ) == pParent ) {
                             node_scoped_lock ln( m_Monitor, *pNode );
                             pNode = rebalance_locked( pParent, pNode, disp );
                         }
@@ -1480,10 +1517,10 @@ namespace cds { namespace container {
         {
             // pParent and pNode should be locked.
             // Returns a damaged node, or nullptr if no more rebalancing is necessary
-            assert( parent( pNode, memory_model::memory_order_relaxed ) == pParent );
+            assert( parent( pNode ) == pParent );
 
-            node_type * pLeft = child( pNode, left_child, memory_model::memory_order_relaxed );
-            node_type * pRight = child( pNode, right_child, memory_model::memory_order_relaxed );
+            node_type * pLeft = child( pNode, left_child );
+            node_type * pRight = child( pNode, right_child );
 
             if ( (pLeft == nullptr || pRight == nullptr) && !pNode->is_valued( memory_model::memory_order_relaxed )) {
                 if ( try_unlink_locked( pParent, pNode, disp ))
@@ -1494,12 +1531,11 @@ namespace cds { namespace container {
                 }
             }
 
-            assert( child( pParent, left_child,  memory_model::memory_order_relaxed ) == pNode
-                 || child( pParent, right_child, memory_model::memory_order_relaxed ) == pNode );
+            assert( child( pParent, left_child ) == pNode || child( pParent, right_child ) == pNode );
 
-            int h = pNode->height( memory_model::memory_order_relaxed );
-            int hL = pLeft ? pLeft->height( memory_model::memory_order_relaxed ) : 0;
-            int hR = pRight ? pRight->height( memory_model::memory_order_relaxed ) : 0;
+            int h = height( pNode );
+            int hL = height_null( pLeft );
+            int hR = height_null( pRight );
             int hNew = 1 + std::max( hL, hR );
             int balance = hL - hR;
 
@@ -1508,7 +1544,7 @@ namespace cds { namespace container {
             else if ( balance < -1 )
                 return rebalance_to_left_locked( pParent, pNode, pRight, hL );
             else if ( hNew != h ) {
-                pNode->height( hNew, memory_model::memory_order_relaxed );
+                set_height( pNode, hNew );
 
                 // pParent is already locked
                 return fix_height_locked( pParent );
@@ -1519,9 +1555,8 @@ namespace cds { namespace container {
 
         node_type * rebalance_to_right_locked( node_type * pParent, node_type * pNode, node_type * pLeft, int hR )
         {
-            assert( parent( pNode, memory_model::memory_order_relaxed ) == pParent );
-            assert( child( pParent, left_child,  memory_model::memory_order_relaxed ) == pNode
-                 || child( pParent, right_child, memory_model::memory_order_relaxed ) == pNode );
+            assert( parent( pNode ) == pParent );
+            assert( child( pParent, left_child ) == pNode || child( pParent, right_child ) == pNode );
 
             // pParent and pNode is locked yet
             // pNode->pLeft is too large, we will rotate-right.
@@ -1533,14 +1568,14 @@ namespace cds { namespace container {
                 if ( pNode->m_pLeft.load( memory_model::memory_order_relaxed ) != pLeft )
                     return pNode; // retry for pNode
 
-                int hL = pLeft->height( memory_model::memory_order_relaxed );
+                int hL = height( pLeft );
                 if ( hL - hR <= 1 )
                     return pNode; // retry
 
-                node_type * pLRight = child( pLeft, right_child, memory_model::memory_order_relaxed );
-                int hLR = pLRight ? pLRight->height( memory_model::memory_order_relaxed ) : 0;
-                node_type * pLLeft = child( pLeft, left_child, memory_model::memory_order_relaxed );
-                int hLL = pLLeft ? pLLeft->height( memory_model::memory_order_relaxed ) : 0;
+                node_type * pLRight = child( pLeft, right_child );
+                int hLR = height_null( pLRight );
+                node_type * pLLeft = child( pLeft, left_child );
+                int hLL = height_null( pLLeft );
 
                 if ( hLL > hLR ) {
                     // rotate right
@@ -1553,12 +1588,11 @@ namespace cds { namespace container {
                         if ( pLeft->m_pRight.load( memory_model::memory_order_relaxed ) != pLRight )
                             return pNode; // retry
 
-                        hLR = pLRight->height( memory_model::memory_order_relaxed );
+                        hLR = height( pLRight );
                         if ( hLL > hLR )
                             return rotate_right_locked( pParent, pNode, pLeft, hR, hLL, pLRight, hLR );
 
-                        node_type * pLRLeft = child( pLRight, left_child, memory_model::memory_order_relaxed );
-                        int hLRL = pLRLeft ? pLRLeft->height( memory_model::memory_order_relaxed  ) : 0;
+                        int hLRL = height_null( child( pLRight, left_child ));
                         int balance = hLL - hLRL;
                         if ( balance >= -1 && balance <= 1 && !((hLL == 0 || hLRL == 0) && !pLeft->is_valued(memory_model::memory_order_relaxed))) {
                             // nParent.child.left won't be damaged after a double rotation
@@ -1574,9 +1608,8 @@ namespace cds { namespace container {
 
         node_type * rebalance_to_left_locked( node_type * pParent, node_type * pNode, node_type * pRight, int hL )
         {
-            assert( parent( pNode, memory_model::memory_order_relaxed ) == pParent );
-            assert( child( pParent, left_child,  memory_model::memory_order_relaxed ) == pNode
-                 || child( pParent, right_child, memory_model::memory_order_relaxed ) == pNode );
+            assert( parent( pNode ) == pParent );
+            assert( child( pParent, left_child ) == pNode || child( pParent, right_child ) == pNode );
 
             // pParent and pNode is locked yet
             {
@@ -1585,14 +1618,14 @@ namespace cds { namespace container {
                 if ( pNode->m_pRight.load( memory_model::memory_order_relaxed ) != pRight )
                     return pNode; // retry for pNode
 
-                int hR = pRight->height( memory_model::memory_order_relaxed );
+                int hR = height( pRight );
                 if ( hL - hR >= -1 )
                     return pNode; // retry
 
-                node_type * pRLeft = child( pRight, left_child, memory_model::memory_order_relaxed );
-                int hRL = pRLeft ? pRLeft->height( memory_model::memory_order_relaxed ) : 0;
-                node_type * pRRight = child( pRight, right_child, memory_model::memory_order_relaxed );
-                int hRR = pRRight ? pRRight->height( memory_model::memory_order_relaxed ) : 0;
+                node_type * pRLeft = child( pRight, left_child );
+                int hRL = height_null( pRLeft );
+                node_type * pRRight = child( pRight, right_child );
+                int hRR = height_null( pRRight );
                 if ( hRR > hRL )
                     return rotate_left_locked( pParent, pNode, hL, pRight, pRLeft, hRL, hRR );
 
@@ -1602,12 +1635,12 @@ namespace cds { namespace container {
                     if ( pRight->m_pLeft.load( memory_model::memory_order_relaxed ) != pRLeft )
                         return pNode; // retry
 
-                    hRL = pRLeft->height( memory_model::memory_order_relaxed );
+                    hRL = height( pRLeft );
                     if ( hRR >= hRL )
                         return rotate_left_locked( pParent, pNode, hL, pRight, pRLeft, hRL, hRR );
 
-                    node_type * pRLRight = child( pRLeft, right_child, memory_model::memory_order_relaxed );
-                    int hRLR = pRLRight ? pRLRight->height( memory_model::memory_order_relaxed ) : 0;
+                    node_type * pRLRight = child( pRLeft, right_child );
+                    int hRLR = height_null( pRLRight );
                     int balance = hRR - hRLR;
                     if ( balance >= -1 && balance <= 1 && !((hRR == 0 || hRLR == 0) && !pRight->is_valued( memory_model::memory_order_relaxed )))
                          return rotate_left_over_right_locked( pParent, pNode, hL, pRight, pRLeft, hRR, hRLR );
@@ -1618,6 +1651,8 @@ namespace cds { namespace container {
 
         static void begin_change( node_type * pNode, version_type version )
         {
+            assert(pNode->version(memory_model::memory_order_acquire) == version );
+            assert( (version & node_type::shrinking) == 0 );
             pNode->version( version | node_type::shrinking, memory_model::memory_order_release );
         }
         static void end_change( node_type * pNode, version_type version )
@@ -1628,8 +1663,8 @@ namespace cds { namespace container {
 
         node_type * rotate_right_locked( node_type * pParent, node_type * pNode, node_type * pLeft, int hR, int hLL, node_type * pLRight, int hLR )
         {
-            version_type nodeVersion = pNode->version( memory_model::memory_order_relaxed );
-            node_type * pParentLeft = child( pParent, left_child, memory_model::memory_order_relaxed );
+            version_type nodeVersion = pNode->version( memory_model::memory_order_acquire );
+            node_type * pParentLeft = child( pParent, left_child );
 
             begin_change( pNode, nodeVersion );
 
@@ -1650,8 +1685,8 @@ namespace cds { namespace container {
 
             // fix up heights links
             int hNode = 1 + std::max( hLR, hR );
-            pNode->height( hNode, memory_model::memory_order_relaxed );
-            pLeft->height( 1 + std::max( hLL, hNode ), memory_model::memory_order_relaxed );
+            set_height( pNode, hNode );
+            set_height( pLeft, 1 + std::max( hLL, hNode ));
 
             end_change( pNode, nodeVersion );
             m_stat.onRotateRight();
@@ -1691,8 +1726,8 @@ namespace cds { namespace container {
 
         node_type * rotate_left_locked( node_type * pParent, node_type * pNode, int hL, node_type * pRight, node_type * pRLeft, int hRL, int hRR )
         {
-            version_type nodeVersion = pNode->version( memory_model::memory_order_relaxed );
-            node_type * pParentLeft = child( pParent, left_child, memory_model::memory_order_relaxed );
+            version_type nodeVersion = pNode->version( memory_model::memory_order_acquire );
+            node_type * pParentLeft = child( pParent, left_child );
 
             begin_change( pNode, nodeVersion );
 
@@ -1714,8 +1749,8 @@ namespace cds { namespace container {
 
             // fix up heights
             int hNode = 1 + std::max( hL, hRL );
-            pNode->height( hNode, memory_model::memory_order_relaxed );
-            pRight->height( 1 + std::max( hNode, hRR ), memory_model::memory_order_relaxed );
+            set_height( pNode, hNode );
+            set_height( pRight, 1 + std::max( hNode, hRR ));
 
             end_change( pNode, nodeVersion );
             m_stat.onRotateLeft();
@@ -1739,13 +1774,13 @@ namespace cds { namespace container {
 
         node_type * rotate_right_over_left_locked( node_type * pParent, node_type * pNode, node_type * pLeft, int hR, int hLL, node_type * pLRight, int hLRL )
         {
-            version_type nodeVersion = pNode->version( memory_model::memory_order_relaxed );
-            version_type leftVersion = pLeft->version( memory_model::memory_order_relaxed );
+            version_type nodeVersion = pNode->version( memory_model::memory_order_acquire );
+            version_type leftVersion = pLeft->version( memory_model::memory_order_acquire );
 
-            node_type * pPL = child( pParent, left_child, memory_model::memory_order_relaxed );
-            node_type * pLRL = child( pLRight, left_child, memory_model::memory_order_relaxed );
-            node_type * pLRR = child( pLRight, right_child, memory_model::memory_order_relaxed );
-            int hLRR = pLRR ? pLRR->height( memory_model::memory_order_relaxed ) : 0;
+            node_type * pPL = child( pParent, left_child );
+            node_type * pLRL = child( pLRight, left_child );
+            node_type * pLRR = child( pLRight, right_child );
+            int hLRR = height_null( pLRR );
 
             begin_change( pNode, nodeVersion );
             begin_change( pLeft, leftVersion );
@@ -1767,17 +1802,17 @@ namespace cds { namespace container {
             if ( pPL == pNode )
                 pParent->m_pLeft.store( pLRight, memory_model::memory_order_relaxed );
             else {
-                assert( child( pParent, right_child, memory_model::memory_order_relaxed ) == pNode );
+                assert( child( pParent, right_child ) == pNode );
                 pParent->m_pRight.store( pLRight, memory_model::memory_order_relaxed );
             }
             pLRight->m_pParent.store( pParent, memory_model::memory_order_relaxed );
 
             // fix up heights
             int hNode = 1 + std::max( hLRR, hR );
-            pNode->height( hNode, memory_model::memory_order_relaxed );
+            set_height( pNode, hNode );
             int hLeft = 1 + std::max( hLL, hLRL );
-            pLeft->height( hLeft, memory_model::memory_order_relaxed );
-            pLRight->height( 1 + std::max( hLeft, hNode ), memory_model::memory_order_relaxed );
+            set_height( pLeft, hLeft );
+            set_height( pLRight, 1 + std::max( hLeft, hNode ));
 
             end_change( pNode, nodeVersion );
             end_change( pLeft, leftVersion );
@@ -1818,13 +1853,13 @@ namespace cds { namespace container {
 
         node_type * rotate_left_over_right_locked( node_type * pParent, node_type * pNode, int hL, node_type * pRight, node_type * pRLeft, int hRR, int hRLR )
         {
-            version_type nodeVersion = pNode->version( memory_model::memory_order_relaxed );
-            version_type rightVersion = pRight->version( memory_model::memory_order_relaxed );
+            version_type nodeVersion = pNode->version( memory_model::memory_order_acquire );
+            version_type rightVersion = pRight->version( memory_model::memory_order_acquire );
 
-            node_type * pPL = child( pParent, left_child, memory_model::memory_order_relaxed );
-            node_type * pRLL = child( pRLeft, left_child, memory_model::memory_order_relaxed );
-            node_type * pRLR = child( pRLeft, right_child, memory_model::memory_order_relaxed );
-            int hRLL = pRLL ? pRLL->height( memory_model::memory_order_relaxed ) : 0;
+            node_type * pPL = child( pParent, left_child );
+            node_type * pRLL = child( pRLeft, left_child );
+            node_type * pRLR = child( pRLeft, right_child );
+            int hRLL = height_null( pRLL );
 
             begin_change( pNode, nodeVersion );
             begin_change( pRight, rightVersion );
@@ -1853,10 +1888,10 @@ namespace cds { namespace container {
 
             // fix up heights
             int hNode = 1 + std::max( hL, hRLL );
-            pNode->height( hNode, memory_model::memory_order_relaxed );
+            set_height( pNode, hNode );
             int hRight = 1 + std::max( hRLR, hRR );
-            pRight->height( hRight, memory_model::memory_order_relaxed );
-            pRLeft->height( 1 + std::max( hNode, hRight ), memory_model::memory_order_relaxed );
+            set_height( pRight, hRight );
+            set_height( pRLeft, 1 + std::max( hNode, hRight ));
 
             end_change( pNode, nodeVersion );
             end_change( pRight, rightVersion );
index 8474f43aeb4d7e6c6d4179c35c2933c1b1e4d974..ec9b34a1f3acfcb6081b52b32738a842fcb35258 100644 (file)
   </ItemGroup>\r
   <ItemGroup>\r
     <ClCompile Include="..\..\..\tests\unit\map2\map_delodd.cpp" />\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_delodd_bronsonavltree.cpp" />\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_delodd_cuckoo.cpp" />\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_delodd_ellentree.cpp" />\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_delodd_michael.cpp" />\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_delodd_skip.cpp" />\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_delodd_split.cpp" />\r
+  </ItemGroup>\r
+  <ItemGroup>\r
+    <ClInclude Include="..\..\..\tests\unit\map2\map_delodd.h" />\r
   </ItemGroup>\r
   <PropertyGroup Label="Globals">\r
     <ProjectGuid>{3C598F96-FB84-4d42-9B43-F697F53B0221}</ProjectGuid>\r
index be592dd66dce7c26ec775ebc3848f960bd801a75..4559070db1a1fc303e87955c120d713a1c71b737 100644 (file)
   </ItemGroup>\r
   <ItemGroup>\r
     <ClCompile Include="..\..\..\tests\unit\map2\map_find_int.cpp" />\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_find_int_bronsonavltree.cpp" />\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_find_int_cuckoo.cpp" />\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_find_int_ellentree.cpp" />\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_find_int_michael.cpp" />\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_find_int_refinable.cpp" />\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_find_int_skip.cpp" />\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_find_int_split.cpp" />\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_find_int_std.cpp" />\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_find_int_striped.cpp" />\r
     <ClCompile Include="..\..\..\tests\unit\map2\map_find_string.cpp" />\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_find_string_bronsonavltree.cpp" />\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_find_string_cuckoo.cpp" />\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_find_string_ellentree.cpp" />\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_find_string_michael.cpp" />\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_find_string_refinable.cpp" />\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_find_string_skip.cpp" />\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_find_string_split.cpp" />\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_find_string_std.cpp" />\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_find_string_striped.cpp" />\r
     <ClCompile Include="..\..\..\tests\unit\map2\map_insfind_int.cpp" />\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_insfind_int_bronsonavltree.cpp" />\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_insfind_int_cuckoo.cpp" />\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_insfind_int_ellentree.cpp" />\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_insfind_int_michael.cpp" />\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_insfind_int_refinable.cpp" />\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_insfind_int_skip.cpp" />\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_insfind_int_split.cpp" />\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_insfind_int_std.cpp" />\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_insfind_int_striped.cpp" />\r
+  </ItemGroup>\r
+  <ItemGroup>\r
+    <ClInclude Include="..\..\..\tests\unit\map2\map_find_int.h" />\r
+    <ClInclude Include="..\..\..\tests\unit\map2\map_find_string.h" />\r
+    <ClInclude Include="..\..\..\tests\unit\map2\map_insfind_int.h" />\r
   </ItemGroup>\r
   <PropertyGroup Label="Globals">\r
     <ProjectGuid>{BA2A9239-0299-4069-BB0E-16DACE87ADE0}</ProjectGuid>\r
diff --git a/projects/Win/vc12/unit-map-find.vcxproj.filters b/projects/Win/vc12/unit-map-find.vcxproj.filters
new file mode 100644 (file)
index 0000000..7bdd4a8
--- /dev/null
@@ -0,0 +1,117 @@
+<?xml version="1.0" encoding="utf-8"?>\r
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">\r
+  <ItemGroup>\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_find_int.cpp">\r
+      <Filter>map_find_int</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_find_int_bronsonavltree.cpp">\r
+      <Filter>map_find_int</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_find_int_cuckoo.cpp">\r
+      <Filter>map_find_int</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_find_int_ellentree.cpp">\r
+      <Filter>map_find_int</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_find_int_michael.cpp">\r
+      <Filter>map_find_int</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_find_int_refinable.cpp">\r
+      <Filter>map_find_int</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_find_int_skip.cpp">\r
+      <Filter>map_find_int</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_find_int_split.cpp">\r
+      <Filter>map_find_int</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_find_int_std.cpp">\r
+      <Filter>map_find_int</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_find_int_striped.cpp">\r
+      <Filter>map_find_int</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_find_string.cpp">\r
+      <Filter>map_find_string</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_find_string_bronsonavltree.cpp">\r
+      <Filter>map_find_string</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_find_string_cuckoo.cpp">\r
+      <Filter>map_find_string</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_find_string_ellentree.cpp">\r
+      <Filter>map_find_string</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_find_string_michael.cpp">\r
+      <Filter>map_find_string</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_find_string_refinable.cpp">\r
+      <Filter>map_find_string</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_find_string_skip.cpp">\r
+      <Filter>map_find_string</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_find_string_split.cpp">\r
+      <Filter>map_find_string</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_find_string_std.cpp">\r
+      <Filter>map_find_string</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_find_string_striped.cpp">\r
+      <Filter>map_find_string</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_insfind_int.cpp">\r
+      <Filter>map_insfind_int</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_insfind_int_bronsonavltree.cpp">\r
+      <Filter>map_insfind_int</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_insfind_int_cuckoo.cpp">\r
+      <Filter>map_insfind_int</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_insfind_int_ellentree.cpp">\r
+      <Filter>map_insfind_int</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_insfind_int_michael.cpp">\r
+      <Filter>map_insfind_int</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_insfind_int_refinable.cpp">\r
+      <Filter>map_insfind_int</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_insfind_int_skip.cpp">\r
+      <Filter>map_insfind_int</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_insfind_int_split.cpp">\r
+      <Filter>map_insfind_int</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_insfind_int_std.cpp">\r
+      <Filter>map_insfind_int</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_insfind_int_striped.cpp">\r
+      <Filter>map_insfind_int</Filter>\r
+    </ClCompile>\r
+  </ItemGroup>\r
+  <ItemGroup>\r
+    <ClInclude Include="..\..\..\tests\unit\map2\map_find_int.h">\r
+      <Filter>map_find_int</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="..\..\..\tests\unit\map2\map_find_string.h">\r
+      <Filter>map_find_string</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="..\..\..\tests\unit\map2\map_insfind_int.h">\r
+      <Filter>map_insfind_int</Filter>\r
+    </ClInclude>\r
+  </ItemGroup>\r
+  <ItemGroup>\r
+    <Filter Include="map_find_int">\r
+      <UniqueIdentifier>{05793356-5544-4e12-893f-5761dea6536e}</UniqueIdentifier>\r
+    </Filter>\r
+    <Filter Include="map_find_string">\r
+      <UniqueIdentifier>{c6ad8146-72e2-473c-aa04-3db455858146}</UniqueIdentifier>\r
+    </Filter>\r
+    <Filter Include="map_insfind_int">\r
+      <UniqueIdentifier>{ba26fa2b-d618-4dd8-97d6-7dc874d9acf4}</UniqueIdentifier>\r
+    </Filter>\r
+  </ItemGroup>\r
+</Project>
\ No newline at end of file
index 9a504f1d3a77f0d9e6a77e811e942032db475fb1..72364e8a7e7a1abdea683748169c7fa822ac5c09 100644 (file)
   </ItemGroup>\r
   <ItemGroup>\r
     <ClCompile Include="..\..\..\tests\unit\map2\map_insdelfind.cpp" />\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_insdelfind_bronsonavltree.cpp" />\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_insdelfind_cuckoo.cpp" />\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_insdelfind_ellentree.cpp" />\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_insdelfind_michael.cpp" />\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_insdelfind_refinable.cpp" />\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_insdelfind_skip.cpp" />\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_insdelfind_split.cpp" />\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_insdelfind_std.cpp" />\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_insdelfind_striped.cpp" />\r
     <ClCompile Include="..\..\..\tests\unit\map2\map_insdel_func.cpp" />\r
-    <ClCompile Include="..\..\..\tests\unit\map2\map_insdel_func2.cpp" />\r
-    <ClCompile Include="..\..\..\tests\unit\map2\map_insdel_func3.cpp" />\r
-    <ClCompile Include="..\..\..\tests\unit\map2\map_insdel_func4.cpp" />\r
-    <ClCompile Include="..\..\..\tests\unit\map2\map_insdel_func5.cpp" />\r
-    <ClCompile Include="..\..\..\tests\unit\map2\map_insdel_func6.cpp" />\r
-    <ClCompile Include="..\..\..\tests\unit\map2\map_insdel_func7.cpp" />\r
-    <ClCompile Include="..\..\..\tests\unit\map2\map_insdel_func8.cpp" />\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_insdel_func_bronsonavltree.cpp" />\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_insdel_func_cuckoo.cpp" />\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_insdel_func_ellentree.cpp" />\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_insdel_func_michael.cpp" />\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_insdel_func_refinable.cpp" />\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_insdel_func_skip.cpp" />\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_insdel_func_split.cpp" />\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_insdel_func_striped.cpp" />\r
     <ClCompile Include="..\..\..\tests\unit\map2\map_insdel_int.cpp" />\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_insdel_int_bronsonavltree.cpp" />\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_insdel_int_cuckoo.cpp" />\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_insdel_int_ellentree.cpp" />\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_insdel_int_michael.cpp" />\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_insdel_int_refinable.cpp" />\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_insdel_int_skip.cpp" />\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_insdel_int_split.cpp" />\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_insdel_int_striped.cpp" />\r
     <ClCompile Include="..\..\..\tests\unit\map2\map_insdel_item_int.cpp" />\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_insdel_item_int_bronsonavltree.cpp" />\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_insdel_item_int_cuckoo.cpp" />\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_insdel_item_int_ellentree.cpp" />\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_insdel_item_int_michael.cpp" />\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_insdel_item_int_refinable.cpp" />\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_insdel_item_int_skip.cpp" />\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_insdel_item_int_split.cpp" />\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_insdel_item_int_striped.cpp" />\r
     <ClCompile Include="..\..\..\tests\unit\map2\map_insdel_item_string.cpp" />\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_insdel_item_string_bronsonavltree.cpp" />\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_insdel_item_string_cuckoo.cpp" />\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_insdel_item_string_ellentree.cpp" />\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_insdel_item_string_michael.cpp" />\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_insdel_item_string_refinable.cpp" />\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_insdel_item_string_skip.cpp" />\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_insdel_item_string_split.cpp" />\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_insdel_item_string_striped.cpp" />\r
     <ClCompile Include="..\..\..\tests\unit\map2\map_insdel_string.cpp" />\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_insdel_string_bronsonavltree.cpp" />\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_insdel_string_cuckoo.cpp" />\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_insdel_string_ellentree.cpp" />\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_insdel_string_michael.cpp" />\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_insdel_string_refinable.cpp" />\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_insdel_string_skip.cpp" />\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_insdel_string_split.cpp" />\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_insdel_string_std.cpp" />\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_insdel_string_striped.cpp" />\r
   </ItemGroup>\r
   <ItemGroup>\r
+    <ClInclude Include="..\..\..\tests\unit\map2\map_insdelfind.h" />\r
     <ClInclude Include="..\..\..\tests\unit\map2\map_insdel_func.h" />\r
+    <ClInclude Include="..\..\..\tests\unit\map2\map_insdel_int.h" />\r
+    <ClInclude Include="..\..\..\tests\unit\map2\map_insdel_item_int.h" />\r
+    <ClInclude Include="..\..\..\tests\unit\map2\map_insdel_item_string.h" />\r
+    <ClInclude Include="..\..\..\tests\unit\map2\map_insdel_string.h" />\r
   </ItemGroup>\r
   <PropertyGroup Label="Globals">\r
     <ProjectGuid>{CA25BDBF-B354-4597-B6D2-220ABBB0D2F4}</ProjectGuid>\r
diff --git a/projects/Win/vc12/unit-map-insdel.vcxproj.filters b/projects/Win/vc12/unit-map-insdel.vcxproj.filters
new file mode 100644 (file)
index 0000000..dc73d3e
--- /dev/null
@@ -0,0 +1,213 @@
+<?xml version="1.0" encoding="utf-8"?>\r
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">\r
+  <ItemGroup>\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_insdel_func.cpp">\r
+      <Filter>map_insdel_func</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_insdel_func_bronsonavltree.cpp">\r
+      <Filter>map_insdel_func</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_insdel_func_cuckoo.cpp">\r
+      <Filter>map_insdel_func</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_insdel_func_ellentree.cpp">\r
+      <Filter>map_insdel_func</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_insdel_func_michael.cpp">\r
+      <Filter>map_insdel_func</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_insdel_func_refinable.cpp">\r
+      <Filter>map_insdel_func</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_insdel_func_skip.cpp">\r
+      <Filter>map_insdel_func</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_insdel_func_split.cpp">\r
+      <Filter>map_insdel_func</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_insdel_func_striped.cpp">\r
+      <Filter>map_insdel_func</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_insdel_int.cpp">\r
+      <Filter>map_insdel_int</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_insdel_int_bronsonavltree.cpp">\r
+      <Filter>map_insdel_int</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_insdel_int_cuckoo.cpp">\r
+      <Filter>map_insdel_int</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_insdel_int_ellentree.cpp">\r
+      <Filter>map_insdel_int</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_insdel_int_michael.cpp">\r
+      <Filter>map_insdel_int</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_insdel_int_refinable.cpp">\r
+      <Filter>map_insdel_int</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_insdel_int_skip.cpp">\r
+      <Filter>map_insdel_int</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_insdel_int_split.cpp">\r
+      <Filter>map_insdel_int</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_insdel_int_striped.cpp">\r
+      <Filter>map_insdel_int</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_insdel_item_int.cpp">\r
+      <Filter>map_insdel_item_int</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_insdel_item_string.cpp">\r
+      <Filter>map_insdel_item_string</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_insdel_string.cpp">\r
+      <Filter>map_insdel_string</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_insdel_string_bronsonavltree.cpp">\r
+      <Filter>map_insdel_string</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_insdel_string_cuckoo.cpp">\r
+      <Filter>map_insdel_string</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_insdel_string_ellentree.cpp">\r
+      <Filter>map_insdel_string</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_insdel_string_michael.cpp">\r
+      <Filter>map_insdel_string</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_insdel_string_refinable.cpp">\r
+      <Filter>map_insdel_string</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_insdel_string_skip.cpp">\r
+      <Filter>map_insdel_string</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_insdel_string_split.cpp">\r
+      <Filter>map_insdel_string</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_insdel_string_std.cpp">\r
+      <Filter>map_insdel_string</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_insdel_string_striped.cpp">\r
+      <Filter>map_insdel_string</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_insdelfind.cpp">\r
+      <Filter>map_insdelfind</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_insdelfind_bronsonavltree.cpp">\r
+      <Filter>map_insdelfind</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_insdelfind_cuckoo.cpp">\r
+      <Filter>map_insdelfind</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_insdelfind_ellentree.cpp">\r
+      <Filter>map_insdelfind</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_insdelfind_michael.cpp">\r
+      <Filter>map_insdelfind</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_insdelfind_refinable.cpp">\r
+      <Filter>map_insdelfind</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_insdelfind_skip.cpp">\r
+      <Filter>map_insdelfind</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_insdelfind_split.cpp">\r
+      <Filter>map_insdelfind</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_insdelfind_std.cpp">\r
+      <Filter>map_insdelfind</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_insdelfind_striped.cpp">\r
+      <Filter>map_insdelfind</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_insdel_item_int_bronsonavltree.cpp">\r
+      <Filter>map_insdel_item_int</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_insdel_item_int_cuckoo.cpp">\r
+      <Filter>map_insdel_item_int</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_insdel_item_int_ellentree.cpp">\r
+      <Filter>map_insdel_item_int</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_insdel_item_int_michael.cpp">\r
+      <Filter>map_insdel_item_int</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_insdel_item_int_refinable.cpp">\r
+      <Filter>map_insdel_item_int</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_insdel_item_int_skip.cpp">\r
+      <Filter>map_insdel_item_int</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_insdel_item_int_split.cpp">\r
+      <Filter>map_insdel_item_int</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_insdel_item_int_striped.cpp">\r
+      <Filter>map_insdel_item_int</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_insdel_item_string_bronsonavltree.cpp">\r
+      <Filter>map_insdel_item_string</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_insdel_item_string_cuckoo.cpp">\r
+      <Filter>map_insdel_item_string</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_insdel_item_string_ellentree.cpp">\r
+      <Filter>map_insdel_item_string</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_insdel_item_string_michael.cpp">\r
+      <Filter>map_insdel_item_string</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_insdel_item_string_refinable.cpp">\r
+      <Filter>map_insdel_item_string</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_insdel_item_string_skip.cpp">\r
+      <Filter>map_insdel_item_string</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_insdel_item_string_split.cpp">\r
+      <Filter>map_insdel_item_string</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="..\..\..\tests\unit\map2\map_insdel_item_string_striped.cpp">\r
+      <Filter>map_insdel_item_string</Filter>\r
+    </ClCompile>\r
+  </ItemGroup>\r
+  <ItemGroup>\r
+    <Filter Include="map_insdel_func">\r
+      <UniqueIdentifier>{7cb9e730-e4e0-4648-96f1-e1dbf119756e}</UniqueIdentifier>\r
+    </Filter>\r
+    <Filter Include="map_insdel_int">\r
+      <UniqueIdentifier>{55aed984-fed9-4007-9ad3-59bec69befe8}</UniqueIdentifier>\r
+    </Filter>\r
+    <Filter Include="map_insdel_item_int">\r
+      <UniqueIdentifier>{8e7ec24b-8a28-4503-8514-4593923e3451}</UniqueIdentifier>\r
+    </Filter>\r
+    <Filter Include="map_insdel_item_string">\r
+      <UniqueIdentifier>{e7eec6ab-d1a8-4b59-afe9-b98e1b133d73}</UniqueIdentifier>\r
+    </Filter>\r
+    <Filter Include="map_insdel_string">\r
+      <UniqueIdentifier>{f613f4ac-8b0f-4a85-81be-d243141b3ce3}</UniqueIdentifier>\r
+    </Filter>\r
+    <Filter Include="map_insdelfind">\r
+      <UniqueIdentifier>{9172b0cf-89b6-44eb-bddd-1c59d254bff8}</UniqueIdentifier>\r
+    </Filter>\r
+  </ItemGroup>\r
+  <ItemGroup>\r
+    <ClInclude Include="..\..\..\tests\unit\map2\map_insdel_func.h">\r
+      <Filter>map_insdel_func</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="..\..\..\tests\unit\map2\map_insdel_int.h">\r
+      <Filter>map_insdel_int</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="..\..\..\tests\unit\map2\map_insdel_string.h">\r
+      <Filter>map_insdel_string</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="..\..\..\tests\unit\map2\map_insdelfind.h">\r
+      <Filter>map_insdelfind</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="..\..\..\tests\unit\map2\map_insdel_item_int.h">\r
+      <Filter>map_insdel_item_int</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="..\..\..\tests\unit\map2\map_insdel_item_string.h">\r
+      <Filter>map_insdel_item_string</Filter>\r
+    </ClInclude>\r
+  </ItemGroup>\r
+</Project>
\ No newline at end of file
index 09ee4df87a088696f9beec5749ad9418e9eb2576..ada62c81fe30030f006cd660c53c55a0ad04e9aa 100644 (file)
   </ItemGroup>\r
   <ItemGroup>\r
     <ClCompile Include="..\..\..\tests\unit\set2\set_delodd.cpp" />\r
+    <ClCompile Include="..\..\..\tests\unit\set2\set_delodd_cuckoo.cpp" />\r
+    <ClCompile Include="..\..\..\tests\unit\set2\set_delodd_ellentree.cpp" />\r
+    <ClCompile Include="..\..\..\tests\unit\set2\set_delodd_michael.cpp" />\r
+    <ClCompile Include="..\..\..\tests\unit\set2\set_delodd_skip.cpp" />\r
+    <ClCompile Include="..\..\..\tests\unit\set2\set_delodd_split.cpp" />\r
+  </ItemGroup>\r
+  <ItemGroup>\r
+    <ClInclude Include="..\..\..\tests\unit\set2\set_delodd.h" />\r
   </ItemGroup>\r
   <PropertyGroup Label="Globals">\r
     <ProjectGuid>{AF7B2253-2E6D-4992-94D9-4B3699C54929}</ProjectGuid>\r
       <AdditionalOptions>/bigobj /Zc:inline %(AdditionalOptions)</AdditionalOptions>\r
       <Optimization>Disabled</Optimization>\r
       <AdditionalIncludeDirectories>$(SolutionDir)..\..\..;$(SolutionDir)..\..\..\tests\unit;$(SolutionDir)..\..\..\tests;$(BOOST_PATH);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;_WIN32_WINNT=0x0501;_SCL_SECURE=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+      <PreprocessorDefinitions>_SCL_SECURE_NO_WARNINGS;WIN32;_DEBUG;_CONSOLE;_WIN32_WINNT=0x0501;_SCL_SECURE=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
       <MinimalRebuild>true</MinimalRebuild>\r
       <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>\r
       <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>\r
       <AdditionalOptions>/bigobj %(AdditionalOptions)</AdditionalOptions>\r
       <Optimization>Disabled</Optimization>\r
       <AdditionalIncludeDirectories>$(SolutionDir)..\..\..;$(SolutionDir)..\..\..\tests\unit;$(SolutionDir)..\..\..\tests;$(BOOST_PATH);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;_WIN32_WINNT=0x0501;_SCL_SECURE=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+      <PreprocessorDefinitions>_SCL_SECURE_NO_WARNINGS;WIN32;_DEBUG;_CONSOLE;_WIN32_WINNT=0x0501;_SCL_SECURE=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
       <MinimalRebuild>true</MinimalRebuild>\r
       <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>\r
       <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>\r
       <AdditionalOptions>/bigobj /Zc:inline %(AdditionalOptions)</AdditionalOptions>\r
       <Optimization>Disabled</Optimization>\r
       <AdditionalIncludeDirectories>$(SolutionDir)..\..\..;$(SolutionDir)..\..\..\tests\unit;$(SolutionDir)..\..\..\tests;$(BOOST_PATH);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions>CDS_USE_VLD;WIN32;_DEBUG;_CONSOLE;_WIN32_WINNT=0x0501;_SCL_SECURE=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+      <PreprocessorDefinitions>_SCL_SECURE_NO_WARNINGS;CDS_USE_VLD;WIN32;_DEBUG;_CONSOLE;_WIN32_WINNT=0x0501;_SCL_SECURE=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
       <MinimalRebuild>true</MinimalRebuild>\r
       <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>\r
       <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>\r
       <AdditionalOptions>/bigobj /Zc:inline %(AdditionalOptions)</AdditionalOptions>\r
       <Optimization>Disabled</Optimization>\r
       <AdditionalIncludeDirectories>$(SolutionDir)..\..\..;$(SolutionDir)..\..\..\tests\unit;$(SolutionDir)..\..\..\tests;$(BOOST_PATH);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;_WIN32_WINNT=0x0501;_SCL_SECURE=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+      <PreprocessorDefinitions>_SCL_SECURE_NO_WARNINGS;WIN32;_DEBUG;_CONSOLE;_WIN32_WINNT=0x0501;_SCL_SECURE=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
       <MinimalRebuild>true</MinimalRebuild>\r
       <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>\r
       <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>\r
       <AdditionalOptions>/bigobj %(AdditionalOptions)</AdditionalOptions>\r
       <Optimization>Disabled</Optimization>\r
       <AdditionalIncludeDirectories>$(SolutionDir)..\..\..;$(SolutionDir)..\..\..\tests\unit;$(SolutionDir)..\..\..\tests;$(BOOST_PATH);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;_WIN32_WINNT=0x0501;_SCL_SECURE=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+      <PreprocessorDefinitions>_SCL_SECURE_NO_WARNINGS;WIN32;_DEBUG;_CONSOLE;_WIN32_WINNT=0x0501;_SCL_SECURE=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
       <MinimalRebuild>true</MinimalRebuild>\r
       <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>\r
       <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>\r
       <AdditionalOptions>/bigobj /Zc:inline %(AdditionalOptions)</AdditionalOptions>\r
       <Optimization>Disabled</Optimization>\r
       <AdditionalIncludeDirectories>$(SolutionDir)..\..\..;$(SolutionDir)..\..\..\tests\unit;$(SolutionDir)..\..\..\tests;$(BOOST_PATH);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions>CDS_USE_VLD;WIN32;_DEBUG;_CONSOLE;_WIN32_WINNT=0x0501;_SCL_SECURE=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+      <PreprocessorDefinitions>_SCL_SECURE_NO_WARNINGS;CDS_USE_VLD;WIN32;_DEBUG;_CONSOLE;_WIN32_WINNT=0x0501;_SCL_SECURE=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
       <MinimalRebuild>true</MinimalRebuild>\r
       <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>\r
       <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>\r
       <IntrinsicFunctions>true</IntrinsicFunctions>\r
       <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>\r
       <AdditionalIncludeDirectories>$(SolutionDir)..\..\..;$(SolutionDir)..\..\..\tests\unit;$(SolutionDir)..\..\..\tests;$(BOOST_PATH);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;_WIN32_WINNT=0x0501;_SCL_SECURE=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+      <PreprocessorDefinitions>_SCL_SECURE_NO_WARNINGS;WIN32;NDEBUG;_CONSOLE;_WIN32_WINNT=0x0501;_SCL_SECURE=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
       <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>\r
       <FunctionLevelLinking>true</FunctionLevelLinking>\r
       <PrecompiledHeader>\r
       <IntrinsicFunctions>true</IntrinsicFunctions>\r
       <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>\r
       <AdditionalIncludeDirectories>$(SolutionDir)..\..\..;$(SolutionDir)..\..\..\tests\unit;$(SolutionDir)..\..\..\tests;$(BOOST_PATH);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;_WIN32_WINNT=0x0501;_SCL_SECURE=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+      <PreprocessorDefinitions>_SCL_SECURE_NO_WARNINGS;WIN32;NDEBUG;_CONSOLE;_WIN32_WINNT=0x0501;_SCL_SECURE=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
       <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>\r
       <FunctionLevelLinking>true</FunctionLevelLinking>\r
       <PrecompiledHeader>\r
       <IntrinsicFunctions>true</IntrinsicFunctions>\r
       <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>\r
       <AdditionalIncludeDirectories>$(SolutionDir)..\..\..;$(SolutionDir)..\..\..\tests\unit;$(SolutionDir)..\..\..\tests;$(BOOST_PATH);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;_WIN32_WINNT=0x0501;_SCL_SECURE=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+      <PreprocessorDefinitions>_SCL_SECURE_NO_WARNINGS;WIN32;NDEBUG;_CONSOLE;_WIN32_WINNT=0x0501;_SCL_SECURE=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
       <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>\r
       <FunctionLevelLinking>true</FunctionLevelLinking>\r
       <PrecompiledHeader>\r
       <IntrinsicFunctions>true</IntrinsicFunctions>\r
       <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>\r
       <AdditionalIncludeDirectories>$(SolutionDir)..\..\..;$(SolutionDir)..\..\..\tests\unit;$(SolutionDir)..\..\..\tests;$(BOOST_PATH);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;_WIN32_WINNT=0x0501;_SCL_SECURE=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+      <PreprocessorDefinitions>_SCL_SECURE_NO_WARNINGS;WIN32;NDEBUG;_CONSOLE;_WIN32_WINNT=0x0501;_SCL_SECURE=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
       <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>\r
       <FunctionLevelLinking>true</FunctionLevelLinking>\r
       <PrecompiledHeader>\r
index 78c9695a9441363cbb2b0cf64578a6dfc649fc24..4efad4dd41f413e086d429e1ff3c36353790bf5f 100644 (file)
   </ItemGroup>\r
   <ItemGroup>\r
     <ClCompile Include="..\..\..\tests\unit\set2\set_insdelfind.cpp" />\r
+    <ClCompile Include="..\..\..\tests\unit\set2\set_insdelfind_cuckoo.cpp" />\r
+    <ClCompile Include="..\..\..\tests\unit\set2\set_insdelfind_ellentree.cpp" />\r
+    <ClCompile Include="..\..\..\tests\unit\set2\set_insdelfind_michael.cpp" />\r
+    <ClCompile Include="..\..\..\tests\unit\set2\set_insdelfind_refinable.cpp" />\r
+    <ClCompile Include="..\..\..\tests\unit\set2\set_insdelfind_skip.cpp" />\r
+    <ClCompile Include="..\..\..\tests\unit\set2\set_insdelfind_split.cpp" />\r
+    <ClCompile Include="..\..\..\tests\unit\set2\set_insdelfind_std.cpp" />\r
+    <ClCompile Include="..\..\..\tests\unit\set2\set_insdelfind_striped.cpp" />\r
     <ClCompile Include="..\..\..\tests\unit\set2\set_insdel_func.cpp" />\r
-    <ClCompile Include="..\..\..\tests\unit\set2\set_insdel_func2.cpp" />\r
-    <ClCompile Include="..\..\..\tests\unit\set2\set_insdel_func3.cpp" />\r
-    <ClCompile Include="..\..\..\tests\unit\set2\set_insdel_func4.cpp" />\r
-    <ClCompile Include="..\..\..\tests\unit\set2\set_insdel_func5.cpp" />\r
-    <ClCompile Include="..\..\..\tests\unit\set2\set_insdel_func6.cpp" />\r
-    <ClCompile Include="..\..\..\tests\unit\set2\set_insdel_func7.cpp" />\r
+    <ClCompile Include="..\..\..\tests\unit\set2\set_insdel_func_cuckoo.cpp" />\r
+    <ClCompile Include="..\..\..\tests\unit\set2\set_insdel_func_ellentree.cpp" />\r
+    <ClCompile Include="..\..\..\tests\unit\set2\set_insdel_func_refinable.cpp" />\r
+    <ClCompile Include="..\..\..\tests\unit\set2\set_insdel_func_skip.cpp" />\r
+    <ClCompile Include="..\..\..\tests\unit\set2\set_insdel_func_split.cpp" />\r
+    <ClCompile Include="..\..\..\tests\unit\set2\set_insdel_func_striped.cpp" />\r
     <ClCompile Include="..\..\..\tests\unit\set2\set_insdel_string.cpp" />\r
+    <ClCompile Include="..\..\..\tests\unit\set2\set_insdel_string_cuckoo.cpp" />\r
+    <ClCompile Include="..\..\..\tests\unit\set2\set_insdel_string_ellentree.cpp" />\r
+    <ClCompile Include="..\..\..\tests\unit\set2\set_insdel_string_michael.cpp" />\r
+    <ClCompile Include="..\..\..\tests\unit\set2\set_insdel_string_refinable.cpp" />\r
+    <ClCompile Include="..\..\..\tests\unit\set2\set_insdel_string_skip.cpp" />\r
+    <ClCompile Include="..\..\..\tests\unit\set2\set_insdel_string_split.cpp" />\r
+    <ClCompile Include="..\..\..\tests\unit\set2\set_insdel_string_std.cpp" />\r
+    <ClCompile Include="..\..\..\tests\unit\set2\set_insdel_string_striped.cpp" />\r
   </ItemGroup>\r
   <ItemGroup>\r
+    <ClInclude Include="..\..\..\tests\unit\set2\set_insdelfind.h" />\r
     <ClInclude Include="..\..\..\tests\unit\set2\set_insdel_func.h" />\r
+    <ClInclude Include="..\..\..\tests\unit\set2\set_insdel_string.h" />\r
   </ItemGroup>\r
   <PropertyGroup Label="Globals">\r
     <ProjectGuid>{BA23811C-D4CB-4836-B2F3-6791BD6FFCD1}</ProjectGuid>\r
       <AdditionalOptions>/bigobj /Zc:inline %(AdditionalOptions)</AdditionalOptions>\r
       <Optimization>Disabled</Optimization>\r
       <AdditionalIncludeDirectories>$(SolutionDir)..\..\..;$(SolutionDir)..\..\..\tests\unit;$(SolutionDir)..\..\..\tests;$(BOOST_PATH);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;_WIN32_WINNT=0x0501;_SCL_SECURE=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+      <PreprocessorDefinitions>_SCL_SECURE_NO_WARNINGS;WIN32;_DEBUG;_CONSOLE;_WIN32_WINNT=0x0501;_SCL_SECURE=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
       <MinimalRebuild>true</MinimalRebuild>\r
       <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>\r
       <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>\r
       <AdditionalOptions>/bigobj %(AdditionalOptions)</AdditionalOptions>\r
       <Optimization>Disabled</Optimization>\r
       <AdditionalIncludeDirectories>$(SolutionDir)..\..\..;$(SolutionDir)..\..\..\tests\unit;$(SolutionDir)..\..\..\tests;$(BOOST_PATH);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;_WIN32_WINNT=0x0501;_SCL_SECURE=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+      <PreprocessorDefinitions>_SCL_SECURE_NO_WARNINGS;WIN32;_DEBUG;_CONSOLE;_WIN32_WINNT=0x0501;_SCL_SECURE=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
       <MinimalRebuild>true</MinimalRebuild>\r
       <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>\r
       <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>\r
       <AdditionalOptions>/bigobj /Zc:inline %(AdditionalOptions)</AdditionalOptions>\r
       <Optimization>Disabled</Optimization>\r
       <AdditionalIncludeDirectories>$(SolutionDir)..\..\..;$(SolutionDir)..\..\..\tests\unit;$(SolutionDir)..\..\..\tests;$(BOOST_PATH);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions>CDS_USE_VLD;WIN32;_DEBUG;_CONSOLE;_WIN32_WINNT=0x0501;_SCL_SECURE=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+      <PreprocessorDefinitions>_SCL_SECURE_NO_WARNINGS;CDS_USE_VLD;WIN32;_DEBUG;_CONSOLE;_WIN32_WINNT=0x0501;_SCL_SECURE=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
       <MinimalRebuild>true</MinimalRebuild>\r
       <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>\r
       <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>\r
       <AdditionalOptions>/bigobj /Zc:inline %(AdditionalOptions)</AdditionalOptions>\r
       <Optimization>Disabled</Optimization>\r
       <AdditionalIncludeDirectories>$(SolutionDir)..\..\..;$(SolutionDir)..\..\..\tests\unit;$(SolutionDir)..\..\..\tests;$(BOOST_PATH);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;_WIN32_WINNT=0x0501;_SCL_SECURE=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+      <PreprocessorDefinitions>_SCL_SECURE_NO_WARNINGS;WIN32;_DEBUG;_CONSOLE;_WIN32_WINNT=0x0501;_SCL_SECURE=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
       <MinimalRebuild>true</MinimalRebuild>\r
       <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>\r
       <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>\r
       <AdditionalOptions>/bigobj %(AdditionalOptions)</AdditionalOptions>\r
       <Optimization>Disabled</Optimization>\r
       <AdditionalIncludeDirectories>$(SolutionDir)..\..\..;$(SolutionDir)..\..\..\tests\unit;$(SolutionDir)..\..\..\tests;$(BOOST_PATH);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;_WIN32_WINNT=0x0501;_SCL_SECURE=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+      <PreprocessorDefinitions>_SCL_SECURE_NO_WARNINGS;WIN32;_DEBUG;_CONSOLE;_WIN32_WINNT=0x0501;_SCL_SECURE=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
       <MinimalRebuild>true</MinimalRebuild>\r
       <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>\r
       <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>\r
       <AdditionalOptions>/bigobj /Zc:inline %(AdditionalOptions)</AdditionalOptions>\r
       <Optimization>Disabled</Optimization>\r
       <AdditionalIncludeDirectories>$(SolutionDir)..\..\..;$(SolutionDir)..\..\..\tests\unit;$(SolutionDir)..\..\..\tests;$(BOOST_PATH);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions>CDS_USE_VLD;WIN32;_DEBUG;_CONSOLE;_WIN32_WINNT=0x0501;_SCL_SECURE=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+      <PreprocessorDefinitions>_SCL_SECURE_NO_WARNINGS;CDS_USE_VLD;WIN32;_DEBUG;_CONSOLE;_WIN32_WINNT=0x0501;_SCL_SECURE=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
       <MinimalRebuild>true</MinimalRebuild>\r
       <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>\r
       <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>\r
       <IntrinsicFunctions>true</IntrinsicFunctions>\r
       <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>\r
       <AdditionalIncludeDirectories>$(SolutionDir)..\..\..;$(SolutionDir)..\..\..\tests\unit;$(SolutionDir)..\..\..\tests;$(BOOST_PATH);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;_WIN32_WINNT=0x0501;_SCL_SECURE=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+      <PreprocessorDefinitions>_SCL_SECURE_NO_WARNINGS;WIN32;NDEBUG;_CONSOLE;_WIN32_WINNT=0x0501;_SCL_SECURE=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
       <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>\r
       <FunctionLevelLinking>true</FunctionLevelLinking>\r
       <PrecompiledHeader>\r
       <IntrinsicFunctions>true</IntrinsicFunctions>\r
       <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>\r
       <AdditionalIncludeDirectories>$(SolutionDir)..\..\..;$(SolutionDir)..\..\..\tests\unit;$(SolutionDir)..\..\..\tests;$(BOOST_PATH);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;_WIN32_WINNT=0x0501;_SCL_SECURE=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+      <PreprocessorDefinitions>_SCL_SECURE_NO_WARNINGS;WIN32;NDEBUG;_CONSOLE;_WIN32_WINNT=0x0501;_SCL_SECURE=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
       <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>\r
       <FunctionLevelLinking>true</FunctionLevelLinking>\r
       <PrecompiledHeader>\r
       <IntrinsicFunctions>true</IntrinsicFunctions>\r
       <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>\r
       <AdditionalIncludeDirectories>$(SolutionDir)..\..\..;$(SolutionDir)..\..\..\tests\unit;$(SolutionDir)..\..\..\tests;$(BOOST_PATH);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;_WIN32_WINNT=0x0501;_SCL_SECURE=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+      <PreprocessorDefinitions>_SCL_SECURE_NO_WARNINGS;WIN32;NDEBUG;_CONSOLE;_WIN32_WINNT=0x0501;_SCL_SECURE=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
       <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>\r
       <FunctionLevelLinking>true</FunctionLevelLinking>\r
       <PrecompiledHeader>\r
       <IntrinsicFunctions>true</IntrinsicFunctions>\r
       <FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>\r
       <AdditionalIncludeDirectories>$(SolutionDir)..\..\..;$(SolutionDir)..\..\..\tests\unit;$(SolutionDir)..\..\..\tests;$(BOOST_PATH);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;_WIN32_WINNT=0x0501;_SCL_SECURE=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+      <PreprocessorDefinitions>_SCL_SECURE_NO_WARNINGS;WIN32;NDEBUG;_CONSOLE;_WIN32_WINNT=0x0501;_SCL_SECURE=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
       <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>\r
       <FunctionLevelLinking>true</FunctionLevelLinking>\r
       <PrecompiledHeader>\r
diff --git a/projects/Win/vc12/unit-set-insdel.vcxproj.filters b/projects/Win/vc12/unit-set-insdel.vcxproj.filters
new file mode 100644 (file)
index 0000000..ff6fd74
--- /dev/null
@@ -0,0 +1,102 @@
+<?xml version="1.0" encoding="utf-8"?>\r
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">\r
+  <ItemGroup>\r
+    <ClCompile Include="..\..\..\tests\unit\set2\set_insdel_func.cpp">\r
+      <Filter>set_insdel_func</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="..\..\..\tests\unit\set2\set_insdel_func_cuckoo.cpp">\r
+      <Filter>set_insdel_func</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="..\..\..\tests\unit\set2\set_insdel_func_ellentree.cpp">\r
+      <Filter>set_insdel_func</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="..\..\..\tests\unit\set2\set_insdel_func_refinable.cpp">\r
+      <Filter>set_insdel_func</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="..\..\..\tests\unit\set2\set_insdel_func_skip.cpp">\r
+      <Filter>set_insdel_func</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="..\..\..\tests\unit\set2\set_insdel_func_split.cpp">\r
+      <Filter>set_insdel_func</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="..\..\..\tests\unit\set2\set_insdel_func_striped.cpp">\r
+      <Filter>set_insdel_func</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="..\..\..\tests\unit\set2\set_insdel_string.cpp">\r
+      <Filter>set_insdel_string</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="..\..\..\tests\unit\set2\set_insdelfind.cpp">\r
+      <Filter>set_insdelfind</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="..\..\..\tests\unit\set2\set_insdel_string_cuckoo.cpp">\r
+      <Filter>set_insdel_string</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="..\..\..\tests\unit\set2\set_insdel_string_ellentree.cpp">\r
+      <Filter>set_insdel_string</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="..\..\..\tests\unit\set2\set_insdel_string_michael.cpp">\r
+      <Filter>set_insdel_string</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="..\..\..\tests\unit\set2\set_insdel_string_refinable.cpp">\r
+      <Filter>set_insdel_string</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="..\..\..\tests\unit\set2\set_insdel_string_skip.cpp">\r
+      <Filter>set_insdel_string</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="..\..\..\tests\unit\set2\set_insdel_string_split.cpp">\r
+      <Filter>set_insdel_string</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="..\..\..\tests\unit\set2\set_insdel_string_std.cpp">\r
+      <Filter>set_insdel_string</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="..\..\..\tests\unit\set2\set_insdel_string_striped.cpp">\r
+      <Filter>set_insdel_string</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="..\..\..\tests\unit\set2\set_insdelfind_cuckoo.cpp">\r
+      <Filter>set_insdelfind</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="..\..\..\tests\unit\set2\set_insdelfind_ellentree.cpp">\r
+      <Filter>set_insdelfind</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="..\..\..\tests\unit\set2\set_insdelfind_michael.cpp">\r
+      <Filter>set_insdelfind</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="..\..\..\tests\unit\set2\set_insdelfind_refinable.cpp">\r
+      <Filter>set_insdelfind</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="..\..\..\tests\unit\set2\set_insdelfind_skip.cpp">\r
+      <Filter>set_insdelfind</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="..\..\..\tests\unit\set2\set_insdelfind_split.cpp">\r
+      <Filter>set_insdelfind</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="..\..\..\tests\unit\set2\set_insdelfind_std.cpp">\r
+      <Filter>set_insdelfind</Filter>\r
+    </ClCompile>\r
+    <ClCompile Include="..\..\..\tests\unit\set2\set_insdelfind_striped.cpp">\r
+      <Filter>set_insdelfind</Filter>\r
+    </ClCompile>\r
+  </ItemGroup>\r
+  <ItemGroup>\r
+    <Filter Include="set_insdel_func">\r
+      <UniqueIdentifier>{cbe5ede5-77ea-49bb-be6a-16d30d8416f7}</UniqueIdentifier>\r
+    </Filter>\r
+    <Filter Include="set_insdelfind">\r
+      <UniqueIdentifier>{e6a29b71-1355-4731-b5c5-6f277869f951}</UniqueIdentifier>\r
+    </Filter>\r
+    <Filter Include="set_insdel_string">\r
+      <UniqueIdentifier>{8a51ae1e-c41c-4394-bf84-3de8c45ea8bb}</UniqueIdentifier>\r
+    </Filter>\r
+  </ItemGroup>\r
+  <ItemGroup>\r
+    <ClInclude Include="..\..\..\tests\unit\set2\set_insdel_func.h">\r
+      <Filter>set_insdel_func</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="..\..\..\tests\unit\set2\set_insdel_string.h">\r
+      <Filter>set_insdel_string</Filter>\r
+    </ClInclude>\r
+    <ClInclude Include="..\..\..\tests\unit\set2\set_insdelfind.h">\r
+      <Filter>set_insdelfind</Filter>\r
+    </ClInclude>\r
+  </ItemGroup>\r
+</Project>
\ No newline at end of file
index f66e4a4056b31a3f7bd9b74ddbffeabe9237cfa9..abbe9446f24c9f5d5a901c6dfca8850bc20a6c0f 100644 (file)
@@ -1,19 +1,95 @@
 
 CDSUNIT_MAP_SOURCES := \
     tests/unit/map2/map_find_int.cpp \
+    tests/unit/map2/map_find_int_bronsonavltree.cpp \
+    tests/unit/map2/map_find_int_cuckoo.cpp \
+    tests/unit/map2/map_find_int_ellentree.cpp \
+    tests/unit/map2/map_find_int_michael.cpp \
+    tests/unit/map2/map_find_int_skip.cpp \
+    tests/unit/map2/map_find_int_split.cpp \
+    tests/unit/map2/map_find_int_striped.cpp \
+    tests/unit/map2/map_find_int_refinable.cpp \
+    tests/unit/map2/map_find_int_std.cpp \
     tests/unit/map2/map_find_string.cpp \
+    tests/unit/map2/map_find_string_bronsonavltree.cpp \
+    tests/unit/map2/map_find_string_cuckoo.cpp \
+    tests/unit/map2/map_find_string_ellentree.cpp \
+    tests/unit/map2/map_find_string_michael.cpp \
+    tests/unit/map2/map_find_string_skip.cpp \
+    tests/unit/map2/map_find_string_split.cpp \
+    tests/unit/map2/map_find_string_striped.cpp \
+    tests/unit/map2/map_find_string_refinable.cpp \
+    tests/unit/map2/map_find_string_std.cpp \
+    tests/unit/map2/map_insfind_int.cpp \
+    tests/unit/map2/map_insfind_int_bronsonavltree.cpp \
+    tests/unit/map2/map_insfind_int_cuckoo.cpp \
+    tests/unit/map2/map_insfind_int_ellentree.cpp \
+    tests/unit/map2/map_insfind_int_michael.cpp \
+    tests/unit/map2/map_insfind_int_skip.cpp \
+    tests/unit/map2/map_insfind_int_split.cpp \
+    tests/unit/map2/map_insfind_int_striped.cpp \
+    tests/unit/map2/map_insfind_int_refinable.cpp \
+    tests/unit/map2/map_insfind_int_std.cpp \
     tests/unit/map2/map_insdel_func.cpp \
-    tests/unit/map2/map_insdel_func2.cpp \
-    tests/unit/map2/map_insdel_func3.cpp \
-    tests/unit/map2/map_insdel_func4.cpp \
-    tests/unit/map2/map_insdel_func5.cpp \
-    tests/unit/map2/map_insdel_func6.cpp \
-    tests/unit/map2/map_insdel_func7.cpp \
-    tests/unit/map2/map_insdel_func8.cpp \
+    tests/unit/map2/map_insdel_func_michael.cpp \
+    tests/unit/map2/map_insdel_func_split.cpp \
+    tests/unit/map2/map_insdel_func_skip.cpp \
+    tests/unit/map2/map_insdel_func_ellentree.cpp \
+    tests/unit/map2/map_insdel_func_bronsonavltree.cpp \
+    tests/unit/map2/map_insdel_func_striped.cpp \
+    tests/unit/map2/map_insdel_func_refinable.cpp \
+    tests/unit/map2/map_insdel_func_cuckoo.cpp \
     tests/unit/map2/map_insdel_int.cpp \
+    tests/unit/map2/map_insdel_int_michael.cpp \
+    tests/unit/map2/map_insdel_int_split.cpp \
+    tests/unit/map2/map_insdel_int_skip.cpp \
+    tests/unit/map2/map_insdel_int_ellentree.cpp \
+    tests/unit/map2/map_insdel_int_bronsonavltree.cpp \
+    tests/unit/map2/map_insdel_int_striped.cpp \
+    tests/unit/map2/map_insdel_int_refinable.cpp \
+    tests/unit/map2/map_insdel_int_cuckoo.cpp \
     tests/unit/map2/map_insdel_item_int.cpp \
-    tests/unit/map2/map_insdel_string.cpp \
+    tests/unit/map2/map_insdel_item_int_michael.cpp \
+    tests/unit/map2/map_insdel_item_int_split.cpp \
+    tests/unit/map2/map_insdel_item_int_skip.cpp \
+    tests/unit/map2/map_insdel_item_int_ellentree.cpp \
+    tests/unit/map2/map_insdel_item_int_bronsonavltree.cpp \
+    tests/unit/map2/map_insdel_item_int_striped.cpp \
+    tests/unit/map2/map_insdel_item_int_refinable.cpp \
+    tests/unit/map2/map_insdel_item_int_cuckoo.cpp \
     tests/unit/map2/map_insdel_item_string.cpp \
-    tests/unit/map2/map_insfind_int.cpp \
+    tests/unit/map2/map_insdel_item_string_michael.cpp \
+    tests/unit/map2/map_insdel_item_string_split.cpp \
+    tests/unit/map2/map_insdel_item_string_skip.cpp \
+    tests/unit/map2/map_insdel_item_string_ellentree.cpp \
+    tests/unit/map2/map_insdel_item_string_bronsonavltree.cpp \
+    tests/unit/map2/map_insdel_item_string_striped.cpp \
+    tests/unit/map2/map_insdel_item_string_refinable.cpp \
+    tests/unit/map2/map_insdel_item_string_cuckoo.cpp \
+    tests/unit/map2/map_insdel_string.cpp \
+    tests/unit/map2/map_insdel_string_michael.cpp \
+    tests/unit/map2/map_insdel_string_split.cpp \
+    tests/unit/map2/map_insdel_string_skip.cpp \
+    tests/unit/map2/map_insdel_string_ellentree.cpp \
+    tests/unit/map2/map_insdel_string_bronsonavltree.cpp \
+    tests/unit/map2/map_insdel_string_striped.cpp \
+    tests/unit/map2/map_insdel_string_refinable.cpp \
+    tests/unit/map2/map_insdel_string_cuckoo.cpp \
+    tests/unit/map2/map_insdel_string_std.cpp \
     tests/unit/map2/map_insdelfind.cpp \
-    tests/unit/map2/map_delodd.cpp
+    tests/unit/map2/map_insdelfind_michael.cpp \
+    tests/unit/map2/map_insdelfind_split.cpp \
+    tests/unit/map2/map_insdelfind_skip.cpp \
+    tests/unit/map2/map_insdelfind_ellentree.cpp \
+    tests/unit/map2/map_insdelfind_bronsonavltree.cpp \
+    tests/unit/map2/map_insdelfind_striped.cpp \
+    tests/unit/map2/map_insdelfind_refinable.cpp \
+    tests/unit/map2/map_insdelfind_cuckoo.cpp \
+    tests/unit/map2/map_insdelfind_std.cpp \
+    tests/unit/map2/map_delodd.cpp \
+    tests/unit/map2/map_delodd_michael.cpp \
+    tests/unit/map2/map_delodd_bronsonavltree.cpp \
+    tests/unit/map2/map_delodd_ellentree.cpp \
+    tests/unit/map2/map_delodd_split.cpp \
+    tests/unit/map2/map_delodd_skip.cpp \
+    tests/unit/map2/map_delodd_cuckoo.cpp \
index 8fd0dd51865c00df4c63dd94be017a897a385303..2f286246ae224a346699965a76e236482d849896 100644 (file)
@@ -1,12 +1,33 @@
 
 CDSUNIT_SET_SOURCES := \
        tests/unit/set2/set_insdel_func.cpp \
-       tests/unit/set2/set_insdel_func2.cpp \
-       tests/unit/set2/set_insdel_func3.cpp \
-       tests/unit/set2/set_insdel_func4.cpp \
-       tests/unit/set2/set_insdel_func5.cpp \
-       tests/unit/set2/set_insdel_func6.cpp \
-       tests/unit/set2/set_insdel_func7.cpp \
+       tests/unit/set2/set_insdel_func_cuckoo.cpp \
+       tests/unit/set2/set_insdel_func_ellentree.cpp \
+       tests/unit/set2/set_insdel_func_refinable.cpp \
+       tests/unit/set2/set_insdel_func_skip.cpp \
+       tests/unit/set2/set_insdel_func_split.cpp \
+       tests/unit/set2/set_insdel_func_striped.cpp \
        tests/unit/set2/set_insdel_string.cpp \
+    tests/unit/set2/set_insdel_string_michael.cpp \
+       tests/unit/set2/set_insdel_string_cuckoo.cpp \
+       tests/unit/set2/set_insdel_string_ellentree.cpp \
+       tests/unit/set2/set_insdel_string_refinable.cpp \
+       tests/unit/set2/set_insdel_string_skip.cpp \
+       tests/unit/set2/set_insdel_string_split.cpp \
+       tests/unit/set2/set_insdel_string_striped.cpp \
+    tests/unit/set2/set_insdel_string_std.cpp \
        tests/unit/set2/set_insdelfind.cpp \
-       tests/unit/set2/set_delodd.cpp
+    tests/unit/set2/set_insdelfind_michael.cpp \
+       tests/unit/set2/set_insdelfind_cuckoo.cpp \
+       tests/unit/set2/set_insdelfind_ellentree.cpp \
+       tests/unit/set2/set_insdelfind_refinable.cpp \
+       tests/unit/set2/set_insdelfind_skip.cpp \
+       tests/unit/set2/set_insdelfind_split.cpp \
+       tests/unit/set2/set_insdelfind_striped.cpp \
+    tests/unit/set2/set_insdelfind_std.cpp \
+       tests/unit/set2/set_delodd.cpp \
+       tests/unit/set2/set_delodd_cuckoo.cpp \
+       tests/unit/set2/set_delodd_michael.cpp \
+       tests/unit/set2/set_delodd_ellentree.cpp \
+       tests/unit/set2/set_delodd_skip.cpp \
+       tests/unit/set2/set_delodd_split.cpp \
index 89ae6d0d3144dd75346c2ace47112510b734d4be..714b088391945273206652715506b15713468af5 100644 (file)
@@ -81,6 +81,10 @@ namespace CppUnitMini
       unsigned int getUInt( const char * pszParamName, unsigned int nDefVal = 0 ) const { return get( pszParamName, nDefVal ) ; }
       long getLong( const char * pszParamName, long nDefVal = 0 ) const { return get( pszParamName, nDefVal ) ; }
       unsigned long getULong( const char * pszParamName, unsigned long nDefVal = 0 ) const { return get( pszParamName, nDefVal ) ; }
+      size_t getSizeT( const char * pszParamName, size_t nDefVal = 0 ) const 
+      {
+          return static_cast<size_t>( getULong( pszParamName, static_cast<unsigned long>(nDefVal)));
+      }
 
       bool getBool( const char * pszParamName, bool bDefVal = false ) const
       {
@@ -96,8 +100,7 @@ namespace CppUnitMini
               std::cerr << "bad_lexical_cast encountered while getting parameter "
                   << strParamName << "=" << it->second
                   << ": " << ex.what()
-                  << std::endl
-;
+                  << std::endl;
           }
           return bDefVal;
       }
index a57c5d58874ccdc97e0ae8e7057dd9f6856e2e89..c65467ab2379f480ceb7d58e4ca9eea14eb1bc16 100644 (file)
 //$$CDS-header$$
 
-#include "cppunit/thread.h"
-#include "map2/map_types.h"
-#include <algorithm> // random_shuffle
+#include "map2/map_delodd.h"
 
 namespace map2 {
+    CPPUNIT_TEST_SUITE_REGISTRATION( Map_DelOdd );
 
-#   define TEST_MAP(X)         void X() { test<MapTypes<key_type, value_type>::X >(); }
-#   define TEST_MAP_EXTRACT(X) void X() { test_extract<MapTypes<key_type, value_type>::X >(); }
-#   define TEST_MAP_NOLF(X)    void X() { test_nolf<MapTypes<key_type, value_type>::X >(); }
-#   define TEST_MAP_NOLF_EXTRACT(X) void X() { test_nolf_extract<MapTypes<key_type, value_type>::X >(); }
-
-    namespace {
-        static size_t  c_nMapSize = 1000000         ;  // max map size
-        static size_t  c_nInsThreadCount = 4        ;  // insert thread count
-        static size_t  c_nDelThreadCount = 4        ;  // delete thread count
-        static size_t  c_nExtractThreadCount = 4    ;  // extract thread count
-        static size_t  c_nMaxLoadFactor = 8         ;  // maximum load factor
-        static bool    c_bPrintGCState = true;
-    }
-
-    namespace {
-        struct key_thread
-        {
-            size_t  nKey;
-            size_t  nThread;
-
-            key_thread( size_t key, size_t threadNo )
-                : nKey( key )
-                , nThread( threadNo )
-            {}
-
-            key_thread()
-            {}
-        };
-
-        //typedef MapTypes<key_thread, size_t>::key_val     key_value_pair;
+    size_t  Map_DelOdd::c_nMapSize = 1000000         ;  // max map size
+    size_t  Map_DelOdd::c_nInsThreadCount = 4        ;  // insert thread count
+    size_t  Map_DelOdd::c_nDelThreadCount = 4        ;  // delete thread count
+    size_t  Map_DelOdd::c_nExtractThreadCount = 4    ;  // extract thread count
+    size_t  Map_DelOdd::c_nMaxLoadFactor = 8         ;  // maximum load factor
+    bool    Map_DelOdd::c_bPrintGCState = true;
+
+    void Map_DelOdd::setUpParams( const CppUnitMini::TestCfg& cfg ) {
+        c_nMapSize = cfg.getULong("MapSize", static_cast<unsigned long>(c_nMapSize) );
+        c_nInsThreadCount = cfg.getULong("InsThreadCount", static_cast<unsigned long>(c_nInsThreadCount) );
+        c_nDelThreadCount = cfg.getULong("DelThreadCount", static_cast<unsigned long>(c_nDelThreadCount) );
+        c_nExtractThreadCount = cfg.getULong("ExtractThreadCount", static_cast<unsigned long>(c_nExtractThreadCount) );
+        c_nMaxLoadFactor = cfg.getULong("MaxLoadFactor", static_cast<unsigned long>(c_nMaxLoadFactor) );
+        c_bPrintGCState = cfg.getBool("PrintGCStateFlag", true );
+
+        if ( c_nInsThreadCount == 0 )
+            c_nInsThreadCount = cds::OS::topology::processor_count();
+        if ( c_nDelThreadCount == 0 && c_nExtractThreadCount == 0 ) {
+            c_nExtractThreadCount = cds::OS::topology::processor_count() / 2;
+            c_nDelThreadCount = cds::OS::topology::processor_count() - c_nExtractThreadCount;
+        }
+
+        m_arrData.resize( c_nMapSize );
+        for ( size_t i = 0; i < c_nMapSize; ++i )
+            m_arrData[i] = i;
+        std::random_shuffle( m_arrData.begin(), m_arrData.end() );
     }
 
-    template <>
-    struct cmp<key_thread> {
-        int operator ()(key_thread const& k1, key_thread const& k2) const
-        {
-            if ( k1.nKey < k2.nKey )
-                return -1;
-            if ( k1.nKey > k2.nKey )
-                return 1;
-            if ( k1.nThread < k2.nThread )
-                return -1;
-            if ( k1.nThread > k2.nThread )
-                return 1;
-            return 0;
-        }
-        int operator ()(key_thread const& k1, size_t k2) const
-        {
-            if ( k1.nKey < k2 )
-                return -1;
-            if ( k1.nKey > k2 )
-                return 1;
-            return 0;
-        }
-        int operator ()(size_t k1, key_thread const& k2) const
-        {
-            if ( k1 < k2.nKey )
-                return -1;
-            if ( k1 > k2.nKey )
-                return 1;
-            return 0;
-        }
-    };
-
-} // namespace map2
-
-namespace std {
-    template <>
-    struct less<map2::key_thread>
-    {
-        bool operator()(map2::key_thread const& k1, map2::key_thread const& k2) const
-        {
-            if ( k1.nKey <= k2.nKey )
-                return k1.nKey < k2.nKey || k1.nThread < k2.nThread;
-            return false;
-        }
-    };
-
-    template <>
-    struct hash<map2::key_thread>
-    {
-        typedef size_t              result_type;
-        typedef map2::key_thread    argument_type;
-
-        size_t operator()( map2::key_thread const& k ) const
-        {
-            return std::hash<size_t>()(k.nKey);
-        }
-        size_t operator()( size_t k ) const
-        {
-            return std::hash<size_t>()(k);
-        }
-    };
-} // namespace std
-
-namespace boost {
-    inline size_t hash_value( map2::key_thread const& k )
+    void Map_DelOdd::myRun(const char *in_name, bool invert /*= false*/)
     {
-        return std::hash<size_t>()( k.nKey );
+        setUpParams( m_Cfg.get( "Map_DelOdd" ));
+
+        run_MichaelMap(in_name, invert);
+        run_SplitList(in_name, invert);
+        run_SkipListMap(in_name, invert);
+        run_EllenBinTreeMap(in_name, invert);
+        run_BronsonAVLTreeMap(in_name, invert);
+        //run_StripedMap(in_name, invert);
+        //run_RefinableMap(in_name, invert);
+        run_CuckooMap(in_name, invert);
+        //run_StdMap(in_name, invert);
+
+        endTestCase();
     }
 
-    template <>
-    struct hash<map2::key_thread>
-    {
-        typedef size_t              result_type;
-        typedef map2::key_thread    argument_type;
-
-        size_t operator()(map2::key_thread const& k) const
-        {
-            return boost::hash<size_t>()( k.nKey );
-        }
-        size_t operator()(size_t k) const
-        {
-            return boost::hash<size_t>()( k );
-        }
-    };
-} // namespace boost
-
-namespace map2 {
-
-    class Map_DelOdd: public CppUnitMini::TestCase
-    {
-        std::vector<size_t>     m_arrData;
-
-    protected:
-        typedef key_thread  key_type;
-        typedef size_t      value_type;
-        typedef std::pair<key_type const, value_type> pair_type;
-
-        atomics::atomic<size_t>      m_nInsThreadCount;
-
-        // Inserts keys from [0..N)
-        template <class Map>
-        class InsertThread: public CppUnitMini::TestThread
-        {
-            Map&     m_Map;
-
-            virtual InsertThread *    clone()
-            {
-                return new InsertThread( *this );
-            }
-
-            struct ensure_func
-            {
-                template <typename Q>
-                void operator()( bool /*bNew*/, Q const& )
-                {}
-                template <typename Q, typename V>
-                void operator()( bool /*bNew*/, Q const&, V& )
-                {}
-            };
-        public:
-            size_t  m_nInsertSuccess;
-            size_t  m_nInsertFailed;
-
-        public:
-            InsertThread( CppUnitMini::ThreadPool& pool, Map& rMap )
-                : CppUnitMini::TestThread( pool )
-                , m_Map( rMap )
-            {}
-            InsertThread( InsertThread& src )
-                : CppUnitMini::TestThread( src )
-                , m_Map( src.m_Map )
-            {}
-
-            Map_DelOdd&  getTest()
-            {
-                return reinterpret_cast<Map_DelOdd&>( m_Pool.m_Test );
-            }
-
-            virtual void init() { cds::threading::Manager::attachThread()   ; }
-            virtual void fini() { cds::threading::Manager::detachThread()   ; }
-
-            virtual void test()
-            {
-                Map& rMap = m_Map;
-
-                m_nInsertSuccess =
-                    m_nInsertFailed = 0;
-
-                std::vector<size_t>& arrData = getTest().m_arrData;
-                for ( size_t i = 0; i < arrData.size(); ++i ) {
-                    if ( rMap.insert( key_type( arrData[i], m_nThreadNo )))
-                        ++m_nInsertSuccess;
-                    else
-                        ++m_nInsertFailed;
-                }
-
-                ensure_func f;
-                for ( size_t i = arrData.size() - 1; i > 0; --i ) {
-                    if ( arrData[i] & 1 ) {
-                        rMap.ensure( key_type( arrData[i], m_nThreadNo ), f );
-                    }
-                }
-
-                getTest().m_nInsThreadCount.fetch_sub( 1, atomics::memory_order_acquire );
-            }
-        };
-
-        struct key_equal {
-            bool operator()( key_type const& k1, key_type const& k2 ) const
-            {
-                return k1.nKey == k2.nKey;
-            }
-            bool operator()( size_t k1, key_type const& k2 ) const
-            {
-                return k1 == k2.nKey;
-            }
-            bool operator()( key_type const& k1, size_t k2 ) const
-            {
-                return k1.nKey == k2;
-            }
-        };
-
-        struct key_less {
-            bool operator()( key_type const& k1, key_type const& k2 ) const
-            {
-                return k1.nKey < k2.nKey;
-            }
-            bool operator()( size_t k1, key_type const& k2 ) const
-            {
-                return k1 < k2.nKey;
-            }
-            bool operator()( key_type const& k1, size_t k2 ) const
-            {
-                return k1.nKey < k2;
-            }
-
-            typedef key_equal equal_to;
-        };
-
-        // Deletes odd keys from [0..N)
-        template <class Map>
-        class DeleteThread: public CppUnitMini::TestThread
-        {
-            Map&     m_Map;
-
-            virtual DeleteThread *    clone()
-            {
-                return new DeleteThread( *this );
-            }
-        public:
-            size_t  m_nDeleteSuccess;
-            size_t  m_nDeleteFailed;
-
-        public:
-            DeleteThread( CppUnitMini::ThreadPool& pool, Map& rMap )
-                : CppUnitMini::TestThread( pool )
-                , m_Map( rMap )
-            {}
-            DeleteThread( DeleteThread& src )
-                : CppUnitMini::TestThread( src )
-                , m_Map( src.m_Map )
-            {}
-
-            Map_DelOdd&  getTest()
-            {
-                return reinterpret_cast<Map_DelOdd&>( m_Pool.m_Test );
-            }
-
-            virtual void init() { cds::threading::Manager::attachThread()   ; }
-            virtual void fini() { cds::threading::Manager::detachThread()   ; }
-
-            virtual void test()
-            {
-                Map& rMap = m_Map;
-
-                m_nDeleteSuccess =
-                    m_nDeleteFailed = 0;
-
-                std::vector<size_t>& arrData = getTest().m_arrData;
-                if ( m_nThreadNo & 1 ) {
-                    for ( size_t k = 0; k < c_nInsThreadCount; ++k ) {
-                        for ( size_t i = 0; i < arrData.size(); ++i ) {
-                            if ( arrData[i] & 1 ) {
-                                if ( rMap.erase_with( arrData[i], key_less() ))
-                                    ++m_nDeleteSuccess;
-                                else
-                                    ++m_nDeleteFailed;
-                            }
-                        }
-                        if ( getTest().m_nInsThreadCount.load( atomics::memory_order_acquire ) == 0 )
-                            break;
-                    }
-                }
-                else {
-                    for ( size_t k = 0; k < c_nInsThreadCount; ++k ) {
-                        for ( size_t i = arrData.size() - 1; i > 0; --i ) {
-                            if ( arrData[i] & 1 ) {
-                                if ( rMap.erase_with( arrData[i], key_less() ))
-                                    ++m_nDeleteSuccess;
-                                else
-                                    ++m_nDeleteFailed;
-                            }
-                        }
-                        if ( getTest().m_nInsThreadCount.load( atomics::memory_order_acquire ) == 0 )
-                            break;
-                    }
-                }
-            }
-        };
-
-        // Deletes odd keys from [0..N)
-        template <class GC, class Map >
-        class ExtractThread: public CppUnitMini::TestThread
-        {
-            Map&     m_Map;
-
-            virtual ExtractThread *    clone()
-            {
-                return new ExtractThread( *this );
-            }
-        public:
-            size_t  m_nDeleteSuccess;
-            size_t  m_nDeleteFailed;
-
-        public:
-            ExtractThread( CppUnitMini::ThreadPool& pool, Map& rMap )
-                : CppUnitMini::TestThread( pool )
-                , m_Map( rMap )
-            {}
-            ExtractThread( ExtractThread& src )
-                : CppUnitMini::TestThread( src )
-                , m_Map( src.m_Map )
-            {}
-
-            Map_DelOdd&  getTest()
-            {
-                return reinterpret_cast<Map_DelOdd&>( m_Pool.m_Test );
-            }
-
-            virtual void init() { cds::threading::Manager::attachThread()   ; }
-            virtual void fini() { cds::threading::Manager::detachThread()   ; }
-
-            virtual void test()
-            {
-                Map& rMap = m_Map;
-
-                m_nDeleteSuccess =
-                    m_nDeleteFailed = 0;
-
-                typename Map::guarded_ptr gp;
-
-                std::vector<size_t>& arrData = getTest().m_arrData;
-                if ( m_nThreadNo & 1 ) {
-                    for ( size_t k = 0; k < c_nInsThreadCount; ++k ) {
-                        for ( size_t i = 0; i < arrData.size(); ++i ) {
-                            if ( arrData[i] & 1 ) {
-                                gp = rMap.extract_with( arrData[i], key_less());
-                                if ( gp )
-                                    ++m_nDeleteSuccess;
-                                else
-                                    ++m_nDeleteFailed;
-                                gp.release();
-                            }
-                        }
-                        if ( getTest().m_nInsThreadCount.load( atomics::memory_order_acquire ) == 0 )
-                            break;
-                    }
-                }
-                else {
-                    for ( size_t k = 0; k < c_nInsThreadCount; ++k ) {
-                        for ( size_t i = arrData.size() - 1; i > 0; --i ) {
-                            if ( arrData[i] & 1 ) {
-                                gp = rMap.extract_with( arrData[i], key_less());
-                                if ( gp )
-                                    ++m_nDeleteSuccess;
-                                else
-                                    ++m_nDeleteFailed;
-                                gp.release();
-                            }
-                        }
-                        if ( getTest().m_nInsThreadCount.load( atomics::memory_order_acquire ) == 0 )
-                            break;
-                    }
-                }
-            }
-        };
-
-        template <class RCU, class Map >
-        class ExtractThread< cds::urcu::gc<RCU>, Map > : public CppUnitMini::TestThread
-        {
-            Map&     m_Map;
-
-            virtual ExtractThread *    clone()
-            {
-                return new ExtractThread( *this );
-            }
-        public:
-            size_t  m_nDeleteSuccess;
-            size_t  m_nDeleteFailed;
-
-        public:
-            ExtractThread( CppUnitMini::ThreadPool& pool, Map& rMap )
-                : CppUnitMini::TestThread( pool )
-                , m_Map( rMap )
-            {}
-            ExtractThread( ExtractThread& src )
-                : CppUnitMini::TestThread( src )
-                , m_Map( src.m_Map )
-            {}
-
-            Map_DelOdd&  getTest()
-            {
-                return reinterpret_cast<Map_DelOdd&>( m_Pool.m_Test );
-            }
-
-            virtual void init() { cds::threading::Manager::attachThread()   ; }
-            virtual void fini() { cds::threading::Manager::detachThread()   ; }
-
-            virtual void test()
-            {
-                Map& rMap = m_Map;
-
-                m_nDeleteSuccess =
-                    m_nDeleteFailed = 0;
-
-                typename Map::exempt_ptr xp;
-
-                std::vector<size_t>& arrData = getTest().m_arrData;
-                if ( m_nThreadNo & 1 ) {
-                    for ( size_t k = 0; k < c_nInsThreadCount; ++k ) {
-                        for ( size_t i = 0; i < arrData.size(); ++i ) {
-                            if ( arrData[i] & 1 ) {
-                                if ( Map::c_bExtractLockExternal ) {
-                                    {
-                                        typename Map::rcu_lock l;
-                                        xp = rMap.extract_with( arrData[i], key_less() );
-                                        if ( xp )
-                                            ++m_nDeleteSuccess;
-                                        else
-                                            ++m_nDeleteFailed;
-                                    }
-                                }
-                                else {
-                                    xp = rMap.extract_with( arrData[i], key_less() );
-                                    if ( xp )
-                                        ++m_nDeleteSuccess;
-                                    else
-                                        ++m_nDeleteFailed;
-                                }
-                                xp.release();
-                            }
-                        }
-                        if ( getTest().m_nInsThreadCount.load( atomics::memory_order_acquire ) == 0 )
-                            break;
-                    }
-                }
-                else {
-                    for ( size_t k = 0; k < c_nInsThreadCount; ++k ) {
-                        for ( size_t i = arrData.size() - 1; i > 0; --i ) {
-                            if ( arrData[i] & 1 ) {
-                                if ( Map::c_bExtractLockExternal ) {
-                                    {
-                                        typename Map::rcu_lock l;
-                                        xp = rMap.extract_with( arrData[i], key_less() );
-                                        if ( xp )
-                                            ++m_nDeleteSuccess;
-                                        else
-                                            ++m_nDeleteFailed;
-                                    }
-                                }
-                                else {
-                                    xp = rMap.extract_with( arrData[i], key_less() );
-                                    if ( xp )
-                                        ++m_nDeleteSuccess;
-                                    else
-                                        ++m_nDeleteFailed;
-                                }
-                                xp.release();
-                            }
-                        }
-                        if ( getTest().m_nInsThreadCount.load( atomics::memory_order_acquire ) == 0 )
-                            break;
-                    }
-                }
-            }
-        };
-
-    protected:
-        template <class Map>
-        void do_test( size_t nLoadFactor )
-        {
-            Map  testMap( c_nMapSize, nLoadFactor );
-            do_test_with( testMap );
-        }
-
-        template <class Map>
-        void do_test_extract( size_t nLoadFactor )
-        {
-            Map  testMap( c_nMapSize, nLoadFactor );
-            do_test_extract_with( testMap );
-        }
-
-        template <class Map>
-        void do_test_with( Map& testMap )
-        {
-            typedef InsertThread<Map> insert_thread;
-            typedef DeleteThread<Map> delete_thread;
-
-            m_nInsThreadCount.store( c_nInsThreadCount, atomics::memory_order_release );
-
-            CppUnitMini::ThreadPool pool( *this );
-            pool.add( new insert_thread( pool, testMap ), c_nInsThreadCount );
-            pool.add( new delete_thread( pool, testMap ), c_nDelThreadCount ? c_nDelThreadCount : cds::OS::topology::processor_count());
-            pool.run();
-            CPPUNIT_MSG( "   Duration=" << pool.avgDuration() );
-
-            size_t nInsertSuccess = 0;
-            size_t nInsertFailed = 0;
-            size_t nDeleteSuccess = 0;
-            size_t nDeleteFailed = 0;
-            for ( CppUnitMini::ThreadPool::iterator it = pool.begin(); it != pool.end(); ++it ) {
-                insert_thread * pThread = dynamic_cast<insert_thread *>( *it );
-                if ( pThread ) {
-                    nInsertSuccess += pThread->m_nInsertSuccess;
-                    nInsertFailed += pThread->m_nInsertFailed;
-                }
-                else {
-                    delete_thread * p = static_cast<delete_thread *>( *it );
-                    nDeleteSuccess += p->m_nDeleteSuccess;
-                    nDeleteFailed += p->m_nDeleteFailed;
-                }
-            }
-
-            CPPUNIT_MSG( "  Totals (success/failed): \n\t"
-                << "      Insert=" << nInsertSuccess << '/' << nInsertFailed << "\n\t"
-                << "      Delete=" << nDeleteSuccess << '/' << nDeleteFailed << "\n\t"
-                );
-            CPPUNIT_CHECK( nInsertSuccess == c_nMapSize * c_nInsThreadCount );
-            CPPUNIT_CHECK( nInsertFailed == 0 );
-
-            analyze( testMap );
-        }
-
-        template <class Map>
-        void do_test_extract_with( Map& testMap )
-        {
-            typedef InsertThread<Map> insert_thread;
-            typedef DeleteThread<Map> delete_thread;
-            typedef ExtractThread< typename Map::gc, Map > extract_thread;
-
-            m_nInsThreadCount.store( c_nInsThreadCount, atomics::memory_order_release );
-
-            CppUnitMini::ThreadPool pool( *this );
-            pool.add( new insert_thread( pool, testMap ), c_nInsThreadCount );
-            if ( c_nDelThreadCount )
-                pool.add( new delete_thread( pool, testMap ), c_nDelThreadCount );
-            if ( c_nExtractThreadCount )
-                pool.add( new extract_thread( pool, testMap ), c_nExtractThreadCount );
-            pool.run();
-            CPPUNIT_MSG( "   Duration=" << pool.avgDuration() );
-
-            size_t nInsertSuccess = 0;
-            size_t nInsertFailed = 0;
-            size_t nDeleteSuccess = 0;
-            size_t nDeleteFailed = 0;
-            size_t nExtractSuccess = 0;
-            size_t nExtractFailed = 0;
-            for ( CppUnitMini::ThreadPool::iterator it = pool.begin(); it != pool.end(); ++it ) {
-                insert_thread * pThread = dynamic_cast<insert_thread *>( *it );
-                if ( pThread ) {
-                    nInsertSuccess += pThread->m_nInsertSuccess;
-                    nInsertFailed += pThread->m_nInsertFailed;
-                }
-                else {
-                    delete_thread * p = dynamic_cast<delete_thread *>( *it );
-                    if ( p ) {
-                        nDeleteSuccess += p->m_nDeleteSuccess;
-                        nDeleteFailed += p->m_nDeleteFailed;
-                    }
-                    else {
-                        extract_thread * pExtract = dynamic_cast<extract_thread *>( *it );
-                        assert( pExtract );
-                        nExtractSuccess += pExtract->m_nDeleteSuccess;
-                        nExtractFailed += pExtract->m_nDeleteFailed;
-                    }
-                }
-            }
-
-            CPPUNIT_MSG( "  Totals (success/failed): \n\t"
-                << "      Insert=" << nInsertSuccess << '/' << nInsertFailed << "\n\t"
-                << "      Delete=" << nDeleteSuccess << '/' << nDeleteFailed << "\n\t"
-                << "      Extract=" << nExtractSuccess << '/' << nExtractFailed << "\n\t"
-                );
-            CPPUNIT_CHECK( nInsertSuccess == c_nMapSize * c_nInsThreadCount );
-            CPPUNIT_CHECK( nInsertFailed == 0 );
-
-            analyze( testMap );
-        }
-
-        template <class Map>
-        void analyze( Map& testMap )
-        {
-            cds::OS::Timer    timer;
-
-            // All even keys must be in the map
-            {
-                size_t nErrorCount = 0;
-                CPPUNIT_MSG( "  Check even keys..." );
-                for ( size_t n = 0; n < c_nMapSize; n +=2 ) {
-                    for ( size_t i = 0; i < c_nInsThreadCount; ++i ) {
-                        if ( !testMap.find( key_type(n, i) ) ) {
-                            if ( ++nErrorCount < 10 ) {
-                                CPPUNIT_MSG( "key " << n << "-" << i << " is not found!");
-                            }
-                        }
-                    }
-                }
-                CPPUNIT_CHECK_EX( nErrorCount == 0, "Totals: " << nErrorCount << " keys is not found");
-            }
-
-            check_before_cleanup( testMap );
-
-            CPPUNIT_MSG( "  Clear map (single-threaded)..." );
-            timer.reset();
-            testMap.clear();
-            CPPUNIT_MSG( "   Duration=" << timer.duration() );
-            CPPUNIT_CHECK_EX( testMap.empty(), ((long long) testMap.size()) );
-
-            additional_check( testMap );
-            print_stat( testMap );
-
-            additional_cleanup( testMap );
-        }
-
-
-        template <class Map>
-        void test()
-        {
-            CPPUNIT_MSG( "Insert thread count=" << c_nInsThreadCount
-                << " delete thread count=" << c_nDelThreadCount
-                << " set size=" << c_nMapSize
-                );
-
-            for ( size_t nLoadFactor = 1; nLoadFactor <= c_nMaxLoadFactor; nLoadFactor *= 2 ) {
-                CPPUNIT_MSG( "Load factor=" << nLoadFactor );
-                do_test<Map>( nLoadFactor );
-                if ( c_bPrintGCState )
-                    print_gc_state();
-            }
-        }
-
-        template <class Map>
-        void test_extract()
-        {
-            CPPUNIT_MSG( "Thread count: insert=" << c_nInsThreadCount
-                << ", delete=" << c_nDelThreadCount
-                << ", extract=" << c_nExtractThreadCount
-                << "; set size=" << c_nMapSize
-                );
-
-            for ( size_t nLoadFactor = 1; nLoadFactor <= c_nMaxLoadFactor; nLoadFactor *= 2 ) {
-                CPPUNIT_MSG( "Load factor=" << nLoadFactor );
-                do_test_extract<Map>( nLoadFactor );
-                if ( c_bPrintGCState )
-                    print_gc_state();
-            }
-        }
-
-        template <class Map>
-        void test_nolf()
-        {
-            CPPUNIT_MSG( "Insert thread count=" << c_nInsThreadCount
-                << " delete thread count=" << c_nDelThreadCount
-                << " set size=" << c_nMapSize
-                );
-
-            Map s;
-            do_test_with( s );
-            if ( c_bPrintGCState )
-                print_gc_state();
-        }
-
-        template <class Map>
-        void test_nolf_extract()
-        {
-            CPPUNIT_MSG( "Thread count: insert=" << c_nInsThreadCount
-                << ", delete=" << c_nDelThreadCount
-                << ", extract=" << c_nExtractThreadCount
-                << "; set size=" << c_nMapSize
-                );
-
-            Map s;
-            do_test_extract_with( s );
-            if ( c_bPrintGCState )
-                print_gc_state();
-        }
-
-        void setUpParams( const CppUnitMini::TestCfg& cfg ) {
-            c_nMapSize = cfg.getULong("MapSize", static_cast<unsigned long>(c_nMapSize) );
-            c_nInsThreadCount = cfg.getULong("InsThreadCount", static_cast<unsigned long>(c_nInsThreadCount) );
-            c_nDelThreadCount = cfg.getULong("DelThreadCount", static_cast<unsigned long>(c_nDelThreadCount) );
-            c_nExtractThreadCount = cfg.getULong("ExtractThreadCount", static_cast<unsigned long>(c_nExtractThreadCount) );
-            c_nMaxLoadFactor = cfg.getULong("MaxLoadFactor", static_cast<unsigned long>(c_nMaxLoadFactor) );
-            c_bPrintGCState = cfg.getBool("PrintGCStateFlag", true );
-
-            if ( c_nInsThreadCount == 0 )
-                c_nInsThreadCount = cds::OS::topology::processor_count();
-            if ( c_nDelThreadCount == 0 && c_nExtractThreadCount == 0 ) {
-                c_nExtractThreadCount = cds::OS::topology::processor_count() / 2;
-                c_nDelThreadCount = cds::OS::topology::processor_count() - c_nExtractThreadCount;
-            }
-
-            m_arrData.resize( c_nMapSize );
-            for ( size_t i = 0; i < c_nMapSize; ++i )
-                m_arrData[i] = i;
-            std::random_shuffle( m_arrData.begin(), m_arrData.end() );
-        }
-
-#   include "map2/map_defs.h"
-        CDSUNIT_DECLARE_MichaelMap
-        CDSUNIT_DECLARE_SplitList
-        //CDSUNIT_DECLARE_StripedMap
-        //CDSUNIT_DECLARE_RefinableMap
-        CDSUNIT_DECLARE_CuckooMap
-        CDSUNIT_DECLARE_SkipListMap
-        CDSUNIT_DECLARE_EllenBinTreeMap
-        CDSUNIT_DECLARE_BronsonAVLTreeMap
-        //CDSUNIT_DECLARE_StdMap
-
-        CPPUNIT_TEST_SUITE( Map_DelOdd )
-            CDSUNIT_TEST_MichaelMap
-            CDSUNIT_TEST_SplitList
-            CDSUNIT_TEST_SkipListMap
-            CDSUNIT_TEST_EllenBinTreeMap
-            CDSUNIT_TEST_BronsonAVLTreeMap
-            //CDSUNIT_TEST_StripedMap
-            //CDSUNIT_TEST_RefinableMap
-            CDSUNIT_TEST_CuckooMap
-            //CDSUNIT_TEST_StdMap
-        CPPUNIT_TEST_SUITE_END()
-    };
-
-    CPPUNIT_TEST_SUITE_REGISTRATION( Map_DelOdd );
 } // namespace map2
diff --git a/tests/unit/map2/map_delodd.h b/tests/unit/map2/map_delodd.h
new file mode 100644 (file)
index 0000000..226098b
--- /dev/null
@@ -0,0 +1,723 @@
+//$$CDS-header$$
+
+#include "cppunit/thread.h"
+#include "map2/map_types.h"
+#include <algorithm> // random_shuffle
+
+namespace map2 {
+
+#   define TEST_MAP(X)         void X() { test<MapTypes<key_type, value_type>::X >(); }
+#   define TEST_MAP_EXTRACT(X) void X() { test_extract<MapTypes<key_type, value_type>::X >(); }
+#   define TEST_MAP_NOLF(X)    void X() { test_nolf<MapTypes<key_type, value_type>::X >(); }
+#   define TEST_MAP_NOLF_EXTRACT(X) void X() { test_nolf_extract<MapTypes<key_type, value_type>::X >(); }
+
+    namespace {
+        struct key_thread
+        {
+            size_t  nKey;
+            size_t  nThread;
+
+            key_thread( size_t key, size_t threadNo )
+                : nKey( key )
+                , nThread( threadNo )
+            {}
+
+            key_thread()
+            {}
+        };
+
+        //typedef MapTypes<key_thread, size_t>::key_val     key_value_pair;
+    }
+
+    template <>
+    struct cmp<key_thread> {
+        int operator ()(key_thread const& k1, key_thread const& k2) const
+        {
+            if ( k1.nKey < k2.nKey )
+                return -1;
+            if ( k1.nKey > k2.nKey )
+                return 1;
+            if ( k1.nThread < k2.nThread )
+                return -1;
+            if ( k1.nThread > k2.nThread )
+                return 1;
+            return 0;
+        }
+        int operator ()(key_thread const& k1, size_t k2) const
+        {
+            if ( k1.nKey < k2 )
+                return -1;
+            if ( k1.nKey > k2 )
+                return 1;
+            return 0;
+        }
+        int operator ()(size_t k1, key_thread const& k2) const
+        {
+            if ( k1 < k2.nKey )
+                return -1;
+            if ( k1 > k2.nKey )
+                return 1;
+            return 0;
+        }
+    };
+
+} // namespace map2
+
+namespace std {
+    template <>
+    struct less<map2::key_thread>
+    {
+        bool operator()(map2::key_thread const& k1, map2::key_thread const& k2) const
+        {
+            if ( k1.nKey <= k2.nKey )
+                return k1.nKey < k2.nKey || k1.nThread < k2.nThread;
+            return false;
+        }
+    };
+
+    template <>
+    struct hash<map2::key_thread>
+    {
+        typedef size_t              result_type;
+        typedef map2::key_thread    argument_type;
+
+        size_t operator()( map2::key_thread const& k ) const
+        {
+            return std::hash<size_t>()(k.nKey);
+        }
+        size_t operator()( size_t k ) const
+        {
+            return std::hash<size_t>()(k);
+        }
+    };
+} // namespace std
+
+namespace boost {
+    inline size_t hash_value( map2::key_thread const& k )
+    {
+        return std::hash<size_t>()( k.nKey );
+    }
+
+    template <>
+    struct hash<map2::key_thread>
+    {
+        typedef size_t              result_type;
+        typedef map2::key_thread    argument_type;
+
+        size_t operator()(map2::key_thread const& k) const
+        {
+            return boost::hash<size_t>()( k.nKey );
+        }
+        size_t operator()(size_t k) const
+        {
+            return boost::hash<size_t>()( k );
+        }
+    };
+} // namespace boost
+
+namespace map2 {
+
+    class Map_DelOdd: public CppUnitMini::TestCase
+    {
+        static size_t  c_nMapSize;          // max map size
+        static size_t  c_nInsThreadCount;   // insert thread count
+        static size_t  c_nDelThreadCount;   // delete thread count
+        static size_t  c_nExtractThreadCount;  // extract thread count
+        static size_t  c_nMaxLoadFactor;    // maximum load factor
+        static bool    c_bPrintGCState;
+
+        std::vector<size_t>     m_arrData;
+
+    protected:
+        typedef CppUnitMini::TestCase Base;
+
+        typedef key_thread  key_type;
+        typedef size_t      value_type;
+        typedef std::pair<key_type const, value_type> pair_type;
+
+        atomics::atomic<size_t>      m_nInsThreadCount;
+
+        // Inserts keys from [0..N)
+        template <class Map>
+        class InsertThread: public CppUnitMini::TestThread
+        {
+            Map&     m_Map;
+
+            virtual InsertThread *    clone()
+            {
+                return new InsertThread( *this );
+            }
+
+            struct ensure_func
+            {
+                template <typename Q>
+                void operator()( bool /*bNew*/, Q const& )
+                {}
+                template <typename Q, typename V>
+                void operator()( bool /*bNew*/, Q const&, V& )
+                {}
+            };
+        public:
+            size_t  m_nInsertSuccess;
+            size_t  m_nInsertFailed;
+
+        public:
+            InsertThread( CppUnitMini::ThreadPool& pool, Map& rMap )
+                : CppUnitMini::TestThread( pool )
+                , m_Map( rMap )
+            {}
+            InsertThread( InsertThread& src )
+                : CppUnitMini::TestThread( src )
+                , m_Map( src.m_Map )
+            {}
+
+            Map_DelOdd&  getTest()
+            {
+                return reinterpret_cast<Map_DelOdd&>( m_Pool.m_Test );
+            }
+
+            virtual void init() { cds::threading::Manager::attachThread()   ; }
+            virtual void fini() { cds::threading::Manager::detachThread()   ; }
+
+            virtual void test()
+            {
+                Map& rMap = m_Map;
+
+                m_nInsertSuccess =
+                    m_nInsertFailed = 0;
+
+                std::vector<size_t>& arrData = getTest().m_arrData;
+                for ( size_t i = 0; i < arrData.size(); ++i ) {
+                    if ( rMap.insert( key_type( arrData[i], m_nThreadNo )))
+                        ++m_nInsertSuccess;
+                    else
+                        ++m_nInsertFailed;
+                }
+
+                ensure_func f;
+                for ( size_t i = arrData.size() - 1; i > 0; --i ) {
+                    if ( arrData[i] & 1 ) {
+                        rMap.ensure( key_type( arrData[i], m_nThreadNo ), f );
+                    }
+                }
+
+                getTest().m_nInsThreadCount.fetch_sub( 1, atomics::memory_order_acquire );
+            }
+        };
+
+        struct key_equal {
+            bool operator()( key_type const& k1, key_type const& k2 ) const
+            {
+                return k1.nKey == k2.nKey;
+            }
+            bool operator()( size_t k1, key_type const& k2 ) const
+            {
+                return k1 == k2.nKey;
+            }
+            bool operator()( key_type const& k1, size_t k2 ) const
+            {
+                return k1.nKey == k2;
+            }
+        };
+
+        struct key_less {
+            bool operator()( key_type const& k1, key_type const& k2 ) const
+            {
+                return k1.nKey < k2.nKey;
+            }
+            bool operator()( size_t k1, key_type const& k2 ) const
+            {
+                return k1 < k2.nKey;
+            }
+            bool operator()( key_type const& k1, size_t k2 ) const
+            {
+                return k1.nKey < k2;
+            }
+
+            typedef key_equal equal_to;
+        };
+
+        // Deletes odd keys from [0..N)
+        template <class Map>
+        class DeleteThread: public CppUnitMini::TestThread
+        {
+            Map&     m_Map;
+
+            virtual DeleteThread *    clone()
+            {
+                return new DeleteThread( *this );
+            }
+        public:
+            size_t  m_nDeleteSuccess;
+            size_t  m_nDeleteFailed;
+
+        public:
+            DeleteThread( CppUnitMini::ThreadPool& pool, Map& rMap )
+                : CppUnitMini::TestThread( pool )
+                , m_Map( rMap )
+            {}
+            DeleteThread( DeleteThread& src )
+                : CppUnitMini::TestThread( src )
+                , m_Map( src.m_Map )
+            {}
+
+            Map_DelOdd&  getTest()
+            {
+                return reinterpret_cast<Map_DelOdd&>( m_Pool.m_Test );
+            }
+
+            virtual void init() { cds::threading::Manager::attachThread()   ; }
+            virtual void fini() { cds::threading::Manager::detachThread()   ; }
+
+            virtual void test()
+            {
+                Map& rMap = m_Map;
+
+                m_nDeleteSuccess =
+                    m_nDeleteFailed = 0;
+
+                std::vector<size_t>& arrData = getTest().m_arrData;
+                if ( m_nThreadNo & 1 ) {
+                    for ( size_t k = 0; k < c_nInsThreadCount; ++k ) {
+                        for ( size_t i = 0; i < arrData.size(); ++i ) {
+                            if ( arrData[i] & 1 ) {
+                                if ( rMap.erase_with( arrData[i], key_less() ))
+                                    ++m_nDeleteSuccess;
+                                else
+                                    ++m_nDeleteFailed;
+                            }
+                        }
+                        if ( getTest().m_nInsThreadCount.load( atomics::memory_order_acquire ) == 0 )
+                            break;
+                    }
+                }
+                else {
+                    for ( size_t k = 0; k < c_nInsThreadCount; ++k ) {
+                        for ( size_t i = arrData.size() - 1; i > 0; --i ) {
+                            if ( arrData[i] & 1 ) {
+                                if ( rMap.erase_with( arrData[i], key_less() ))
+                                    ++m_nDeleteSuccess;
+                                else
+                                    ++m_nDeleteFailed;
+                            }
+                        }
+                        if ( getTest().m_nInsThreadCount.load( atomics::memory_order_acquire ) == 0 )
+                            break;
+                    }
+                }
+            }
+        };
+
+        // Deletes odd keys from [0..N)
+        template <class GC, class Map >
+        class ExtractThread: public CppUnitMini::TestThread
+        {
+            Map&     m_Map;
+
+            virtual ExtractThread *    clone()
+            {
+                return new ExtractThread( *this );
+            }
+        public:
+            size_t  m_nDeleteSuccess;
+            size_t  m_nDeleteFailed;
+
+        public:
+            ExtractThread( CppUnitMini::ThreadPool& pool, Map& rMap )
+                : CppUnitMini::TestThread( pool )
+                , m_Map( rMap )
+            {}
+            ExtractThread( ExtractThread& src )
+                : CppUnitMini::TestThread( src )
+                , m_Map( src.m_Map )
+            {}
+
+            Map_DelOdd&  getTest()
+            {
+                return reinterpret_cast<Map_DelOdd&>( m_Pool.m_Test );
+            }
+
+            virtual void init() { cds::threading::Manager::attachThread()   ; }
+            virtual void fini() { cds::threading::Manager::detachThread()   ; }
+
+            virtual void test()
+            {
+                Map& rMap = m_Map;
+
+                m_nDeleteSuccess =
+                    m_nDeleteFailed = 0;
+
+                typename Map::guarded_ptr gp;
+
+                std::vector<size_t>& arrData = getTest().m_arrData;
+                if ( m_nThreadNo & 1 ) {
+                    for ( size_t k = 0; k < c_nInsThreadCount; ++k ) {
+                        for ( size_t i = 0; i < arrData.size(); ++i ) {
+                            if ( arrData[i] & 1 ) {
+                                gp = rMap.extract_with( arrData[i], key_less());
+                                if ( gp )
+                                    ++m_nDeleteSuccess;
+                                else
+                                    ++m_nDeleteFailed;
+                                gp.release();
+                            }
+                        }
+                        if ( getTest().m_nInsThreadCount.load( atomics::memory_order_acquire ) == 0 )
+                            break;
+                    }
+                }
+                else {
+                    for ( size_t k = 0; k < c_nInsThreadCount; ++k ) {
+                        for ( size_t i = arrData.size() - 1; i > 0; --i ) {
+                            if ( arrData[i] & 1 ) {
+                                gp = rMap.extract_with( arrData[i], key_less());
+                                if ( gp )
+                                    ++m_nDeleteSuccess;
+                                else
+                                    ++m_nDeleteFailed;
+                                gp.release();
+                            }
+                        }
+                        if ( getTest().m_nInsThreadCount.load( atomics::memory_order_acquire ) == 0 )
+                            break;
+                    }
+                }
+            }
+        };
+
+        template <class RCU, class Map >
+        class ExtractThread< cds::urcu::gc<RCU>, Map > : public CppUnitMini::TestThread
+        {
+            Map&     m_Map;
+
+            virtual ExtractThread *    clone()
+            {
+                return new ExtractThread( *this );
+            }
+        public:
+            size_t  m_nDeleteSuccess;
+            size_t  m_nDeleteFailed;
+
+        public:
+            ExtractThread( CppUnitMini::ThreadPool& pool, Map& rMap )
+                : CppUnitMini::TestThread( pool )
+                , m_Map( rMap )
+            {}
+            ExtractThread( ExtractThread& src )
+                : CppUnitMini::TestThread( src )
+                , m_Map( src.m_Map )
+            {}
+
+            Map_DelOdd&  getTest()
+            {
+                return reinterpret_cast<Map_DelOdd&>( m_Pool.m_Test );
+            }
+
+            virtual void init() { cds::threading::Manager::attachThread()   ; }
+            virtual void fini() { cds::threading::Manager::detachThread()   ; }
+
+            virtual void test()
+            {
+                Map& rMap = m_Map;
+
+                m_nDeleteSuccess =
+                    m_nDeleteFailed = 0;
+
+                typename Map::exempt_ptr xp;
+
+                std::vector<size_t>& arrData = getTest().m_arrData;
+                if ( m_nThreadNo & 1 ) {
+                    for ( size_t k = 0; k < c_nInsThreadCount; ++k ) {
+                        for ( size_t i = 0; i < arrData.size(); ++i ) {
+                            if ( arrData[i] & 1 ) {
+                                if ( Map::c_bExtractLockExternal ) {
+                                    {
+                                        typename Map::rcu_lock l;
+                                        xp = rMap.extract_with( arrData[i], key_less() );
+                                        if ( xp )
+                                            ++m_nDeleteSuccess;
+                                        else
+                                            ++m_nDeleteFailed;
+                                    }
+                                }
+                                else {
+                                    xp = rMap.extract_with( arrData[i], key_less() );
+                                    if ( xp )
+                                        ++m_nDeleteSuccess;
+                                    else
+                                        ++m_nDeleteFailed;
+                                }
+                                xp.release();
+                            }
+                        }
+                        if ( getTest().m_nInsThreadCount.load( atomics::memory_order_acquire ) == 0 )
+                            break;
+                    }
+                }
+                else {
+                    for ( size_t k = 0; k < c_nInsThreadCount; ++k ) {
+                        for ( size_t i = arrData.size() - 1; i > 0; --i ) {
+                            if ( arrData[i] & 1 ) {
+                                if ( Map::c_bExtractLockExternal ) {
+                                    {
+                                        typename Map::rcu_lock l;
+                                        xp = rMap.extract_with( arrData[i], key_less() );
+                                        if ( xp )
+                                            ++m_nDeleteSuccess;
+                                        else
+                                            ++m_nDeleteFailed;
+                                    }
+                                }
+                                else {
+                                    xp = rMap.extract_with( arrData[i], key_less() );
+                                    if ( xp )
+                                        ++m_nDeleteSuccess;
+                                    else
+                                        ++m_nDeleteFailed;
+                                }
+                                xp.release();
+                            }
+                        }
+                        if ( getTest().m_nInsThreadCount.load( atomics::memory_order_acquire ) == 0 )
+                            break;
+                    }
+                }
+            }
+        };
+
+    protected:
+        template <class Map>
+        void do_test( size_t nLoadFactor )
+        {
+            Map  testMap( c_nMapSize, nLoadFactor );
+            do_test_with( testMap );
+        }
+
+        template <class Map>
+        void do_test_extract( size_t nLoadFactor )
+        {
+            Map  testMap( c_nMapSize, nLoadFactor );
+            do_test_extract_with( testMap );
+        }
+
+        template <class Map>
+        void do_test_with( Map& testMap )
+        {
+            typedef InsertThread<Map> insert_thread;
+            typedef DeleteThread<Map> delete_thread;
+
+            m_nInsThreadCount.store( c_nInsThreadCount, atomics::memory_order_release );
+
+            CppUnitMini::ThreadPool pool( *this );
+            pool.add( new insert_thread( pool, testMap ), c_nInsThreadCount );
+            pool.add( new delete_thread( pool, testMap ), c_nDelThreadCount ? c_nDelThreadCount : cds::OS::topology::processor_count());
+            pool.run();
+            CPPUNIT_MSG( "   Duration=" << pool.avgDuration() );
+
+            size_t nInsertSuccess = 0;
+            size_t nInsertFailed = 0;
+            size_t nDeleteSuccess = 0;
+            size_t nDeleteFailed = 0;
+            for ( CppUnitMini::ThreadPool::iterator it = pool.begin(); it != pool.end(); ++it ) {
+                insert_thread * pThread = dynamic_cast<insert_thread *>( *it );
+                if ( pThread ) {
+                    nInsertSuccess += pThread->m_nInsertSuccess;
+                    nInsertFailed += pThread->m_nInsertFailed;
+                }
+                else {
+                    delete_thread * p = static_cast<delete_thread *>( *it );
+                    nDeleteSuccess += p->m_nDeleteSuccess;
+                    nDeleteFailed += p->m_nDeleteFailed;
+                }
+            }
+
+            CPPUNIT_MSG( "  Totals (success/failed): \n\t"
+                << "      Insert=" << nInsertSuccess << '/' << nInsertFailed << "\n\t"
+                << "      Delete=" << nDeleteSuccess << '/' << nDeleteFailed << "\n\t"
+                );
+            CPPUNIT_CHECK( nInsertSuccess == c_nMapSize * c_nInsThreadCount );
+            CPPUNIT_CHECK( nInsertFailed == 0 );
+
+            analyze( testMap );
+        }
+
+        template <class Map>
+        void do_test_extract_with( Map& testMap )
+        {
+            typedef InsertThread<Map> insert_thread;
+            typedef DeleteThread<Map> delete_thread;
+            typedef ExtractThread< typename Map::gc, Map > extract_thread;
+
+            m_nInsThreadCount.store( c_nInsThreadCount, atomics::memory_order_release );
+
+            CppUnitMini::ThreadPool pool( *this );
+            pool.add( new insert_thread( pool, testMap ), c_nInsThreadCount );
+            if ( c_nDelThreadCount )
+                pool.add( new delete_thread( pool, testMap ), c_nDelThreadCount );
+            if ( c_nExtractThreadCount )
+                pool.add( new extract_thread( pool, testMap ), c_nExtractThreadCount );
+            pool.run();
+            CPPUNIT_MSG( "   Duration=" << pool.avgDuration() );
+
+            size_t nInsertSuccess = 0;
+            size_t nInsertFailed = 0;
+            size_t nDeleteSuccess = 0;
+            size_t nDeleteFailed = 0;
+            size_t nExtractSuccess = 0;
+            size_t nExtractFailed = 0;
+            for ( CppUnitMini::ThreadPool::iterator it = pool.begin(); it != pool.end(); ++it ) {
+                insert_thread * pThread = dynamic_cast<insert_thread *>( *it );
+                if ( pThread ) {
+                    nInsertSuccess += pThread->m_nInsertSuccess;
+                    nInsertFailed += pThread->m_nInsertFailed;
+                }
+                else {
+                    delete_thread * p = dynamic_cast<delete_thread *>( *it );
+                    if ( p ) {
+                        nDeleteSuccess += p->m_nDeleteSuccess;
+                        nDeleteFailed += p->m_nDeleteFailed;
+                    }
+                    else {
+                        extract_thread * pExtract = dynamic_cast<extract_thread *>( *it );
+                        assert( pExtract );
+                        nExtractSuccess += pExtract->m_nDeleteSuccess;
+                        nExtractFailed += pExtract->m_nDeleteFailed;
+                    }
+                }
+            }
+
+            CPPUNIT_MSG( "  Totals (success/failed): \n\t"
+                << "      Insert=" << nInsertSuccess << '/' << nInsertFailed << "\n\t"
+                << "      Delete=" << nDeleteSuccess << '/' << nDeleteFailed << "\n\t"
+                << "      Extract=" << nExtractSuccess << '/' << nExtractFailed << "\n\t"
+                );
+            CPPUNIT_CHECK( nInsertSuccess == c_nMapSize * c_nInsThreadCount );
+            CPPUNIT_CHECK( nInsertFailed == 0 );
+
+            analyze( testMap );
+        }
+
+        template <class Map>
+        void analyze( Map& testMap )
+        {
+            cds::OS::Timer    timer;
+
+            // All even keys must be in the map
+            {
+                size_t nErrorCount = 0;
+                CPPUNIT_MSG( "  Check even keys..." );
+                for ( size_t n = 0; n < c_nMapSize; n +=2 ) {
+                    for ( size_t i = 0; i < c_nInsThreadCount; ++i ) {
+                        if ( !testMap.find( key_type(n, i) ) ) {
+                            if ( ++nErrorCount < 10 ) {
+                                CPPUNIT_MSG( "key " << n << "-" << i << " is not found!");
+                            }
+                        }
+                    }
+                }
+                CPPUNIT_CHECK_EX( nErrorCount == 0, "Totals: " << nErrorCount << " keys is not found");
+            }
+
+            check_before_cleanup( testMap );
+
+            CPPUNIT_MSG( "  Clear map (single-threaded)..." );
+            timer.reset();
+            testMap.clear();
+            CPPUNIT_MSG( "   Duration=" << timer.duration() );
+            CPPUNIT_CHECK_EX( testMap.empty(), ((long long) testMap.size()) );
+
+            additional_check( testMap );
+            print_stat( testMap );
+
+            additional_cleanup( testMap );
+        }
+
+
+        template <class Map>
+        void test()
+        {
+            CPPUNIT_MSG( "Insert thread count=" << c_nInsThreadCount
+                << " delete thread count=" << c_nDelThreadCount
+                << " set size=" << c_nMapSize
+                );
+
+            for ( size_t nLoadFactor = 1; nLoadFactor <= c_nMaxLoadFactor; nLoadFactor *= 2 ) {
+                CPPUNIT_MSG( "Load factor=" << nLoadFactor );
+                do_test<Map>( nLoadFactor );
+                if ( c_bPrintGCState )
+                    print_gc_state();
+            }
+        }
+
+        template <class Map>
+        void test_extract()
+        {
+            CPPUNIT_MSG( "Thread count: insert=" << c_nInsThreadCount
+                << ", delete=" << c_nDelThreadCount
+                << ", extract=" << c_nExtractThreadCount
+                << "; set size=" << c_nMapSize
+                );
+
+            for ( size_t nLoadFactor = 1; nLoadFactor <= c_nMaxLoadFactor; nLoadFactor *= 2 ) {
+                CPPUNIT_MSG( "Load factor=" << nLoadFactor );
+                do_test_extract<Map>( nLoadFactor );
+                if ( c_bPrintGCState )
+                    print_gc_state();
+            }
+        }
+
+        template <class Map>
+        void test_nolf()
+        {
+            CPPUNIT_MSG( "Insert thread count=" << c_nInsThreadCount
+                << " delete thread count=" << c_nDelThreadCount
+                << " set size=" << c_nMapSize
+                );
+
+            Map s;
+            do_test_with( s );
+            if ( c_bPrintGCState )
+                print_gc_state();
+        }
+
+        template <class Map>
+        void test_nolf_extract()
+        {
+            CPPUNIT_MSG( "Thread count: insert=" << c_nInsThreadCount
+                << ", delete=" << c_nDelThreadCount
+                << ", extract=" << c_nExtractThreadCount
+                << "; set size=" << c_nMapSize
+                );
+
+            Map s;
+            do_test_extract_with( s );
+            if ( c_bPrintGCState )
+                print_gc_state();
+        }
+
+        void setUpParams( const CppUnitMini::TestCfg& cfg );
+
+        void run_MichaelMap(const char *in_name, bool invert = false);
+        void run_SplitList(const char *in_name, bool invert = false);
+        //void run_StripedMap(const char *in_name, bool invert = false);
+        //void run_RefinableMap(const char *in_name, bool invert = false);
+        void run_CuckooMap(const char *in_name, bool invert = false);
+        void run_SkipListMap(const char *in_name, bool invert = false);
+        void run_EllenBinTreeMap(const char *in_name, bool invert = false);
+        void run_BronsonAVLTreeMap(const char *in_name, bool invert = false);
+        //void run_StdMap(const char *in_name, bool invert = false);
+
+        virtual void myRun(const char *in_name, bool invert = false);
+
+#   include "map2/map_defs.h"
+        CDSUNIT_DECLARE_MichaelMap
+        CDSUNIT_DECLARE_SplitList
+        //CDSUNIT_DECLARE_StripedMap
+        //CDSUNIT_DECLARE_RefinableMap
+        CDSUNIT_DECLARE_CuckooMap
+        CDSUNIT_DECLARE_SkipListMap
+        CDSUNIT_DECLARE_EllenBinTreeMap
+        CDSUNIT_DECLARE_BronsonAVLTreeMap
+        //CDSUNIT_DECLARE_StdMap
+    };
+} // namespace map2
diff --git a/tests/unit/map2/map_delodd_bronsonavltree.cpp b/tests/unit/map2/map_delodd_bronsonavltree.cpp
new file mode 100644 (file)
index 0000000..0448891
--- /dev/null
@@ -0,0 +1,9 @@
+//$$CDS-header$$
+
+#include "map2/map_delodd.h"
+
+namespace map2 {
+    CPPUNIT_TEST_SUITE_PART( Map_DelOdd, run_BronsonAVLTreeMap )
+        CDSUNIT_TEST_BronsonAVLTreeMap
+    CPPUNIT_TEST_SUITE_END_PART()
+} // namespace map2
diff --git a/tests/unit/map2/map_delodd_cuckoo.cpp b/tests/unit/map2/map_delodd_cuckoo.cpp
new file mode 100644 (file)
index 0000000..191d35a
--- /dev/null
@@ -0,0 +1,9 @@
+//$$CDS-header$$
+
+#include "map2/map_delodd.h"
+
+namespace map2 {
+    CPPUNIT_TEST_SUITE_PART( Map_DelOdd, run_CuckooMap )
+        CDSUNIT_TEST_CuckooMap
+    CPPUNIT_TEST_SUITE_END_PART()
+} // namespace map2
diff --git a/tests/unit/map2/map_delodd_ellentree.cpp b/tests/unit/map2/map_delodd_ellentree.cpp
new file mode 100644 (file)
index 0000000..e6883aa
--- /dev/null
@@ -0,0 +1,9 @@
+//$$CDS-header$$
+
+#include "map2/map_delodd.h"
+
+namespace map2 {
+    CPPUNIT_TEST_SUITE_PART( Map_DelOdd, run_EllenBinTreeMap )
+        CDSUNIT_TEST_EllenBinTreeMap
+    CPPUNIT_TEST_SUITE_END_PART()
+} // namespace map2
diff --git a/tests/unit/map2/map_delodd_michael.cpp b/tests/unit/map2/map_delodd_michael.cpp
new file mode 100644 (file)
index 0000000..c114aed
--- /dev/null
@@ -0,0 +1,9 @@
+//$$CDS-header$$
+
+#include "map2/map_delodd.h"
+
+namespace map2 {
+    CPPUNIT_TEST_SUITE_PART( Map_DelOdd, run_MichaelMap )
+        CDSUNIT_TEST_MichaelMap
+    CPPUNIT_TEST_SUITE_END_PART()
+} // namespace map2
diff --git a/tests/unit/map2/map_delodd_skip.cpp b/tests/unit/map2/map_delodd_skip.cpp
new file mode 100644 (file)
index 0000000..bb92b6d
--- /dev/null
@@ -0,0 +1,9 @@
+//$$CDS-header$$
+
+#include "map2/map_delodd.h"
+
+namespace map2 {
+    CPPUNIT_TEST_SUITE_PART( Map_DelOdd, run_SkipListMap )
+        CDSUNIT_TEST_SkipListMap
+    CPPUNIT_TEST_SUITE_END_PART()
+} // namespace map2
diff --git a/tests/unit/map2/map_delodd_split.cpp b/tests/unit/map2/map_delodd_split.cpp
new file mode 100644 (file)
index 0000000..b8895cb
--- /dev/null
@@ -0,0 +1,9 @@
+//$$CDS-header$$
+
+#include "map2/map_delodd.h"
+
+namespace map2 {
+    CPPUNIT_TEST_SUITE_PART( Map_DelOdd, run_SplitList )
+        CDSUNIT_TEST_SplitList
+    CPPUNIT_TEST_SUITE_END_PART()
+} // namespace map2
index 8e4f22c05e06538895fdaed2aaf5f416671751a4..5b201ff826fa15dc837e544e994d98ba92d3d837 100644 (file)
 
 // defines concurrent access to map::nonconcurrent_iterator::Sequence::TValue::nAccess field
 
-#include "map2/map_types.h"
-#include "cppunit/thread.h"
-
-#include <vector>
-#include <algorithm> // random_shuffle
+#include "map2/map_find_int.h"
 
 // find int test in map<int> in mutithreaded mode
 namespace map2 {
+    CPPUNIT_TEST_SUITE_REGISTRATION( Map_find_int );
 
-#   define TEST_MAP(X)         void X() { test<MapTypes<key_type, value_type>::X >()    ; }
-#   define TEST_MAP_NOLF(X)    void X() { test_nolf<MapTypes<key_type, value_type>::X >()    ; }
-#   define TEST_MAP_EXTRACT(X)  TEST_MAP(X)
-#   define TEST_MAP_NOLF_EXTRACT(X) TEST_MAP_NOLF(X)
-
-    namespace {
-        static size_t  c_nThreadCount = 8      ;  // thread count
-        static size_t  c_nMapSize = 20000000   ;  // map size (count of searching item)
-        static size_t  c_nPercentExists = 50   ;  // percent of existing keys in searching sequence
-        static size_t  c_nPassCount = 2;
-        static size_t  c_nMaxLoadFactor = 8    ;  // maximum load factor
-        static bool    c_bPrintGCState = true;
-    }
+    size_t Map_find_int::c_nThreadCount = 8      ;  // thread count
+    size_t Map_find_int::c_nMapSize = 20000000   ;  // map size (count of searching item)
+    size_t Map_find_int::c_nPercentExists = 50   ;  // percent of existing keys in searching sequence
+    size_t Map_find_int::c_nPassCount = 2;
+    size_t Map_find_int::c_nMaxLoadFactor = 8    ;  // maximum load factor
+    bool   Map_find_int::c_bPrintGCState = true;
 
-    class Map_find_int: public CppUnitMini::TestCase
+    void Map_find_int::generateSequence()
     {
-        typedef size_t   key_type;
-        struct value_type {
-            key_type    nKey    ;   // key
-            bool        bExists ;   // true - key in map, false - key not in map
-        };
-
-        typedef std::vector<value_type> ValueVector;
-        ValueVector             m_Arr;
-        size_t                  m_nRealMapSize;
-        bool                    m_bSequenceInitialized;
-
-        void generateSequence()
-        {
-            size_t nPercent = c_nPercentExists;
-
-            if ( nPercent > 100 )
-                nPercent = 100;
-            else if ( nPercent < 1 )
-                nPercent = 1;
-
-            m_nRealMapSize = 0;
-
-            m_Arr.resize( c_nMapSize );
-            for ( size_t i = 0; i < c_nMapSize; ++i ) {
-                m_Arr[i].nKey = i * 13;
-                m_Arr[i].bExists = CppUnitMini::Rand( 100 ) <= nPercent;
-                if ( m_Arr[i].bExists )
-                    ++m_nRealMapSize;
-            }
-            std::random_shuffle( m_Arr.begin(), m_Arr.end() );
-        }
-
-        template <typename Iterator, typename Map>
-        static bool check_result( Iterator const& it, Map const& map )
-        {
-            return it != map.end();
-        }
-        template <typename Map>
-        static bool check_result( bool b, Map const& )
-        {
-            return b;
-        }
-
-        template <class Map>
-        class TestThread: public CppUnitMini::TestThread
-        {
-            Map&     m_Map;
-
-            virtual TestThread *    clone()
-            {
-                return new TestThread( *this );
-            }
-        public:
-            struct Stat {
-                size_t      nSuccess;
-                size_t      nFailed;
-
-                Stat()
-                    : nSuccess(0)
-                    , nFailed(0)
-                {}
-            };
-
-            Stat    m_KeyExists;
-            Stat    m_KeyNotExists;
-
-        public:
-            TestThread( CppUnitMini::ThreadPool& pool, Map& rMap )
-                : CppUnitMini::TestThread( pool )
-                , m_Map( rMap )
-            {}
-            TestThread( TestThread& src )
-                : CppUnitMini::TestThread( src )
-                , m_Map( src.m_Map )
-            {}
-
-            Map_find_int&  getTest()
-            {
-                return reinterpret_cast<Map_find_int&>( m_Pool.m_Test );
-            }
-
-            virtual void init() { cds::threading::Manager::attachThread()   ; }
-            virtual void fini() { cds::threading::Manager::detachThread()   ; }
-
-            virtual void test()
-            {
-                ValueVector& arr = getTest().m_Arr;
-                //size_t nSize = arr.size();
-
-                Map& rMap = m_Map;
-                for ( size_t nPass = 0; nPass < c_nPassCount; ++nPass ) {
-                    if ( m_nThreadNo & 1 ) {
-                        ValueVector::const_iterator itEnd = arr.end();
-                        for ( ValueVector::const_iterator it = arr.begin(); it != itEnd; ++it ) {
-                            auto bFound = rMap.find( it->nKey );
-                            if ( it->bExists ) {
-                                if ( check_result( bFound, rMap ))
-                                    ++m_KeyExists.nSuccess;
-                                else {
-                                    //rMap.find( it->nKey );
-                                    ++m_KeyExists.nFailed;
-                                }
-                            }
-                            else {
-                                if ( check_result( bFound, rMap )) {
-                                    //rMap.find( it->nKey );
-                                    ++m_KeyNotExists.nFailed;
-                                }
-                                else
-                                    ++m_KeyNotExists.nSuccess;
-                            }
-                        }
-                    }
-                    else {
-                        ValueVector::const_reverse_iterator itEnd = arr.rend();
-                        for ( ValueVector::const_reverse_iterator it = arr.rbegin(); it != itEnd; ++it ) {
-                            auto bFound = rMap.find( it->nKey );
-                            if ( it->bExists ) {
-                                if ( check_result( bFound, rMap ))
-                                    ++m_KeyExists.nSuccess;
-                                else {
-                                    //rMap.find( it->nKey );
-                                    ++m_KeyExists.nFailed;
-                                }
-                            }
-                            else {
-                                if ( check_result( bFound, rMap )) {
-                                    //rMap.find( it->nKey );
-                                    ++m_KeyNotExists.nFailed;
-                                }
-                                else
-                                    ++m_KeyNotExists.nSuccess;
-                            }
-                        }
-                    }
-                }
-            }
-        };
-
-    protected:
+        size_t nPercent = c_nPercentExists;
 
-        template <class Map>
-        void find_int_test( Map& testMap )
-        {
-            typedef TestThread<Map>     Thread;
-            cds::OS::Timer    timer;
+        if ( nPercent > 100 )
+            nPercent = 100;
+        else if ( nPercent < 1 )
+            nPercent = 1;
 
-            // Fill the map
-            CPPUNIT_MSG( "  Fill map with " << m_Arr.size() << " items...");
-            timer.reset();
-            for ( size_t i = 0; i < m_Arr.size(); ++i ) {
-                if ( m_Arr[i].bExists ) {
-                    CPPUNIT_ASSERT( check_result( testMap.insert( m_Arr[i].nKey, m_Arr[i] ), testMap ));
-                }
-            }
-            CPPUNIT_MSG( "   Duration=" << timer.duration() );
+        m_nRealMapSize = 0;
 
-            CPPUNIT_MSG( "  Searching...");
-            CppUnitMini::ThreadPool pool( *this );
-            pool.add( new Thread( pool, testMap ), c_nThreadCount );
-            pool.run();
-            CPPUNIT_MSG( "   Duration=" << pool.avgDuration() );
-
-            for ( CppUnitMini::ThreadPool::iterator it = pool.begin(); it != pool.end(); ++it ) {
-                Thread * pThread = static_cast<Thread *>( *it );
-                CPPUNIT_CHECK( pThread->m_KeyExists.nFailed == 0 );
-                CPPUNIT_CHECK( pThread->m_KeyExists.nSuccess == m_nRealMapSize * c_nPassCount );
-                CPPUNIT_CHECK( pThread->m_KeyNotExists.nFailed == 0 );
-                CPPUNIT_CHECK( pThread->m_KeyNotExists.nSuccess == (m_Arr.size() - m_nRealMapSize) * c_nPassCount );
-            }
-
-            check_before_cleanup( testMap );
-
-            testMap.clear();
-            additional_check( testMap );
-            print_stat( testMap );
-            additional_cleanup( testMap );
-        }
-
-        void initTestSequence()
-        {
-            CPPUNIT_MSG( "Generating test data...");
-            cds::OS::Timer    timer;
-            generateSequence();
-            CPPUNIT_MSG( "   Duration=" << timer.duration() );
-            CPPUNIT_MSG( "Map size=" << m_nRealMapSize << " find key loop=" << m_Arr.size() << " (" << c_nPercentExists << "% success)" );
-            CPPUNIT_MSG( "Thread count=" << c_nThreadCount << " Pass count=" << c_nPassCount );
-
-            m_bSequenceInitialized = true;
-        }
-
-        template <class Map>
-        void test()
-        {
-            if ( !m_bSequenceInitialized )
-                initTestSequence();
-
-            for ( size_t nLoadFactor = 1; nLoadFactor <= c_nMaxLoadFactor; nLoadFactor *= 2 ) {
-                CPPUNIT_MSG( "Load factor=" << nLoadFactor );
-                Map  testMap( c_nMapSize, nLoadFactor );
-                find_int_test( testMap );
-                if ( c_bPrintGCState )
-                    print_gc_state();
-            }
-        }
-
-        template <class Map>
-        void test_nolf()
-        {
-            if ( !m_bSequenceInitialized )
-                initTestSequence();
-
-            Map testMap;
-            find_int_test( testMap );
-            if ( c_bPrintGCState )
-                print_gc_state();
+        m_Arr.resize( c_nMapSize );
+        for ( size_t i = 0; i < c_nMapSize; ++i ) {
+            m_Arr[i].nKey = i * 13;
+            m_Arr[i].bExists = CppUnitMini::Rand( 100 ) <= nPercent;
+            if ( m_Arr[i].bExists )
+                ++m_nRealMapSize;
         }
+        std::random_shuffle( m_Arr.begin(), m_Arr.end() );
+    }
 
-        void setUpParams( const CppUnitMini::TestCfg& cfg ) {
-            c_nThreadCount = cfg.getULong("ThreadCount", 8 )        ; // thread count
-            c_nMapSize = cfg.getULong("MapSize", 20000000 )         ;  // map size (count of searching item)
-            c_nPercentExists = cfg.getULong("PercentExists", 50 )   ;  // percent of existing keys in searching sequence
-            c_nPassCount = cfg.getULong("PassCount", 2 );
-            c_nMaxLoadFactor = cfg.getULong("MaxLoadFactor", 8 );
-            c_bPrintGCState = cfg.getBool("PrintGCStateFlag", true );
-        }
-
-
-    public:
-        Map_find_int()
-            : m_bSequenceInitialized( false )
-        {}
+    void Map_find_int::initTestSequence()
+    {
+        CPPUNIT_MSG( "Generating test data...");
+        cds::OS::Timer    timer;
+        generateSequence();
+        CPPUNIT_MSG( "   Duration=" << timer.duration() );
+        CPPUNIT_MSG( "Map size=" << m_nRealMapSize << " find key loop=" << m_Arr.size() << " (" << c_nPercentExists << "% success)" );
+        CPPUNIT_MSG( "Thread count=" << c_nThreadCount << " Pass count=" << c_nPassCount );
+
+        m_bSequenceInitialized = true;
+    }
 
-#   include "map2/map_defs.h"
-        CDSUNIT_DECLARE_MichaelMap
-        CDSUNIT_DECLARE_MichaelMap_nogc
-        CDSUNIT_DECLARE_SplitList
-        CDSUNIT_DECLARE_SplitList_nogc
-        CDSUNIT_DECLARE_SkipListMap
-        CDSUNIT_DECLARE_SkipListMap_nogc
-        CDSUNIT_DECLARE_EllenBinTreeMap
-        CDSUNIT_DECLARE_BronsonAVLTreeMap
-        CDSUNIT_DECLARE_StripedMap
-        CDSUNIT_DECLARE_RefinableMap
-        CDSUNIT_DECLARE_CuckooMap
-        CDSUNIT_DECLARE_StdMap
+    void Map_find_int::setUpParams( const CppUnitMini::TestCfg& cfg )
+    {
+        c_nThreadCount = cfg.getSizeT("ThreadCount", c_nThreadCount );
+        c_nMapSize = cfg.getSizeT("MapSize", c_nMapSize);
+        c_nPercentExists = cfg.getSizeT("PercentExists", c_nPercentExists);
+        c_nPassCount = cfg.getSizeT("PassCount", c_nPassCount);
+        c_nMaxLoadFactor = cfg.getSizeT("MaxLoadFactor", c_nMaxLoadFactor);
+        c_bPrintGCState = cfg.getBool("PrintGCStateFlag", c_bPrintGCState );
+    }
 
-        CPPUNIT_TEST_SUITE( Map_find_int )
-            CDSUNIT_TEST_MichaelMap
-            CDSUNIT_TEST_MichaelMap_nogc
-            CDSUNIT_TEST_SplitList
-            CDSUNIT_TEST_SplitList_nogc
-            CDSUNIT_TEST_SkipListMap
-            CDSUNIT_TEST_SkipListMap_nogc
-            CDSUNIT_TEST_EllenBinTreeMap
-            CDSUNIT_TEST_BronsonAVLTreeMap
-            CDSUNIT_TEST_StripedMap
-            CDSUNIT_TEST_RefinableMap
-            CDSUNIT_TEST_CuckooMap
-            CDSUNIT_TEST_StdMap
-        CPPUNIT_TEST_SUITE_END()
-    };
+    void Map_find_int::myRun(const char *in_name, bool invert /*= false*/)
+    {
+        setUpParams( m_Cfg.get( "Map_find_int" ));
+
+        run_MichaelMap(in_name, invert);
+        run_SplitList(in_name, invert);
+        run_SkipListMap(in_name, invert);
+        run_EllenBinTreeMap(in_name, invert);
+        run_BronsonAVLTreeMap(in_name, invert);
+        run_StripedMap(in_name, invert);
+        run_RefinableMap(in_name, invert);
+        run_CuckooMap(in_name, invert);
+        run_StdMap(in_name, invert);
+
+        endTestCase();
+    }
 
-    CPPUNIT_TEST_SUITE_REGISTRATION( Map_find_int );
 } // namespace map
diff --git a/tests/unit/map2/map_find_int.h b/tests/unit/map2/map_find_int.h
new file mode 100644 (file)
index 0000000..cc4c12e
--- /dev/null
@@ -0,0 +1,251 @@
+//$$CDS-header$$
+
+// defines concurrent access to map::nonconcurrent_iterator::Sequence::TValue::nAccess field
+
+#include "map2/map_types.h"
+#include "cppunit/thread.h"
+
+#include <vector>
+#include <algorithm> // random_shuffle
+
+// find int test in map<int> in mutithreaded mode
+namespace map2 {
+
+#   define TEST_MAP(X)         void X() { test<MapTypes<key_type, value_type>::X >()    ; }
+#   define TEST_MAP_NOLF(X)    void X() { test_nolf<MapTypes<key_type, value_type>::X >()    ; }
+#   define TEST_MAP_EXTRACT(X)  TEST_MAP(X)
+#   define TEST_MAP_NOLF_EXTRACT(X) TEST_MAP_NOLF(X)
+
+    class Map_find_int: public CppUnitMini::TestCase
+    {
+        static size_t c_nThreadCount;   // thread count
+        static size_t c_nMapSize;       // map size (count of searching item)
+        static size_t c_nPercentExists; // percent of existing keys in searching sequence
+        static size_t c_nPassCount;
+        static size_t c_nMaxLoadFactor; // maximum load factor
+        static bool   c_bPrintGCState;
+
+        typedef CppUnitMini::TestCase Base;
+        typedef size_t   key_type;
+        struct value_type {
+            key_type    nKey    ;   // key
+            bool        bExists ;   // true - key in map, false - key not in map
+        };
+
+        typedef std::vector<value_type> ValueVector;
+        ValueVector             m_Arr;
+        size_t                  m_nRealMapSize;
+        bool                    m_bSequenceInitialized;
+
+        void generateSequence();
+
+        template <typename Iterator, typename Map>
+        static bool check_result( Iterator const& it, Map const& map )
+        {
+            return it != map.end();
+        }
+        template <typename Map>
+        static bool check_result( bool b, Map const& )
+        {
+            return b;
+        }
+
+        template <class Map>
+        class TestThread: public CppUnitMini::TestThread
+        {
+            Map&     m_Map;
+
+            virtual TestThread *    clone()
+            {
+                return new TestThread( *this );
+            }
+        public:
+            struct Stat {
+                size_t      nSuccess;
+                size_t      nFailed;
+
+                Stat()
+                    : nSuccess(0)
+                    , nFailed(0)
+                {}
+            };
+
+            Stat    m_KeyExists;
+            Stat    m_KeyNotExists;
+
+        public:
+            TestThread( CppUnitMini::ThreadPool& pool, Map& rMap )
+                : CppUnitMini::TestThread( pool )
+                , m_Map( rMap )
+            {}
+            TestThread( TestThread& src )
+                : CppUnitMini::TestThread( src )
+                , m_Map( src.m_Map )
+            {}
+
+            Map_find_int&  getTest()
+            {
+                return reinterpret_cast<Map_find_int&>( m_Pool.m_Test );
+            }
+
+            virtual void init() { cds::threading::Manager::attachThread()   ; }
+            virtual void fini() { cds::threading::Manager::detachThread()   ; }
+
+            virtual void test()
+            {
+                ValueVector& arr = getTest().m_Arr;
+                //size_t nSize = arr.size();
+
+                Map& rMap = m_Map;
+                for ( size_t nPass = 0; nPass < c_nPassCount; ++nPass ) {
+                    if ( m_nThreadNo & 1 ) {
+                        ValueVector::const_iterator itEnd = arr.end();
+                        for ( ValueVector::const_iterator it = arr.begin(); it != itEnd; ++it ) {
+                            auto bFound = rMap.find( it->nKey );
+                            if ( it->bExists ) {
+                                if ( check_result( bFound, rMap ))
+                                    ++m_KeyExists.nSuccess;
+                                else {
+                                    //rMap.find( it->nKey );
+                                    ++m_KeyExists.nFailed;
+                                }
+                            }
+                            else {
+                                if ( check_result( bFound, rMap )) {
+                                    //rMap.find( it->nKey );
+                                    ++m_KeyNotExists.nFailed;
+                                }
+                                else
+                                    ++m_KeyNotExists.nSuccess;
+                            }
+                        }
+                    }
+                    else {
+                        ValueVector::const_reverse_iterator itEnd = arr.rend();
+                        for ( ValueVector::const_reverse_iterator it = arr.rbegin(); it != itEnd; ++it ) {
+                            auto bFound = rMap.find( it->nKey );
+                            if ( it->bExists ) {
+                                if ( check_result( bFound, rMap ))
+                                    ++m_KeyExists.nSuccess;
+                                else {
+                                    //rMap.find( it->nKey );
+                                    ++m_KeyExists.nFailed;
+                                }
+                            }
+                            else {
+                                if ( check_result( bFound, rMap )) {
+                                    //rMap.find( it->nKey );
+                                    ++m_KeyNotExists.nFailed;
+                                }
+                                else
+                                    ++m_KeyNotExists.nSuccess;
+                            }
+                        }
+                    }
+                }
+            }
+        };
+
+    protected:
+
+        template <class Map>
+        void find_int_test( Map& testMap )
+        {
+            typedef TestThread<Map>     Thread;
+            cds::OS::Timer    timer;
+
+            // Fill the map
+            CPPUNIT_MSG( "  Fill map with " << m_Arr.size() << " items...");
+            timer.reset();
+            for ( size_t i = 0; i < m_Arr.size(); ++i ) {
+                if ( m_Arr[i].bExists ) {
+                    CPPUNIT_ASSERT( check_result( testMap.insert( m_Arr[i].nKey, m_Arr[i] ), testMap ));
+                }
+            }
+            CPPUNIT_MSG( "   Duration=" << timer.duration() );
+
+            CPPUNIT_MSG( "  Searching...");
+            CppUnitMini::ThreadPool pool( *this );
+            pool.add( new Thread( pool, testMap ), c_nThreadCount );
+            pool.run();
+            CPPUNIT_MSG( "   Duration=" << pool.avgDuration() );
+
+            for ( CppUnitMini::ThreadPool::iterator it = pool.begin(); it != pool.end(); ++it ) {
+                Thread * pThread = static_cast<Thread *>( *it );
+                CPPUNIT_CHECK( pThread->m_KeyExists.nFailed == 0 );
+                CPPUNIT_CHECK( pThread->m_KeyExists.nSuccess == m_nRealMapSize * c_nPassCount );
+                CPPUNIT_CHECK( pThread->m_KeyNotExists.nFailed == 0 );
+                CPPUNIT_CHECK( pThread->m_KeyNotExists.nSuccess == (m_Arr.size() - m_nRealMapSize) * c_nPassCount );
+            }
+
+            check_before_cleanup( testMap );
+
+            testMap.clear();
+            additional_check( testMap );
+            print_stat( testMap );
+            additional_cleanup( testMap );
+        }
+
+        void initTestSequence();
+
+        template <class Map>
+        void test()
+        {
+            if ( !m_bSequenceInitialized )
+                initTestSequence();
+
+            for ( size_t nLoadFactor = 1; nLoadFactor <= c_nMaxLoadFactor; nLoadFactor *= 2 ) {
+                CPPUNIT_MSG( "Load factor=" << nLoadFactor );
+                Map  testMap( c_nMapSize, nLoadFactor );
+                find_int_test( testMap );
+                if ( c_bPrintGCState )
+                    print_gc_state();
+            }
+        }
+
+        template <class Map>
+        void test_nolf()
+        {
+            if ( !m_bSequenceInitialized )
+                initTestSequence();
+
+            Map testMap;
+            find_int_test( testMap );
+            if ( c_bPrintGCState )
+                print_gc_state();
+        }
+
+        void setUpParams( const CppUnitMini::TestCfg& cfg );
+
+        void run_MichaelMap(const char *in_name, bool invert = false);
+        void run_SplitList(const char *in_name, bool invert = false);
+        void run_StripedMap(const char *in_name, bool invert = false);
+        void run_RefinableMap(const char *in_name, bool invert = false);
+        void run_CuckooMap(const char *in_name, bool invert = false);
+        void run_SkipListMap(const char *in_name, bool invert = false);
+        void run_EllenBinTreeMap(const char *in_name, bool invert = false);
+        void run_BronsonAVLTreeMap(const char *in_name, bool invert = false);
+        void run_StdMap(const char *in_name, bool invert = false);
+
+        virtual void myRun(const char *in_name, bool invert = false);
+
+    public:
+        Map_find_int()
+            : m_bSequenceInitialized( false )
+        {}
+
+#   include "map2/map_defs.h"
+        CDSUNIT_DECLARE_MichaelMap
+        CDSUNIT_DECLARE_MichaelMap_nogc
+        CDSUNIT_DECLARE_SplitList
+        CDSUNIT_DECLARE_SplitList_nogc
+        CDSUNIT_DECLARE_SkipListMap
+        CDSUNIT_DECLARE_SkipListMap_nogc
+        CDSUNIT_DECLARE_EllenBinTreeMap
+        CDSUNIT_DECLARE_BronsonAVLTreeMap
+        CDSUNIT_DECLARE_StripedMap
+        CDSUNIT_DECLARE_RefinableMap
+        CDSUNIT_DECLARE_CuckooMap
+        CDSUNIT_DECLARE_StdMap
+    };
+} // namespace map
diff --git a/tests/unit/map2/map_find_int_bronsonavltree.cpp b/tests/unit/map2/map_find_int_bronsonavltree.cpp
new file mode 100644 (file)
index 0000000..2c915a6
--- /dev/null
@@ -0,0 +1,9 @@
+//$$CDS-header$$
+
+#include "map2/map_find_int.h"
+
+namespace map2 {
+    CPPUNIT_TEST_SUITE_PART( Map_find_int, run_BronsonAVLTreeMap )
+        CDSUNIT_TEST_BronsonAVLTreeMap
+    CPPUNIT_TEST_SUITE_END_PART()
+} // namespace map2
diff --git a/tests/unit/map2/map_find_int_cuckoo.cpp b/tests/unit/map2/map_find_int_cuckoo.cpp
new file mode 100644 (file)
index 0000000..b397fca
--- /dev/null
@@ -0,0 +1,9 @@
+//$$CDS-header$$
+
+#include "map2/map_find_int.h"
+
+namespace map2 {
+    CPPUNIT_TEST_SUITE_PART( Map_find_int, run_CuckooMap )
+        CDSUNIT_TEST_CuckooMap
+    CPPUNIT_TEST_SUITE_END_PART()
+} // namespace map2
diff --git a/tests/unit/map2/map_find_int_ellentree.cpp b/tests/unit/map2/map_find_int_ellentree.cpp
new file mode 100644 (file)
index 0000000..3f5e9ff
--- /dev/null
@@ -0,0 +1,9 @@
+//$$CDS-header$$
+
+#include "map2/map_find_int.h"
+
+namespace map2 {
+    CPPUNIT_TEST_SUITE_PART( Map_find_int, run_EllenBinTreeMap )
+        CDSUNIT_TEST_EllenBinTreeMap
+    CPPUNIT_TEST_SUITE_END_PART()
+} // namespace map2
diff --git a/tests/unit/map2/map_find_int_michael.cpp b/tests/unit/map2/map_find_int_michael.cpp
new file mode 100644 (file)
index 0000000..6ab7702
--- /dev/null
@@ -0,0 +1,10 @@
+//$$CDS-header$$
+
+#include "map2/map_find_int.h"
+
+namespace map2 {
+    CPPUNIT_TEST_SUITE_PART( Map_find_int, run_MichaelMap )
+        CDSUNIT_TEST_MichaelMap
+        CDSUNIT_TEST_MichaelMap_nogc
+    CPPUNIT_TEST_SUITE_END_PART()
+} // namespace map2
diff --git a/tests/unit/map2/map_find_int_refinable.cpp b/tests/unit/map2/map_find_int_refinable.cpp
new file mode 100644 (file)
index 0000000..d047537
--- /dev/null
@@ -0,0 +1,9 @@
+//$$CDS-header$$
+
+#include "map2/map_find_int.h"
+
+namespace map2 {
+    CPPUNIT_TEST_SUITE_PART( Map_find_int, run_RefinableMap )
+        CDSUNIT_TEST_RefinableMap
+    CPPUNIT_TEST_SUITE_END_PART()
+} // namespace map2
diff --git a/tests/unit/map2/map_find_int_skip.cpp b/tests/unit/map2/map_find_int_skip.cpp
new file mode 100644 (file)
index 0000000..edfcc41
--- /dev/null
@@ -0,0 +1,10 @@
+//$$CDS-header$$
+
+#include "map2/map_find_int.h"
+
+namespace map2 {
+    CPPUNIT_TEST_SUITE_PART( Map_find_int, run_SkipListMap )
+        CDSUNIT_TEST_SkipListMap
+        CDSUNIT_TEST_SkipListMap_nogc
+    CPPUNIT_TEST_SUITE_END_PART()
+} // namespace map2
diff --git a/tests/unit/map2/map_find_int_split.cpp b/tests/unit/map2/map_find_int_split.cpp
new file mode 100644 (file)
index 0000000..b565e3e
--- /dev/null
@@ -0,0 +1,10 @@
+//$$CDS-header$$
+
+#include "map2/map_find_int.h"
+
+namespace map2 {
+    CPPUNIT_TEST_SUITE_PART( Map_find_int, run_SplitList )
+        CDSUNIT_TEST_SplitList
+        CDSUNIT_TEST_SplitList_nogc
+    CPPUNIT_TEST_SUITE_END_PART()
+} // namespace map2
diff --git a/tests/unit/map2/map_find_int_std.cpp b/tests/unit/map2/map_find_int_std.cpp
new file mode 100644 (file)
index 0000000..bcb759e
--- /dev/null
@@ -0,0 +1,9 @@
+//$$CDS-header$$
+
+#include "map2/map_find_int.h"
+
+namespace map2 {
+    CPPUNIT_TEST_SUITE_PART( Map_find_int, run_StdMap )
+        CDSUNIT_TEST_StdMap
+    CPPUNIT_TEST_SUITE_END_PART()
+} // namespace map2
diff --git a/tests/unit/map2/map_find_int_striped.cpp b/tests/unit/map2/map_find_int_striped.cpp
new file mode 100644 (file)
index 0000000..d93dbf1
--- /dev/null
@@ -0,0 +1,9 @@
+//$$CDS-header$$
+
+#include "map2/map_find_int.h"
+
+namespace map2 {
+    CPPUNIT_TEST_SUITE_PART( Map_find_int, run_StripedMap )
+        CDSUNIT_TEST_StripedMap
+    CPPUNIT_TEST_SUITE_END_PART()
+} // namespace map2
index e1398b9c394bce4e038e9c4499b486870bc6305a..c0629f434e929034987c2ce9e8bf67c9d67ccc8c 100644 (file)
 //$$CDS-header$$
 
-#include "map2/map_types.h"
-#include "cppunit/thread.h"
-
-#include <vector>
+#include "map2/map_find_string.h"
 
 namespace map2 {
+    CPPUNIT_TEST_SUITE_REGISTRATION( Map_find_string );
 
-#   define TEST_MAP(X)         void X() { test<MapTypes<key_type, value_type>::X >()    ; }
-#   define TEST_MAP_NOLF(X)    void X() { test_nolf<MapTypes<key_type, value_type>::X >()    ; }
-#   define TEST_MAP_EXTRACT(X)  TEST_MAP(X)
-#   define TEST_MAP_NOLF_EXTRACT(X) TEST_MAP_NOLF(X)
-
-    namespace {
-        static size_t  c_nThreadCount = 8      ;  // thread count
-        static size_t  c_nMapSize = 20000000   ;  // map size (count of searching item)
-        static size_t  c_nPercentExists = 50   ;  // percent of existing keys in searching sequence
-        static size_t  c_nPassCount = 2;
-        static size_t  c_nMaxLoadFactor = 8    ;  // maximum load factor
-        static bool    c_bPrintGCState = true;
-    }
+    size_t Map_find_string::c_nThreadCount = 8      ;  // thread count
+    size_t Map_find_string::c_nMapSize = 20000000   ;  // map size (count of searching item)
+    size_t Map_find_string::c_nPercentExists = 50   ;  // percent of existing keys in searching sequence
+    size_t Map_find_string::c_nPassCount = 2;
+    size_t Map_find_string::c_nMaxLoadFactor = 8    ;  // maximum load factor
+    bool   Map_find_string::c_bPrintGCState = true;
 
-    class Map_find_string: public CppUnitMini::TestCase
+    void Map_find_string::generateSequence()
     {
-        typedef std::string  key_type;
-        struct value_type {
-            std::string const * pKey;
-            bool        bExists ;   // true - key in map, false - key not in map
-        };
-
-        typedef std::vector<value_type> ValueVector;
-        ValueVector             m_Arr;
-        size_t                  m_nRealMapSize;
-        bool                    m_bSeqInit;
-
-        template <typename Iterator, typename Map>
-        static bool check_result( Iterator const& it, Map const& map )
-        {
-            return it != map.end();
-        }
-        template <typename Map>
-        static bool check_result( bool b, Map const& )
-        {
-            return b;
-        }
-
-        template <class MAP>
-        class TestThread: public CppUnitMini::TestThread
-        {
-            MAP&     m_Map;
-
-            virtual TestThread *    clone()
-            {
-                return new TestThread( *this );
-            }
-        public:
-            struct Stat {
-                size_t      nSuccess;
-                size_t      nFailed;
-
-                Stat()
-                    : nSuccess(0)
-                    , nFailed(0)
-                {}
-            };
-
-            Stat    m_KeyExists;
-            Stat    m_KeyNotExists;
-
-        public:
-            TestThread( CppUnitMini::ThreadPool& pool, MAP& rMap )
-                : CppUnitMini::TestThread( pool )
-                , m_Map( rMap )
-            {}
-            TestThread( TestThread& src )
-                : CppUnitMini::TestThread( src )
-                , m_Map( src.m_Map )
-            {}
-
-            Map_find_string&  getTest()
-            {
-                return reinterpret_cast<Map_find_string&>( m_Pool.m_Test );
-            }
-
-            virtual void init() { cds::threading::Manager::attachThread()   ; }
-            virtual void fini() { cds::threading::Manager::detachThread()   ; }
-
-            virtual void test()
-            {
-                ValueVector& arr = getTest().m_Arr;
-                //size_t nSize = arr.size();
-
-                MAP& rMap = m_Map;
-                for ( size_t nPass = 0; nPass < c_nPassCount; ++nPass ) {
-                    if ( m_nThreadNo & 1 ) {
-                        ValueVector::const_iterator itEnd = arr.end();
-                        for ( ValueVector::const_iterator it = arr.begin(); it != itEnd; ++it ) {
-                            auto bFound = rMap.find( *(it->pKey) );
-                            if ( it->bExists ) {
-                                if ( check_result(bFound, rMap))
-                                    ++m_KeyExists.nSuccess;
-                                else
-                                    ++m_KeyExists.nFailed;
-                            }
-                            else {
-                                if ( check_result(bFound, rMap))
-                                    ++m_KeyNotExists.nFailed;
-                                else
-                                    ++m_KeyNotExists.nSuccess;
-                            }
-                        }
-                    }
-                    else {
-                        ValueVector::const_reverse_iterator itEnd = arr.rend();
-                        for ( ValueVector::const_reverse_iterator it = arr.rbegin(); it != itEnd; ++it ) {
-                            auto bFound = rMap.find( *(it->pKey) );
-                            if ( it->bExists ) {
-                                if ( check_result(bFound, rMap))
-                                    ++m_KeyExists.nSuccess;
-                                else
-                                    ++m_KeyExists.nFailed;
-                            }
-                            else {
-                                if ( check_result( bFound, rMap ))
-                                    ++m_KeyNotExists.nFailed;
-                                else
-                                    ++m_KeyNotExists.nSuccess;
-                            }
-                        }
-                    }
-                }
-            }
-        };
-
-    public:
-        Map_find_string()
-            : m_bSeqInit( false )
-        {}
-
-    protected:
-
-        void generateSequence()
-        {
-            size_t nPercent = c_nPercentExists;
-
-            if ( nPercent > 100 )
-                nPercent = 100;
-            else if ( nPercent < 1 )
-                nPercent = 1;
-
-            m_nRealMapSize = 0;
-
-            std::vector<std::string> const & arrString = CppUnitMini::TestCase::getTestStrings();
-            size_t nSize = arrString.size();
-            if ( nSize > c_nMapSize )
-                nSize = c_nMapSize;
-            m_Arr.resize( nSize );
-            for ( size_t i = 0; i < nSize; ++i ) {
-                m_Arr[i].pKey = &( arrString[i] );
-                m_Arr[i].bExists = CppUnitMini::Rand( 100 ) <= nPercent;
-                if ( m_Arr[i].bExists )
-                    ++m_nRealMapSize;
-            }
+        size_t nPercent = c_nPercentExists;
+
+        if ( nPercent > 100 )
+            nPercent = 100;
+        else if ( nPercent < 1 )
+            nPercent = 1;
+
+        m_nRealMapSize = 0;
+
+        std::vector<std::string> const & arrString = CppUnitMini::TestCase::getTestStrings();
+        size_t nSize = arrString.size();
+        if ( nSize > c_nMapSize )
+            nSize = c_nMapSize;
+        m_Arr.resize( nSize );
+        for ( size_t i = 0; i < nSize; ++i ) {
+            m_Arr[i].pKey = &( arrString[i] );
+            m_Arr[i].bExists = CppUnitMini::Rand( 100 ) <= nPercent;
+            if ( m_Arr[i].bExists )
+                ++m_nRealMapSize;
         }
+    }
 
+    void Map_find_string::initTestSequence()
+    {
+        if ( !m_bSeqInit ) {
+            m_bSeqInit = true;
 
-        template <class MAP>
-        void find_string_test( MAP& testMap )
-        {
-            typedef TestThread<MAP>     Thread;
+            CPPUNIT_MSG( "Generating test data...");
             cds::OS::Timer    timer;
-
-            // Fill the map
-            CPPUNIT_MSG( "  Fill map...");
-            timer.reset();
-            for ( size_t i = 0; i < m_Arr.size(); ++i ) {
-                // All keys in arrData are unique, insert() must be successful
-                if ( m_Arr[i].bExists )
-                    CPPUNIT_ASSERT( check_result( testMap.insert( *(m_Arr[i].pKey), m_Arr[i] ), testMap ));
-            }
+            generateSequence();
             CPPUNIT_MSG( "   Duration=" << timer.duration() );
-
-            CPPUNIT_MSG( "  Searching...");
-            CppUnitMini::ThreadPool pool( *this );
-            pool.add( new Thread( pool, testMap ), c_nThreadCount );
-            pool.run();
-            CPPUNIT_MSG( "   Duration=" << pool.avgDuration() );
-
-            // Postcondition: the number of success searching == the number of map item
-            for ( CppUnitMini::ThreadPool::iterator it = pool.begin(); it != pool.end(); ++it ) {
-                Thread * pThread = static_cast<Thread *>( *it );
-                CPPUNIT_CHECK( pThread->m_KeyExists.nSuccess == m_nRealMapSize * c_nPassCount );
-                CPPUNIT_CHECK( pThread->m_KeyExists.nFailed == 0 );
-                CPPUNIT_CHECK( pThread->m_KeyNotExists.nSuccess == (m_Arr.size() - m_nRealMapSize) * c_nPassCount );
-                CPPUNIT_CHECK( pThread->m_KeyNotExists.nFailed == 0 );
-            }
-
-            check_before_cleanup( testMap );
-
-            testMap.clear();
-            additional_check( testMap );
-            print_stat( testMap );
-            additional_cleanup( testMap );
-        }
-
-        void initTestSequence()
-        {
-            if ( !m_bSeqInit ) {
-                m_bSeqInit = true;
-
-                CPPUNIT_MSG( "Generating test data...");
-                cds::OS::Timer    timer;
-                generateSequence();
-                CPPUNIT_MSG( "   Duration=" << timer.duration() );
-                CPPUNIT_MSG( "Map size=" << m_nRealMapSize << " find key loop=" << m_Arr.size() << " (" << c_nPercentExists << "% success)" );
-                CPPUNIT_MSG( "Thread count=" << c_nThreadCount << " Pass count=" << c_nPassCount );
-            }
-        }
-
-        template <class MAP>
-        void test()
-        {
-            initTestSequence();
-
-            for ( size_t nLoadFactor = 1; nLoadFactor <= c_nMaxLoadFactor; nLoadFactor *= 2 ) {
-                CPPUNIT_MSG( "Load factor=" << nLoadFactor );
-                MAP  testMap( m_Arr.size(), nLoadFactor );
-                find_string_test( testMap );
-                if ( c_bPrintGCState )
-                    print_gc_state();
-            }
-        }
-
-        template <class MAP>
-        void test_nolf()
-        {
-            initTestSequence();
-
-            MAP testMap;
-            find_string_test( testMap );
-            if ( c_bPrintGCState )
-                print_gc_state();
-        }
-
-        void setUpParams( const CppUnitMini::TestCfg& cfg ) {
-            c_nThreadCount = cfg.getULong("ThreadCount", 8 )        ; // thread count
-            c_nMapSize = cfg.getULong("MapSize", 20000000 )         ;  // map size (count of searching item)
-            c_nPercentExists = cfg.getULong("PercentExists", 50 )   ;  // percent of existing keys in searching sequence
-            c_nPassCount = cfg.getULong("PassCount", 2 );
-            c_nMaxLoadFactor = cfg.getULong("MaxLoadFactor", 8 );
-            c_bPrintGCState = cfg.getBool("PrintGCStateFlag", true );
+            CPPUNIT_MSG( "Map size=" << m_nRealMapSize << " find key loop=" << m_Arr.size() << " (" << c_nPercentExists << "% success)" );
+            CPPUNIT_MSG( "Thread count=" << c_nThreadCount << " Pass count=" << c_nPassCount );
         }
+    }
 
-#   include "map2/map_defs.h"
-        CDSUNIT_DECLARE_MichaelMap
-        CDSUNIT_DECLARE_MichaelMap_nogc
-        CDSUNIT_DECLARE_SplitList
-        CDSUNIT_DECLARE_SplitList_nogc
-        CDSUNIT_DECLARE_SkipListMap
-        CDSUNIT_DECLARE_SkipListMap_nogc
-        CDSUNIT_DECLARE_EllenBinTreeMap
-        CDSUNIT_DECLARE_BronsonAVLTreeMap
-        CDSUNIT_DECLARE_StripedMap
-        CDSUNIT_DECLARE_RefinableMap
-        CDSUNIT_DECLARE_CuckooMap
-        CDSUNIT_DECLARE_StdMap
-
-        CPPUNIT_TEST_SUITE( Map_find_string )
-            CDSUNIT_TEST_MichaelMap
-            CDSUNIT_TEST_MichaelMap_nogc
-            CDSUNIT_TEST_SplitList
-            CDSUNIT_TEST_SplitList_nogc
-            CDSUNIT_TEST_SkipListMap
-            CDSUNIT_TEST_SkipListMap_nogc
-            CDSUNIT_TEST_EllenBinTreeMap
-            CDSUNIT_TEST_BronsonAVLTreeMap
-            CDSUNIT_TEST_StripedMap
-            CDSUNIT_TEST_RefinableMap
-            CDSUNIT_TEST_CuckooMap
-            CDSUNIT_TEST_StdMap
-        CPPUNIT_TEST_SUITE_END()
-
-    };
+    void Map_find_string::setUpParams( const CppUnitMini::TestCfg& cfg )
+    {
+        c_nThreadCount = cfg.getSizeT("ThreadCount", c_nThreadCount );
+        c_nMapSize = cfg.getSizeT("MapSize", c_nMapSize );
+        c_nPercentExists = cfg.getSizeT("PercentExists", c_nPercentExists );
+        c_nPassCount = cfg.getSizeT("PassCount", c_nPassCount );
+        c_nMaxLoadFactor = cfg.getSizeT("MaxLoadFactor", c_nMaxLoadFactor );
+        c_bPrintGCState = cfg.getBool("PrintGCStateFlag", true );
+    }
 
-    CPPUNIT_TEST_SUITE_REGISTRATION( Map_find_string );
+    void Map_find_string::myRun(const char *in_name, bool invert /*= false*/)
+    {
+        setUpParams( m_Cfg.get( "Map_find_string" ));
+
+        run_MichaelMap(in_name, invert);
+        run_SplitList(in_name, invert);
+        run_SkipListMap(in_name, invert);
+        run_EllenBinTreeMap(in_name, invert);
+        run_BronsonAVLTreeMap(in_name, invert);
+        run_StripedMap(in_name, invert);
+        run_RefinableMap(in_name, invert);
+        run_CuckooMap(in_name, invert);
+        run_StdMap(in_name, invert);
+
+        endTestCase();
+    }
 } // namespace map2
diff --git a/tests/unit/map2/map_find_string.h b/tests/unit/map2/map_find_string.h
new file mode 100644 (file)
index 0000000..8796698
--- /dev/null
@@ -0,0 +1,239 @@
+//$$CDS-header$$
+
+#include "map2/map_types.h"
+#include "cppunit/thread.h"
+
+#include <vector>
+
+namespace map2 {
+
+#   define TEST_MAP(X)         void X() { test<MapTypes<key_type, value_type>::X >()    ; }
+#   define TEST_MAP_NOLF(X)    void X() { test_nolf<MapTypes<key_type, value_type>::X >()    ; }
+#   define TEST_MAP_EXTRACT(X)  TEST_MAP(X)
+#   define TEST_MAP_NOLF_EXTRACT(X) TEST_MAP_NOLF(X)
+
+    class Map_find_string: public CppUnitMini::TestCase
+    {
+        static size_t  c_nThreadCount;      // thread count
+        static size_t  c_nMapSize;          // map size (count of searching item)
+        static size_t  c_nPercentExists;    // percent of existing keys in searching sequence
+        static size_t  c_nPassCount;
+        static size_t  c_nMaxLoadFactor;    // maximum load factor
+        static bool    c_bPrintGCState;
+
+        typedef CppUnitMini::TestCase Base;
+        typedef std::string  key_type;
+        struct value_type {
+            std::string const * pKey;
+            bool        bExists ;   // true - key in map, false - key not in map
+        };
+
+        typedef std::vector<value_type> ValueVector;
+        ValueVector             m_Arr;
+        size_t                  m_nRealMapSize;
+        bool                    m_bSeqInit;
+
+        template <typename Iterator, typename Map>
+        static bool check_result( Iterator const& it, Map const& map )
+        {
+            return it != map.end();
+        }
+        template <typename Map>
+        static bool check_result( bool b, Map const& )
+        {
+            return b;
+        }
+
+        template <class MAP>
+        class TestThread: public CppUnitMini::TestThread
+        {
+            MAP&     m_Map;
+
+            virtual TestThread *    clone()
+            {
+                return new TestThread( *this );
+            }
+        public:
+            struct Stat {
+                size_t      nSuccess;
+                size_t      nFailed;
+
+                Stat()
+                    : nSuccess(0)
+                    , nFailed(0)
+                {}
+            };
+
+            Stat    m_KeyExists;
+            Stat    m_KeyNotExists;
+
+        public:
+            TestThread( CppUnitMini::ThreadPool& pool, MAP& rMap )
+                : CppUnitMini::TestThread( pool )
+                , m_Map( rMap )
+            {}
+            TestThread( TestThread& src )
+                : CppUnitMini::TestThread( src )
+                , m_Map( src.m_Map )
+            {}
+
+            Map_find_string&  getTest()
+            {
+                return reinterpret_cast<Map_find_string&>( m_Pool.m_Test );
+            }
+
+            virtual void init() { cds::threading::Manager::attachThread()   ; }
+            virtual void fini() { cds::threading::Manager::detachThread()   ; }
+
+            virtual void test()
+            {
+                ValueVector& arr = getTest().m_Arr;
+                //size_t nSize = arr.size();
+
+                MAP& rMap = m_Map;
+                for ( size_t nPass = 0; nPass < c_nPassCount; ++nPass ) {
+                    if ( m_nThreadNo & 1 ) {
+                        ValueVector::const_iterator itEnd = arr.end();
+                        for ( ValueVector::const_iterator it = arr.begin(); it != itEnd; ++it ) {
+                            auto bFound = rMap.find( *(it->pKey) );
+                            if ( it->bExists ) {
+                                if ( check_result(bFound, rMap))
+                                    ++m_KeyExists.nSuccess;
+                                else
+                                    ++m_KeyExists.nFailed;
+                            }
+                            else {
+                                if ( check_result(bFound, rMap))
+                                    ++m_KeyNotExists.nFailed;
+                                else
+                                    ++m_KeyNotExists.nSuccess;
+                            }
+                        }
+                    }
+                    else {
+                        ValueVector::const_reverse_iterator itEnd = arr.rend();
+                        for ( ValueVector::const_reverse_iterator it = arr.rbegin(); it != itEnd; ++it ) {
+                            auto bFound = rMap.find( *(it->pKey) );
+                            if ( it->bExists ) {
+                                if ( check_result(bFound, rMap))
+                                    ++m_KeyExists.nSuccess;
+                                else
+                                    ++m_KeyExists.nFailed;
+                            }
+                            else {
+                                if ( check_result( bFound, rMap ))
+                                    ++m_KeyNotExists.nFailed;
+                                else
+                                    ++m_KeyNotExists.nSuccess;
+                            }
+                        }
+                    }
+                }
+            }
+        };
+
+    public:
+        Map_find_string()
+            : m_bSeqInit( false )
+        {}
+
+    protected:
+
+        void generateSequence();
+
+        template <class MAP>
+        void find_string_test( MAP& testMap )
+        {
+            typedef TestThread<MAP>     Thread;
+            cds::OS::Timer    timer;
+
+            // Fill the map
+            CPPUNIT_MSG( "  Fill map...");
+            timer.reset();
+            for ( size_t i = 0; i < m_Arr.size(); ++i ) {
+                // All keys in arrData are unique, insert() must be successful
+                if ( m_Arr[i].bExists )
+                    CPPUNIT_ASSERT( check_result( testMap.insert( *(m_Arr[i].pKey), m_Arr[i] ), testMap ));
+            }
+            CPPUNIT_MSG( "   Duration=" << timer.duration() );
+
+            CPPUNIT_MSG( "  Searching...");
+            CppUnitMini::ThreadPool pool( *this );
+            pool.add( new Thread( pool, testMap ), c_nThreadCount );
+            pool.run();
+            CPPUNIT_MSG( "   Duration=" << pool.avgDuration() );
+
+            // Postcondition: the number of success searching == the number of map item
+            for ( CppUnitMini::ThreadPool::iterator it = pool.begin(); it != pool.end(); ++it ) {
+                Thread * pThread = static_cast<Thread *>( *it );
+                CPPUNIT_CHECK( pThread->m_KeyExists.nSuccess == m_nRealMapSize * c_nPassCount );
+                CPPUNIT_CHECK( pThread->m_KeyExists.nFailed == 0 );
+                CPPUNIT_CHECK( pThread->m_KeyNotExists.nSuccess == (m_Arr.size() - m_nRealMapSize) * c_nPassCount );
+                CPPUNIT_CHECK( pThread->m_KeyNotExists.nFailed == 0 );
+            }
+
+            check_before_cleanup( testMap );
+
+            testMap.clear();
+            additional_check( testMap );
+            print_stat( testMap );
+            additional_cleanup( testMap );
+        }
+
+        void initTestSequence();
+
+        template <class MAP>
+        void test()
+        {
+            initTestSequence();
+
+            for ( size_t nLoadFactor = 1; nLoadFactor <= c_nMaxLoadFactor; nLoadFactor *= 2 ) {
+                CPPUNIT_MSG( "Load factor=" << nLoadFactor );
+                MAP  testMap( m_Arr.size(), nLoadFactor );
+                find_string_test( testMap );
+                if ( c_bPrintGCState )
+                    print_gc_state();
+            }
+        }
+
+        template <class MAP>
+        void test_nolf()
+        {
+            initTestSequence();
+
+            MAP testMap;
+            find_string_test( testMap );
+            if ( c_bPrintGCState )
+                print_gc_state();
+        }
+
+        void setUpParams( const CppUnitMini::TestCfg& cfg );
+
+        void run_MichaelMap(const char *in_name, bool invert = false);
+        void run_SplitList(const char *in_name, bool invert = false);
+        void run_StripedMap(const char *in_name, bool invert = false);
+        void run_RefinableMap(const char *in_name, bool invert = false);
+        void run_CuckooMap(const char *in_name, bool invert = false);
+        void run_SkipListMap(const char *in_name, bool invert = false);
+        void run_EllenBinTreeMap(const char *in_name, bool invert = false);
+        void run_BronsonAVLTreeMap(const char *in_name, bool invert = false);
+        void run_StdMap(const char *in_name, bool invert = false);
+
+        virtual void myRun(const char *in_name, bool invert = false);
+
+
+#   include "map2/map_defs.h"
+        CDSUNIT_DECLARE_MichaelMap
+        CDSUNIT_DECLARE_MichaelMap_nogc
+        CDSUNIT_DECLARE_SplitList
+        CDSUNIT_DECLARE_SplitList_nogc
+        CDSUNIT_DECLARE_SkipListMap
+        CDSUNIT_DECLARE_SkipListMap_nogc
+        CDSUNIT_DECLARE_EllenBinTreeMap
+        CDSUNIT_DECLARE_BronsonAVLTreeMap
+        CDSUNIT_DECLARE_StripedMap
+        CDSUNIT_DECLARE_RefinableMap
+        CDSUNIT_DECLARE_CuckooMap
+        CDSUNIT_DECLARE_StdMap
+    };
+} // namespace map2
diff --git a/tests/unit/map2/map_find_string_bronsonavltree.cpp b/tests/unit/map2/map_find_string_bronsonavltree.cpp
new file mode 100644 (file)
index 0000000..b74d017
--- /dev/null
@@ -0,0 +1,9 @@
+//$$CDS-header$$
+
+#include "map2/map_find_string.h"
+
+namespace map2 {
+    CPPUNIT_TEST_SUITE_PART( Map_find_string, run_BronsonAVLTreeMap )
+        CDSUNIT_TEST_BronsonAVLTreeMap
+    CPPUNIT_TEST_SUITE_END_PART()
+} // namespace map2
diff --git a/tests/unit/map2/map_find_string_cuckoo.cpp b/tests/unit/map2/map_find_string_cuckoo.cpp
new file mode 100644 (file)
index 0000000..c508512
--- /dev/null
@@ -0,0 +1,9 @@
+//$$CDS-header$$
+
+#include "map2/map_find_string.h"
+
+namespace map2 {
+    CPPUNIT_TEST_SUITE_PART( Map_find_string, run_CuckooMap )
+        CDSUNIT_TEST_CuckooMap
+    CPPUNIT_TEST_SUITE_END_PART()
+} // namespace map2
diff --git a/tests/unit/map2/map_find_string_ellentree.cpp b/tests/unit/map2/map_find_string_ellentree.cpp
new file mode 100644 (file)
index 0000000..9539c7d
--- /dev/null
@@ -0,0 +1,9 @@
+//$$CDS-header$$
+
+#include "map2/map_find_string.h"
+
+namespace map2 {
+    CPPUNIT_TEST_SUITE_PART( Map_find_string, run_EllenBinTreeMap )
+        CDSUNIT_TEST_EllenBinTreeMap
+    CPPUNIT_TEST_SUITE_END_PART()
+} // namespace map2
diff --git a/tests/unit/map2/map_find_string_michael.cpp b/tests/unit/map2/map_find_string_michael.cpp
new file mode 100644 (file)
index 0000000..5e9f61b
--- /dev/null
@@ -0,0 +1,10 @@
+//$$CDS-header$$
+
+#include "map2/map_find_string.h"
+
+namespace map2 {
+    CPPUNIT_TEST_SUITE_PART( Map_find_string, run_MichaelMap )
+        CDSUNIT_TEST_MichaelMap
+        CDSUNIT_TEST_MichaelMap_nogc
+    CPPUNIT_TEST_SUITE_END_PART()
+} // namespace map2
diff --git a/tests/unit/map2/map_find_string_refinable.cpp b/tests/unit/map2/map_find_string_refinable.cpp
new file mode 100644 (file)
index 0000000..dd9a91f
--- /dev/null
@@ -0,0 +1,9 @@
+//$$CDS-header$$
+
+#include "map2/map_find_string.h"
+
+namespace map2 {
+    CPPUNIT_TEST_SUITE_PART( Map_find_string, run_RefinableMap )
+        CDSUNIT_TEST_RefinableMap
+    CPPUNIT_TEST_SUITE_END_PART()
+} // namespace map2
diff --git a/tests/unit/map2/map_find_string_skip.cpp b/tests/unit/map2/map_find_string_skip.cpp
new file mode 100644 (file)
index 0000000..47671c1
--- /dev/null
@@ -0,0 +1,10 @@
+//$$CDS-header$$
+
+#include "map2/map_find_string.h"
+
+namespace map2 {
+    CPPUNIT_TEST_SUITE_PART( Map_find_string, run_SkipListMap )
+        CDSUNIT_TEST_SkipListMap
+        CDSUNIT_TEST_SkipListMap_nogc
+    CPPUNIT_TEST_SUITE_END_PART()
+} // namespace map2
diff --git a/tests/unit/map2/map_find_string_split.cpp b/tests/unit/map2/map_find_string_split.cpp
new file mode 100644 (file)
index 0000000..d2095b1
--- /dev/null
@@ -0,0 +1,10 @@
+//$$CDS-header$$
+
+#include "map2/map_find_string.h"
+
+namespace map2 {
+    CPPUNIT_TEST_SUITE_PART( Map_find_string, run_SplitList )
+        CDSUNIT_TEST_SplitList
+        CDSUNIT_TEST_SplitList_nogc
+    CPPUNIT_TEST_SUITE_END_PART()
+} // namespace map2
diff --git a/tests/unit/map2/map_find_string_std.cpp b/tests/unit/map2/map_find_string_std.cpp
new file mode 100644 (file)
index 0000000..d268977
--- /dev/null
@@ -0,0 +1,9 @@
+//$$CDS-header$$
+
+#include "map2/map_find_string.h"
+
+namespace map2 {
+    CPPUNIT_TEST_SUITE_PART( Map_find_string, run_StdMap )
+        CDSUNIT_TEST_StdMap
+    CPPUNIT_TEST_SUITE_END_PART()
+} // namespace map2
diff --git a/tests/unit/map2/map_find_string_striped.cpp b/tests/unit/map2/map_find_string_striped.cpp
new file mode 100644 (file)
index 0000000..1d8280b
--- /dev/null
@@ -0,0 +1,9 @@
+//$$CDS-header$$
+
+#include "map2/map_find_string.h"
+
+namespace map2 {
+    CPPUNIT_TEST_SUITE_PART( Map_find_string, run_StripedMap )
+        CDSUNIT_TEST_StripedMap
+    CPPUNIT_TEST_SUITE_END_PART()
+} // namespace map2
index 6232125a1ac649af88bfdd0a6578d5bd8b278261..6898d390020390401b4db7df633b36b528e45050 100644 (file)
@@ -46,8 +46,4 @@ namespace map2 {
 
         endTestCase();
     }
-
-    CPPUNIT_TEST_SUITE_PART( Map_InsDel_func, run_MichaelMap )
-        CDSUNIT_TEST_MichaelMap
-    CPPUNIT_TEST_SUITE_END_PART()
 } // namespace map2
diff --git a/tests/unit/map2/map_insdel_func2.cpp b/tests/unit/map2/map_insdel_func2.cpp
deleted file mode 100644 (file)
index da1c3fa..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-//$$CDS-header$$
-
-#include "map2/map_insdel_func.h"
-
-namespace map2 {
-    CPPUNIT_TEST_SUITE_PART( Map_InsDel_func, run_SplitList )
-        CDSUNIT_TEST_SplitList
-    CPPUNIT_TEST_SUITE_END_PART()
-} // namespace map2
-
diff --git a/tests/unit/map2/map_insdel_func3.cpp b/tests/unit/map2/map_insdel_func3.cpp
deleted file mode 100644 (file)
index 9cec610..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-//$$CDS-header$$
-
-#include "map2/map_insdel_func.h"
-
-namespace map2 {
-    CPPUNIT_TEST_SUITE_PART( Map_InsDel_func, run_SkipListMap )
-        CDSUNIT_TEST_SkipListMap
-    CPPUNIT_TEST_SUITE_END_PART()
-} // namespace map2
-
diff --git a/tests/unit/map2/map_insdel_func4.cpp b/tests/unit/map2/map_insdel_func4.cpp
deleted file mode 100644 (file)
index 1533d35..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-//$$CDS-header$$
-
-#include "map2/map_insdel_func.h"
-
-namespace map2 {
-    CPPUNIT_TEST_SUITE_PART( Map_InsDel_func, run_EllenBinTreeMap )
-        CDSUNIT_TEST_EllenBinTreeMap
-    CPPUNIT_TEST_SUITE_END_PART()
-} // namespace map2
-
diff --git a/tests/unit/map2/map_insdel_func5.cpp b/tests/unit/map2/map_insdel_func5.cpp
deleted file mode 100644 (file)
index 30d277d..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-//$$CDS-header$$
-
-#include "map2/map_insdel_func.h"
-
-namespace map2 {
-    CPPUNIT_TEST_SUITE_PART( Map_InsDel_func, run_BronsonAVLTreeMap )
-        CDSUNIT_TEST_BronsonAVLTreeMap
-    CPPUNIT_TEST_SUITE_END_PART()
-} // namespace map2
diff --git a/tests/unit/map2/map_insdel_func6.cpp b/tests/unit/map2/map_insdel_func6.cpp
deleted file mode 100644 (file)
index f684118..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-//$$CDS-header$$
-
-#include "map2/map_insdel_func.h"
-
-namespace map2 {
-    CPPUNIT_TEST_SUITE_PART( Map_InsDel_func, run_StripedMap )
-        CDSUNIT_TEST_StripedMap
-    CPPUNIT_TEST_SUITE_END_PART()
-} // namespace map2
diff --git a/tests/unit/map2/map_insdel_func7.cpp b/tests/unit/map2/map_insdel_func7.cpp
deleted file mode 100644 (file)
index 10fdfad..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-//$$CDS-header$$
-
-#include "map2/map_insdel_func.h"
-
-namespace map2 {
-    CPPUNIT_TEST_SUITE_PART( Map_InsDel_func, run_RefinableMap )
-        CDSUNIT_TEST_RefinableMap
-    CPPUNIT_TEST_SUITE_END_PART()
-} // namespace map2
diff --git a/tests/unit/map2/map_insdel_func8.cpp b/tests/unit/map2/map_insdel_func8.cpp
deleted file mode 100644 (file)
index b890195..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-//$$CDS-header$$
-
-#include "map2/map_insdel_func.h"
-
-namespace map2 {
-    CPPUNIT_TEST_SUITE_PART( Map_InsDel_func, run_CuckooMap )
-        CDSUNIT_TEST_CuckooMap
-    CPPUNIT_TEST_SUITE_END_PART()
-} // namespace map2
diff --git a/tests/unit/map2/map_insdel_func_bronsonavltree.cpp b/tests/unit/map2/map_insdel_func_bronsonavltree.cpp
new file mode 100644 (file)
index 0000000..30d277d
--- /dev/null
@@ -0,0 +1,9 @@
+//$$CDS-header$$
+
+#include "map2/map_insdel_func.h"
+
+namespace map2 {
+    CPPUNIT_TEST_SUITE_PART( Map_InsDel_func, run_BronsonAVLTreeMap )
+        CDSUNIT_TEST_BronsonAVLTreeMap
+    CPPUNIT_TEST_SUITE_END_PART()
+} // namespace map2
diff --git a/tests/unit/map2/map_insdel_func_cuckoo.cpp b/tests/unit/map2/map_insdel_func_cuckoo.cpp
new file mode 100644 (file)
index 0000000..b890195
--- /dev/null
@@ -0,0 +1,9 @@
+//$$CDS-header$$
+
+#include "map2/map_insdel_func.h"
+
+namespace map2 {
+    CPPUNIT_TEST_SUITE_PART( Map_InsDel_func, run_CuckooMap )
+        CDSUNIT_TEST_CuckooMap
+    CPPUNIT_TEST_SUITE_END_PART()
+} // namespace map2
diff --git a/tests/unit/map2/map_insdel_func_ellentree.cpp b/tests/unit/map2/map_insdel_func_ellentree.cpp
new file mode 100644 (file)
index 0000000..1533d35
--- /dev/null
@@ -0,0 +1,10 @@
+//$$CDS-header$$
+
+#include "map2/map_insdel_func.h"
+
+namespace map2 {
+    CPPUNIT_TEST_SUITE_PART( Map_InsDel_func, run_EllenBinTreeMap )
+        CDSUNIT_TEST_EllenBinTreeMap
+    CPPUNIT_TEST_SUITE_END_PART()
+} // namespace map2
+
diff --git a/tests/unit/map2/map_insdel_func_michael.cpp b/tests/unit/map2/map_insdel_func_michael.cpp
new file mode 100644 (file)
index 0000000..41e1a7c
--- /dev/null
@@ -0,0 +1,9 @@
+//$$CDS-header$$
+
+#include "map2/map_insdel_func.h"
+
+namespace map2 {
+    CPPUNIT_TEST_SUITE_PART( Map_InsDel_func, run_MichaelMap )
+        CDSUNIT_TEST_MichaelMap
+    CPPUNIT_TEST_SUITE_END_PART()
+} // namespace map2
diff --git a/tests/unit/map2/map_insdel_func_refinable.cpp b/tests/unit/map2/map_insdel_func_refinable.cpp
new file mode 100644 (file)
index 0000000..10fdfad
--- /dev/null
@@ -0,0 +1,9 @@
+//$$CDS-header$$
+
+#include "map2/map_insdel_func.h"
+
+namespace map2 {
+    CPPUNIT_TEST_SUITE_PART( Map_InsDel_func, run_RefinableMap )
+        CDSUNIT_TEST_RefinableMap
+    CPPUNIT_TEST_SUITE_END_PART()
+} // namespace map2
diff --git a/tests/unit/map2/map_insdel_func_skip.cpp b/tests/unit/map2/map_insdel_func_skip.cpp
new file mode 100644 (file)
index 0000000..9cec610
--- /dev/null
@@ -0,0 +1,10 @@
+//$$CDS-header$$
+
+#include "map2/map_insdel_func.h"
+
+namespace map2 {
+    CPPUNIT_TEST_SUITE_PART( Map_InsDel_func, run_SkipListMap )
+        CDSUNIT_TEST_SkipListMap
+    CPPUNIT_TEST_SUITE_END_PART()
+} // namespace map2
+
diff --git a/tests/unit/map2/map_insdel_func_split.cpp b/tests/unit/map2/map_insdel_func_split.cpp
new file mode 100644 (file)
index 0000000..da1c3fa
--- /dev/null
@@ -0,0 +1,10 @@
+//$$CDS-header$$
+
+#include "map2/map_insdel_func.h"
+
+namespace map2 {
+    CPPUNIT_TEST_SUITE_PART( Map_InsDel_func, run_SplitList )
+        CDSUNIT_TEST_SplitList
+    CPPUNIT_TEST_SUITE_END_PART()
+} // namespace map2
+
diff --git a/tests/unit/map2/map_insdel_func_striped.cpp b/tests/unit/map2/map_insdel_func_striped.cpp
new file mode 100644 (file)
index 0000000..f684118
--- /dev/null
@@ -0,0 +1,9 @@
+//$$CDS-header$$
+
+#include "map2/map_insdel_func.h"
+
+namespace map2 {
+    CPPUNIT_TEST_SUITE_PART( Map_InsDel_func, run_StripedMap )
+        CDSUNIT_TEST_StripedMap
+    CPPUNIT_TEST_SUITE_END_PART()
+} // namespace map2
index a6ecc14989d77d6e1848a620f113fd8f4ed3b459..42e053cf1c86d4b87f5020a9bfbfd22b7effd66c 100644 (file)
 //$$CDS-header$$
 
-#include "map2/map_types.h"
-#include "cppunit/thread.h"
-
-#include <vector>
+#include "map2/map_insdel_int.h"
 
 namespace map2 {
+    CPPUNIT_TEST_SUITE_REGISTRATION( Map_InsDel_int );
 
-#   define TEST_MAP(X)         void X() { test<MapTypes<key_type, value_type>::X >()    ; }
-#   define TEST_MAP_EXTRACT(X)  TEST_MAP(X)
-#   define TEST_MAP_NOLF(X)    void X() { test_nolf<MapTypes<key_type, value_type>::X >()    ; }
-#   define TEST_MAP_NOLF_EXTRACT(X) TEST_MAP_NOLF(X)
-
-    namespace {
-        static size_t  c_nMapSize = 1000000    ;  // map size
-        static size_t  c_nInsertThreadCount = 4;  // count of insertion thread
-        static size_t  c_nDeleteThreadCount = 4;  // count of deletion thread
-        static size_t  c_nThreadPassCount = 4  ;  // pass count for each thread
-        static size_t  c_nMaxLoadFactor = 8    ;  // maximum load factor
-        static bool    c_bPrintGCState = true;
+    size_t Map_InsDel_int::c_nMapSize = 1000000;
+    size_t Map_InsDel_int::c_nInsertThreadCount = 4;
+    size_t Map_InsDel_int::c_nDeleteThreadCount = 4;
+    size_t Map_InsDel_int::c_nThreadPassCount = 4;
+    size_t Map_InsDel_int::c_nMaxLoadFactor = 8;
+    bool   Map_InsDel_int::c_bPrintGCState = true;
+
+
+    void Map_InsDel_int::setUpParams( const CppUnitMini::TestCfg& cfg ) {
+        c_nInsertThreadCount = cfg.getSizeT("InsertThreadCount", c_nInsertThreadCount );
+        c_nDeleteThreadCount = cfg.getSizeT("DeleteThreadCount", c_nDeleteThreadCount );
+        c_nThreadPassCount = cfg.getSizeT("ThreadPassCount", c_nThreadPassCount );
+        c_nMapSize = cfg.getSizeT("MapSize", c_nMapSize );
+        c_nMaxLoadFactor = cfg.getSizeT("MaxLoadFactor", c_nMaxLoadFactor );
+        c_bPrintGCState = cfg.getBool("PrintGCStateFlag", c_bPrintGCState );
     }
 
-    class Map_InsDel_int: public CppUnitMini::TestCase
+    void Map_InsDel_int::myRun(const char *in_name, bool invert /*= false*/)
     {
-        typedef size_t  key_type;
-        typedef size_t  value_type;
-
-        typedef std::vector<key_type>   key_array;
-        key_array                       m_arrValues;
-
-        template <class MAP>
-        class Inserter: public CppUnitMini::TestThread
-        {
-            MAP&     m_Map;
-
-            virtual Inserter *    clone()
-            {
-                return new Inserter( *this );
-            }
-        public:
-            size_t  m_nInsertSuccess;
-            size_t  m_nInsertFailed;
-
-        public:
-            Inserter( CppUnitMini::ThreadPool& pool, MAP& rMap )
-                : CppUnitMini::TestThread( pool )
-                , m_Map( rMap )
-            {}
-            Inserter( Inserter& src )
-                : CppUnitMini::TestThread( src )
-                , m_Map( src.m_Map )
-            {}
-
-            Map_InsDel_int&  getTest()
-            {
-                return reinterpret_cast<Map_InsDel_int&>( m_Pool.m_Test );
-            }
-
-            virtual void init() { cds::threading::Manager::attachThread()   ; }
-            virtual void fini() { cds::threading::Manager::detachThread()   ; }
-
-            virtual void test()
-            {
-                MAP& rMap = m_Map;
-
-                m_nInsertSuccess =
-                    m_nInsertFailed = 0;
-                key_array const& arr = getTest().m_arrValues;
-
-                if ( m_nThreadNo & 1 ) {
-                    for ( size_t nPass = 0; nPass < c_nThreadPassCount; ++nPass ) {
-                        for ( key_array::const_iterator it = arr.begin(), itEnd = arr.end(); it != itEnd; ++it ) {
-                            if ( rMap.insert( *it, *it * 8 ) )
-                                ++m_nInsertSuccess;
-                            else
-                                ++m_nInsertFailed;
-                        }
-                    }
-                }
-                else {
-                    for ( size_t nPass = 0; nPass < c_nThreadPassCount; ++nPass ) {
-                        for ( key_array::const_reverse_iterator it = arr.rbegin(), itEnd = arr.rend(); it != itEnd; ++it ) {
-                            if ( rMap.insert( *it, *it * 8 ) )
-                                ++m_nInsertSuccess;
-                            else
-                                ++m_nInsertFailed;
-                        }
-                    }
-                }
-            }
-        };
-
-        template <class MAP>
-        class Deleter: public CppUnitMini::TestThread
-        {
-            MAP&     m_Map;
-
-            virtual Deleter *    clone()
-            {
-                return new Deleter( *this );
-            }
-        public:
-            size_t  m_nDeleteSuccess;
-            size_t  m_nDeleteFailed;
-
-        public:
-            Deleter( CppUnitMini::ThreadPool& pool, MAP& rMap )
-                : CppUnitMini::TestThread( pool )
-                , m_Map( rMap )
-            {}
-            Deleter( Deleter& src )
-                : CppUnitMini::TestThread( src )
-                , m_Map( src.m_Map )
-            {}
-
-            Map_InsDel_int&  getTest()
-            {
-                return reinterpret_cast<Map_InsDel_int&>( m_Pool.m_Test );
-            }
-
-            virtual void init() { cds::threading::Manager::attachThread()   ; }
-            virtual void fini() { cds::threading::Manager::detachThread()   ; }
-
-            virtual void test()
-            {
-                MAP& rMap = m_Map;
-
-                m_nDeleteSuccess =
-                    m_nDeleteFailed = 0;
-                key_array const& arr = getTest().m_arrValues;
-
-                if ( m_nThreadNo & 1 ) {
-                    for ( size_t nPass = 0; nPass < c_nThreadPassCount; ++nPass ) {
-                        for ( key_array::const_iterator it = arr.begin(), itEnd = arr.end(); it != itEnd; ++it ) {
-                            if ( rMap.erase( *it ) )
-                                ++m_nDeleteSuccess;
-                            else
-                                ++m_nDeleteFailed;
-                        }
-                    }
-                }
-                else {
-                    for ( size_t nPass = 0; nPass < c_nThreadPassCount; ++nPass ) {
-                        for ( key_array::const_reverse_iterator it = arr.rbegin(), itEnd = arr.rend(); it != itEnd; ++it ) {
-                            if ( rMap.erase( *it ) )
-                                ++m_nDeleteSuccess;
-                            else
-                                ++m_nDeleteFailed;
-                        }
-                    }
-                }
-            }
-        };
-
-    protected:
-        template <class MAP>
-        void do_test( MAP& testMap )
-        {
-            typedef Inserter<MAP>       InserterThread;
-            typedef Deleter<MAP>        DeleterThread;
-            cds::OS::Timer    timer;
-
-            m_arrValues.clear();
-            m_arrValues.reserve( c_nMapSize );
-            for ( size_t i = 0; i < c_nMapSize; ++i )
-                m_arrValues.push_back( i );
-            std::random_shuffle( m_arrValues.begin(), m_arrValues.end() );
-
-            CppUnitMini::ThreadPool pool( *this );
-            pool.add( new InserterThread( pool, testMap ), c_nInsertThreadCount );
-            pool.add( new DeleterThread( pool, testMap ), c_nDeleteThreadCount );
-            pool.run();
-            CPPUNIT_MSG( "   Duration=" << pool.avgDuration() );
-
-            size_t nInsertSuccess = 0;
-            size_t nInsertFailed = 0;
-            size_t nDeleteSuccess = 0;
-            size_t nDeleteFailed = 0;
-            for ( CppUnitMini::ThreadPool::iterator it = pool.begin(); it != pool.end(); ++it ) {
-                InserterThread * pThread = dynamic_cast<InserterThread *>( *it );
-                if ( pThread ) {
-                    nInsertSuccess += pThread->m_nInsertSuccess;
-                    nInsertFailed += pThread->m_nInsertFailed;
-                }
-                else {
-                    DeleterThread * p = static_cast<DeleterThread *>( *it );
-                    nDeleteSuccess += p->m_nDeleteSuccess;
-                    nDeleteFailed += p->m_nDeleteFailed;
-                }
-            }
-
-            CPPUNIT_MSG( "    Totals: Ins succ=" << nInsertSuccess
-                << " Del succ=" << nDeleteSuccess << "\n"
-                << "          : Ins fail=" << nInsertFailed
-                << " Del fail=" << nDeleteFailed
-                << " Map size=" << testMap.size()
-                );
-
-            check_before_cleanup( testMap );
-
-            CPPUNIT_MSG( "  Clear map (single-threaded)..." );
-            timer.reset();
-            for ( size_t nItem = 0; nItem < c_nMapSize; ++nItem ) {
-                testMap.erase( nItem );
-            }
-            CPPUNIT_MSG( "   Duration=" << timer.duration() );
-            CPPUNIT_ASSERT_EX( testMap.empty(), ((long long) testMap.size()) );
-
-            additional_check( testMap );
-            print_stat( testMap );
-            additional_cleanup( testMap );
-        }
-
-        template <class MAP>
-        void test()
-        {
-            CPPUNIT_MSG( "Thread count: insert=" << c_nInsertThreadCount
-                << " delete=" << c_nDeleteThreadCount
-                << " pass count=" << c_nThreadPassCount
-                << " map size=" << c_nMapSize
-                );
-
-            for ( size_t nLoadFactor = 1; nLoadFactor <= c_nMaxLoadFactor; nLoadFactor *= 2 ) {
-                CPPUNIT_MSG( "Load factor=" << nLoadFactor );
-                MAP  testMap( c_nMapSize, nLoadFactor );
-                do_test( testMap );
-                if ( c_bPrintGCState )
-                    print_gc_state();
-            }
-        }
-
-        template <class MAP>
-        void test_nolf()
-        {
-            CPPUNIT_MSG( "Thread count: insert=" << c_nInsertThreadCount
-                << " delete=" << c_nDeleteThreadCount
-                << " pass count=" << c_nThreadPassCount
-                << " map size=" << c_nMapSize
-                );
-
-            MAP testMap;
-            do_test( testMap );
-            if ( c_bPrintGCState )
-                print_gc_state();
-        }
-
-        void setUpParams( const CppUnitMini::TestCfg& cfg ) {
-            c_nInsertThreadCount = cfg.getULong("InsertThreadCount", 4 );
-            c_nDeleteThreadCount = cfg.getULong("DeleteThreadCount", 4 );
-            c_nThreadPassCount = cfg.getULong("ThreadPassCount", 4 );
-            c_nMapSize = cfg.getULong("MapSize", 1000000 );
-            c_nMaxLoadFactor = cfg.getULong("MaxLoadFactor", 8 );
-            c_bPrintGCState = cfg.getBool("PrintGCStateFlag", true );
-        }
-
-#   include "map2/map_defs.h"
-        CDSUNIT_DECLARE_MichaelMap
-        CDSUNIT_DECLARE_SplitList
-        CDSUNIT_DECLARE_SkipListMap
-        CDSUNIT_DECLARE_EllenBinTreeMap
-        CDSUNIT_DECLARE_BronsonAVLTreeMap
-        CDSUNIT_DECLARE_StripedMap
-        CDSUNIT_DECLARE_RefinableMap
-        CDSUNIT_DECLARE_CuckooMap
-        CDSUNIT_DECLARE_StdMap
-
-        CPPUNIT_TEST_SUITE( Map_InsDel_int )
-            CDSUNIT_TEST_MichaelMap
-            CDSUNIT_TEST_SplitList
-            CDSUNIT_TEST_SkipListMap
-            CDSUNIT_TEST_EllenBinTreeMap
-            CDSUNIT_TEST_BronsonAVLTreeMap
-            CDSUNIT_TEST_StripedMap
-            CDSUNIT_TEST_RefinableMap
-            CDSUNIT_TEST_CuckooMap
-            CDSUNIT_TEST_StdMap
-        CPPUNIT_TEST_SUITE_END()
-
-    };
-
-    CPPUNIT_TEST_SUITE_REGISTRATION( Map_InsDel_int );
+        setUpParams( m_Cfg.get( "Map_InsDel_int" ));
+
+        run_MichaelMap(in_name, invert);
+        run_SplitList(in_name, invert);
+        run_SkipListMap(in_name, invert);
+        run_EllenBinTreeMap(in_name, invert);
+        run_BronsonAVLTreeMap(in_name, invert);
+        run_StripedMap(in_name, invert);
+        run_RefinableMap(in_name, invert);
+        run_CuckooMap(in_name, invert);
+
+        endTestCase();
+    }
 } // namespace map2
diff --git a/tests/unit/map2/map_insdel_int.h b/tests/unit/map2/map_insdel_int.h
new file mode 100644 (file)
index 0000000..c1b825d
--- /dev/null
@@ -0,0 +1,272 @@
+//$$CDS-header$$
+
+#include "map2/map_types.h"
+#include "cppunit/thread.h"
+
+#include <vector>
+
+namespace map2 {
+
+#   define TEST_MAP(X)         void X() { test<MapTypes<key_type, value_type>::X >(); }
+#   define TEST_MAP_EXTRACT(X) TEST_MAP(X)
+#   define TEST_MAP_NOLF(X)    void X() { test_nolf<MapTypes<key_type, value_type>::X >(); }
+#   define TEST_MAP_NOLF_EXTRACT(X) TEST_MAP_NOLF(X)
+
+    class Map_InsDel_int: public CppUnitMini::TestCase
+    {
+        static size_t  c_nMapSize;            // map size
+        static size_t  c_nInsertThreadCount;  // count of insertion thread
+        static size_t  c_nDeleteThreadCount;  // count of deletion thread
+        static size_t  c_nThreadPassCount;    // pass count for each thread
+        static size_t  c_nMaxLoadFactor;      // maximum load factor
+        static bool    c_bPrintGCState;
+
+        typedef CppUnitMini::TestCase Base;
+        typedef size_t  key_type;
+        typedef size_t  value_type;
+
+        typedef std::vector<key_type>   key_array;
+        key_array                       m_arrValues;
+
+        template <class MAP>
+        class Inserter: public CppUnitMini::TestThread
+        {
+            MAP&     m_Map;
+
+            virtual Inserter *    clone()
+            {
+                return new Inserter( *this );
+            }
+        public:
+            size_t  m_nInsertSuccess;
+            size_t  m_nInsertFailed;
+
+        public:
+            Inserter( CppUnitMini::ThreadPool& pool, MAP& rMap )
+                : CppUnitMini::TestThread( pool )
+                , m_Map( rMap )
+            {}
+            Inserter( Inserter& src )
+                : CppUnitMini::TestThread( src )
+                , m_Map( src.m_Map )
+            {}
+
+            Map_InsDel_int&  getTest()
+            {
+                return reinterpret_cast<Map_InsDel_int&>( m_Pool.m_Test );
+            }
+
+            virtual void init() { cds::threading::Manager::attachThread()   ; }
+            virtual void fini() { cds::threading::Manager::detachThread()   ; }
+
+            virtual void test()
+            {
+                MAP& rMap = m_Map;
+
+                m_nInsertSuccess =
+                    m_nInsertFailed = 0;
+                key_array const& arr = getTest().m_arrValues;
+
+                if ( m_nThreadNo & 1 ) {
+                    for ( size_t nPass = 0; nPass < c_nThreadPassCount; ++nPass ) {
+                        for ( key_array::const_iterator it = arr.begin(), itEnd = arr.end(); it != itEnd; ++it ) {
+                            if ( rMap.insert( *it, *it * 8 ) )
+                                ++m_nInsertSuccess;
+                            else
+                                ++m_nInsertFailed;
+                        }
+                    }
+                }
+                else {
+                    for ( size_t nPass = 0; nPass < c_nThreadPassCount; ++nPass ) {
+                        for ( key_array::const_reverse_iterator it = arr.rbegin(), itEnd = arr.rend(); it != itEnd; ++it ) {
+                            if ( rMap.insert( *it, *it * 8 ) )
+                                ++m_nInsertSuccess;
+                            else
+                                ++m_nInsertFailed;
+                        }
+                    }
+                }
+            }
+        };
+
+        template <class MAP>
+        class Deleter: public CppUnitMini::TestThread
+        {
+            MAP&     m_Map;
+
+            virtual Deleter *    clone()
+            {
+                return new Deleter( *this );
+            }
+        public:
+            size_t  m_nDeleteSuccess;
+            size_t  m_nDeleteFailed;
+
+        public:
+            Deleter( CppUnitMini::ThreadPool& pool, MAP& rMap )
+                : CppUnitMini::TestThread( pool )
+                , m_Map( rMap )
+            {}
+            Deleter( Deleter& src )
+                : CppUnitMini::TestThread( src )
+                , m_Map( src.m_Map )
+            {}
+
+            Map_InsDel_int&  getTest()
+            {
+                return reinterpret_cast<Map_InsDel_int&>( m_Pool.m_Test );
+            }
+
+            virtual void init() { cds::threading::Manager::attachThread()   ; }
+            virtual void fini() { cds::threading::Manager::detachThread()   ; }
+
+            virtual void test()
+            {
+                MAP& rMap = m_Map;
+
+                m_nDeleteSuccess =
+                    m_nDeleteFailed = 0;
+                key_array const& arr = getTest().m_arrValues;
+
+                if ( m_nThreadNo & 1 ) {
+                    for ( size_t nPass = 0; nPass < c_nThreadPassCount; ++nPass ) {
+                        for ( key_array::const_iterator it = arr.begin(), itEnd = arr.end(); it != itEnd; ++it ) {
+                            if ( rMap.erase( *it ) )
+                                ++m_nDeleteSuccess;
+                            else
+                                ++m_nDeleteFailed;
+                        }
+                    }
+                }
+                else {
+                    for ( size_t nPass = 0; nPass < c_nThreadPassCount; ++nPass ) {
+                        for ( key_array::const_reverse_iterator it = arr.rbegin(), itEnd = arr.rend(); it != itEnd; ++it ) {
+                            if ( rMap.erase( *it ) )
+                                ++m_nDeleteSuccess;
+                            else
+                                ++m_nDeleteFailed;
+                        }
+                    }
+                }
+            }
+        };
+
+    protected:
+        template <class MAP>
+        void do_test( MAP& testMap )
+        {
+            typedef Inserter<MAP>       InserterThread;
+            typedef Deleter<MAP>        DeleterThread;
+            cds::OS::Timer    timer;
+
+            m_arrValues.clear();
+            m_arrValues.reserve( c_nMapSize );
+            for ( size_t i = 0; i < c_nMapSize; ++i )
+                m_arrValues.push_back( i );
+            std::random_shuffle( m_arrValues.begin(), m_arrValues.end() );
+
+            CppUnitMini::ThreadPool pool( *this );
+            pool.add( new InserterThread( pool, testMap ), c_nInsertThreadCount );
+            pool.add( new DeleterThread( pool, testMap ), c_nDeleteThreadCount );
+            pool.run();
+            CPPUNIT_MSG( "   Duration=" << pool.avgDuration() );
+
+            size_t nInsertSuccess = 0;
+            size_t nInsertFailed = 0;
+            size_t nDeleteSuccess = 0;
+            size_t nDeleteFailed = 0;
+            for ( CppUnitMini::ThreadPool::iterator it = pool.begin(); it != pool.end(); ++it ) {
+                InserterThread * pThread = dynamic_cast<InserterThread *>( *it );
+                if ( pThread ) {
+                    nInsertSuccess += pThread->m_nInsertSuccess;
+                    nInsertFailed += pThread->m_nInsertFailed;
+                }
+                else {
+                    DeleterThread * p = static_cast<DeleterThread *>( *it );
+                    nDeleteSuccess += p->m_nDeleteSuccess;
+                    nDeleteFailed += p->m_nDeleteFailed;
+                }
+            }
+
+            CPPUNIT_MSG( "    Totals: Ins succ=" << nInsertSuccess
+                << " Del succ=" << nDeleteSuccess << "\n"
+                << "          : Ins fail=" << nInsertFailed
+                << " Del fail=" << nDeleteFailed
+                << " Map size=" << testMap.size()
+                );
+
+            check_before_cleanup( testMap );
+
+            CPPUNIT_MSG( "  Clear map (single-threaded)..." );
+            timer.reset();
+            for ( size_t nItem = 0; nItem < c_nMapSize; ++nItem ) {
+                testMap.erase( nItem );
+            }
+            CPPUNIT_MSG( "   Duration=" << timer.duration() );
+            CPPUNIT_ASSERT_EX( testMap.empty(), ((long long) testMap.size()) );
+
+            additional_check( testMap );
+            print_stat( testMap );
+            additional_cleanup( testMap );
+        }
+
+        template <class MAP>
+        void test()
+        {
+            CPPUNIT_MSG( "Thread count: insert=" << c_nInsertThreadCount
+                << " delete=" << c_nDeleteThreadCount
+                << " pass count=" << c_nThreadPassCount
+                << " map size=" << c_nMapSize
+                );
+
+            for ( size_t nLoadFactor = 1; nLoadFactor <= c_nMaxLoadFactor; nLoadFactor *= 2 ) {
+                CPPUNIT_MSG( "Load factor=" << nLoadFactor );
+                MAP  testMap( c_nMapSize, nLoadFactor );
+                do_test( testMap );
+                if ( c_bPrintGCState )
+                    print_gc_state();
+            }
+        }
+
+        template <class MAP>
+        void test_nolf()
+        {
+            CPPUNIT_MSG( "Thread count: insert=" << c_nInsertThreadCount
+                << " delete=" << c_nDeleteThreadCount
+                << " pass count=" << c_nThreadPassCount
+                << " map size=" << c_nMapSize
+                );
+
+            MAP testMap;
+            do_test( testMap );
+            if ( c_bPrintGCState )
+                print_gc_state();
+        }
+
+        void setUpParams( const CppUnitMini::TestCfg& cfg );
+
+        void run_MichaelMap(const char *in_name, bool invert = false);
+        void run_SplitList(const char *in_name, bool invert = false);
+        void run_StripedMap(const char *in_name, bool invert = false);
+        void run_RefinableMap(const char *in_name, bool invert = false);
+        void run_CuckooMap(const char *in_name, bool invert = false);
+        void run_SkipListMap(const char *in_name, bool invert = false);
+        void run_EllenBinTreeMap(const char *in_name, bool invert = false);
+        void run_BronsonAVLTreeMap(const char *in_name, bool invert = false);
+
+        virtual void myRun(const char *in_name, bool invert = false);
+
+
+#   include "map2/map_defs.h"
+        CDSUNIT_DECLARE_MichaelMap
+        CDSUNIT_DECLARE_SplitList
+        CDSUNIT_DECLARE_SkipListMap
+        CDSUNIT_DECLARE_EllenBinTreeMap
+        CDSUNIT_DECLARE_BronsonAVLTreeMap
+        CDSUNIT_DECLARE_StripedMap
+        CDSUNIT_DECLARE_RefinableMap
+        CDSUNIT_DECLARE_CuckooMap
+        //CDSUNIT_DECLARE_StdMap
+    };
+} // namespace map2
diff --git a/tests/unit/map2/map_insdel_int_bronsonavltree.cpp b/tests/unit/map2/map_insdel_int_bronsonavltree.cpp
new file mode 100644 (file)
index 0000000..e2c4c33
--- /dev/null
@@ -0,0 +1,9 @@
+//$$CDS-header$$
+
+#include "map2/map_insdel_int.h"
+
+namespace map2 {
+    CPPUNIT_TEST_SUITE_PART( Map_InsDel_int, run_BronsonAVLTreeMap )
+        CDSUNIT_TEST_BronsonAVLTreeMap
+    CPPUNIT_TEST_SUITE_END_PART()
+} // namespace map2
diff --git a/tests/unit/map2/map_insdel_int_cuckoo.cpp b/tests/unit/map2/map_insdel_int_cuckoo.cpp
new file mode 100644 (file)
index 0000000..f18faff
--- /dev/null
@@ -0,0 +1,9 @@
+//$$CDS-header$$
+
+#include "map2/map_insdel_int.h"
+
+namespace map2 {
+    CPPUNIT_TEST_SUITE_PART( Map_InsDel_int, run_CuckooMap )
+        CDSUNIT_TEST_CuckooMap
+    CPPUNIT_TEST_SUITE_END_PART()
+} // namespace map2
diff --git a/tests/unit/map2/map_insdel_int_ellentree.cpp b/tests/unit/map2/map_insdel_int_ellentree.cpp
new file mode 100644 (file)
index 0000000..d026cca
--- /dev/null
@@ -0,0 +1,9 @@
+//$$CDS-header$$
+
+#include "map2/map_insdel_int.h"
+
+namespace map2 {
+    CPPUNIT_TEST_SUITE_PART( Map_InsDel_int, run_EllenBinTreeMap )
+        CDSUNIT_TEST_EllenBinTreeMap
+    CPPUNIT_TEST_SUITE_END_PART()
+} // namespace map2
diff --git a/tests/unit/map2/map_insdel_int_michael.cpp b/tests/unit/map2/map_insdel_int_michael.cpp
new file mode 100644 (file)
index 0000000..1f523d4
--- /dev/null
@@ -0,0 +1,9 @@
+//$$CDS-header$$
+
+#include "map2/map_insdel_int.h"
+
+namespace map2 {
+    CPPUNIT_TEST_SUITE_PART( Map_InsDel_int, run_MichaelMap )
+        CDSUNIT_TEST_MichaelMap
+    CPPUNIT_TEST_SUITE_END_PART()
+} // namespace map2
diff --git a/tests/unit/map2/map_insdel_int_refinable.cpp b/tests/unit/map2/map_insdel_int_refinable.cpp
new file mode 100644 (file)
index 0000000..956eb42
--- /dev/null
@@ -0,0 +1,9 @@
+//$$CDS-header$$
+
+#include "map2/map_insdel_int.h"
+
+namespace map2 {
+    CPPUNIT_TEST_SUITE_PART( Map_InsDel_int, run_RefinableMap )
+        CDSUNIT_TEST_RefinableMap
+    CPPUNIT_TEST_SUITE_END_PART()
+} // namespace map2
diff --git a/tests/unit/map2/map_insdel_int_skip.cpp b/tests/unit/map2/map_insdel_int_skip.cpp
new file mode 100644 (file)
index 0000000..c0b4405
--- /dev/null
@@ -0,0 +1,9 @@
+//$$CDS-header$$
+
+#include "map2/map_insdel_int.h"
+
+namespace map2 {
+    CPPUNIT_TEST_SUITE_PART( Map_InsDel_int, run_SkipListMap )
+        CDSUNIT_TEST_SkipListMap
+    CPPUNIT_TEST_SUITE_END_PART()
+} // namespace map2
diff --git a/tests/unit/map2/map_insdel_int_split.cpp b/tests/unit/map2/map_insdel_int_split.cpp
new file mode 100644 (file)
index 0000000..b28f0d6
--- /dev/null
@@ -0,0 +1,9 @@
+//$$CDS-header$$
+
+#include "map2/map_insdel_int.h"
+
+namespace map2 {
+    CPPUNIT_TEST_SUITE_PART( Map_InsDel_int, run_SplitList )
+        CDSUNIT_TEST_SplitList
+    CPPUNIT_TEST_SUITE_END_PART()
+} // namespace map2
diff --git a/tests/unit/map2/map_insdel_int_striped.cpp b/tests/unit/map2/map_insdel_int_striped.cpp
new file mode 100644 (file)
index 0000000..fc4644f
--- /dev/null
@@ -0,0 +1,9 @@
+//$$CDS-header$$
+
+#include "map2/map_insdel_int.h"
+
+namespace map2 {
+    CPPUNIT_TEST_SUITE_PART( Map_InsDel_int, run_StripedMap )
+        CDSUNIT_TEST_StripedMap
+    CPPUNIT_TEST_SUITE_END_PART()
+} // namespace map2
index ad80499c13bc36437985b6037e2df1219485bb76..cfb7d8c2b014d1b8962f87363876d0badbbf038b 100644 (file)
 //$$CDS-header$$
 
-#include "map2/map_types.h"
-#include "cppunit/thread.h"
-
-#include <vector>
-#include <algorithm>    // random_shuffle
+#include "map2/map_insdel_item_int.h"
 
 namespace map2 {
+    CPPUNIT_TEST_SUITE_REGISTRATION( Map_InsDel_Item_int );
 
-#   define TEST_MAP(X)         void X() { test<MapTypes<key_type, value_type>::X >()    ; }
-#   define TEST_MAP_NOLF(X)    void X() { test_nolf<MapTypes<key_type, value_type>::X >()    ; }
-#   define TEST_MAP_EXTRACT(X)  TEST_MAP(X)
-#   define TEST_MAP_NOLF_EXTRACT(X) TEST_MAP_NOLF(X)
+    size_t Map_InsDel_Item_int::c_nMapSize = 1000000    ;  // map size
+    size_t Map_InsDel_Item_int::c_nThreadCount = 4      ;  // thread count
+    size_t Map_InsDel_Item_int::c_nGoalItem = Map_InsDel_Item_int::c_nMapSize / 2;
+    size_t Map_InsDel_Item_int::c_nAttemptCount = 100000       ;   // count of SUCCESS insert/delete for each thread
+    size_t Map_InsDel_Item_int::c_nMaxLoadFactor = 8    ;  // maximum load factor
+    bool   Map_InsDel_Item_int::c_bPrintGCState = true;
 
-    namespace {
-        static size_t  c_nMapSize = 1000000    ;  // map size
-        static size_t  c_nThreadCount = 4      ;  // thread count
-        static size_t  c_nGoalItem = c_nMapSize / 2;
-        static size_t  c_nAttemptCount = 100000       ;   // count of SUCCESS insert/delete for each thread
-        static size_t  c_nMaxLoadFactor = 8    ;  // maximum load factor
-        static bool    c_bPrintGCState = true;
+    void Map_InsDel_Item_int::setUpParams( const CppUnitMini::TestCfg& cfg )
+    {
+        c_nThreadCount = cfg.getSizeT("ThreadCount", c_nThreadCount );
+        c_nMapSize = cfg.getSizeT("MapSize", c_nMapSize );
+        c_nGoalItem = cfg.getSizeT("GoalItem", c_nGoalItem );
+        c_nAttemptCount = cfg.getSizeT("AttemptCount", c_nAttemptCount );
+        c_nMaxLoadFactor = cfg.getSizeT("MaxLoadFactor", c_nMaxLoadFactor );
+        c_bPrintGCState = cfg.getBool("PrintGCStateFlag", true );
     }
 
-    class Map_InsDel_Item_int: public CppUnitMini::TestCase
+    void Map_InsDel_Item_int::myRun(const char *in_name, bool invert /*= false*/)
     {
-        typedef size_t  key_type;
-        typedef size_t  value_type;
-
-        template <class MAP>
-        class Inserter: public CppUnitMini::TestThread
-        {
-            MAP&     m_Map;
-
-            virtual Inserter *    clone()
-            {
-                return new Inserter( *this );
-            }
-
-            struct ensure_func
-            {
-                void operator()( bool bNew, std::pair<key_type const, value_type>& item )
-                {
-                    if ( bNew )
-                        item.second = item.first;
-                }
-                // for boost::container::flat_map
-                void operator()( bool bNew, std::pair<key_type, value_type>& item )
-                {
-                    if ( bNew )
-                        item.second = item.first;
-                }
-
-                // for BronsonAVLTreeMap
-                void operator()( bool bNew, key_type key, value_type& val )
-                {
-                    if ( bNew )
-                        val = key;
-                }
-            };
-
-        public:
-            size_t  m_nInsertSuccess;
-            size_t  m_nInsertFailed;
-
-        public:
-            Inserter( CppUnitMini::ThreadPool& pool, MAP& rMap )
-                : CppUnitMini::TestThread( pool )
-                , m_Map( rMap )
-            {}
-            Inserter( Inserter& src )
-                : CppUnitMini::TestThread( src )
-                , m_Map( src.m_Map )
-            {}
-
-            Map_InsDel_Item_int&  getTest()
-            {
-                return reinterpret_cast<Map_InsDel_Item_int&>( m_Pool.m_Test );
-            }
-
-            virtual void init() { cds::threading::Manager::attachThread()   ; }
-            virtual void fini() { cds::threading::Manager::detachThread()   ; }
-
-            virtual void test()
-            {
-                MAP& rMap = m_Map;
-
-                m_nInsertSuccess =
-                    m_nInsertFailed = 0;
-
-                size_t nGoalItem = c_nGoalItem;
-                for ( size_t nAttempt = 0; nAttempt < c_nAttemptCount; ) {
-                    if ( nAttempt % 2  == 0 ) {
-                        if ( rMap.insert( nGoalItem, nGoalItem )) {
-                            ++m_nInsertSuccess;
-                            ++nAttempt;
-                        }
-                        else
-                            ++m_nInsertFailed;
-                    }
-                    else {
-                        std::pair<bool, bool> ensureResult = rMap.ensure( nGoalItem, ensure_func() );
-                        if ( ensureResult.second ) {
-                            ++m_nInsertSuccess;
-                            ++nAttempt;
-                        }
-                        else
-                            ++m_nInsertFailed;
-                    }
-                }
-            }
-        };
-
-        template <class MAP>
-        class Deleter: public CppUnitMini::TestThread
-        {
-            MAP&     m_Map;
-
-            virtual Deleter *    clone()
-            {
-                return new Deleter( *this );
-            }
-        public:
-            size_t  m_nDeleteSuccess;
-            size_t  m_nDeleteFailed;
-
-        public:
-            Deleter( CppUnitMini::ThreadPool& pool, MAP& rMap )
-                : CppUnitMini::TestThread( pool )
-                , m_Map( rMap )
-            {}
-            Deleter( Deleter& src )
-                : CppUnitMini::TestThread( src )
-                , m_Map( src.m_Map )
-            {}
-
-            Map_InsDel_Item_int&  getTest()
-            {
-                return reinterpret_cast<Map_InsDel_Item_int&>( m_Pool.m_Test );
-            }
-
-            virtual void init() { cds::threading::Manager::attachThread()   ; }
-            virtual void fini() { cds::threading::Manager::detachThread()   ; }
-
-            virtual void test()
-            {
-                MAP& rMap = m_Map;
-
-                m_nDeleteSuccess =
-                    m_nDeleteFailed = 0;
-
-                size_t nGoalItem = c_nGoalItem;
-                for ( size_t nAttempt = 0; nAttempt < c_nAttemptCount; ) {
-                    if ( rMap.erase( nGoalItem )) {
-                        ++m_nDeleteSuccess;
-                        ++nAttempt;
-                    }
-                    else
-                        ++m_nDeleteFailed;
-                }
-            }
-        };
-
-    protected:
-
-        template <class MAP>
-        void do_test( MAP& testMap )
-        {
-            typedef Inserter<MAP>       InserterThread;
-            typedef Deleter<MAP>        DeleterThread;
-            cds::OS::Timer    timer;
-
-            // Fill the map
-            CPPUNIT_MSG( "  Fill map (" << c_nMapSize << " items)...");
-            timer.reset();
-            {
-                std::vector<key_type>   v;
-                v.reserve( c_nMapSize );
-                for ( size_t i = 0; i < c_nMapSize; ++i )
-                    v.push_back( i );
-                std::random_shuffle( v.begin(), v.end() );
-                for ( size_t i = 0; i < v.size(); ++i ) {
-                    CPPUNIT_ASSERT( testMap.insert( v[i], v[i] ));
-                }
-            }
-            CPPUNIT_MSG( "   Duration=" << timer.duration() );
-
-            CPPUNIT_MSG( "  Insert/delete the key " << c_nGoalItem << " (" << c_nAttemptCount << " successful times)...");
-            CppUnitMini::ThreadPool pool( *this );
-            pool.add( new InserterThread( pool, testMap ), (c_nThreadCount + 1) / 2 );
-            pool.add( new DeleterThread( pool, testMap ), (c_nThreadCount + 1) / 2 );
-            pool.run();
-            CPPUNIT_MSG( "   Duration=" << pool.avgDuration() );
-
-            size_t nInsertSuccess = 0;
-            size_t nInsertFailed = 0;
-            size_t nDeleteSuccess = 0;
-            size_t nDeleteFailed = 0;
-            for ( CppUnitMini::ThreadPool::iterator it = pool.begin(); it != pool.end(); ++it ) {
-                InserterThread * pThread = dynamic_cast<InserterThread *>( *it );
-                if ( pThread ) {
-                    CPPUNIT_CHECK( pThread->m_nInsertSuccess == c_nAttemptCount );
-                    nInsertSuccess += pThread->m_nInsertSuccess;
-                    nInsertFailed += pThread->m_nInsertFailed;
-                }
-                else {
-                    DeleterThread * p = static_cast<DeleterThread *>( *it );
-                    CPPUNIT_CHECK( p->m_nDeleteSuccess == c_nAttemptCount );
-                    nDeleteSuccess += p->m_nDeleteSuccess;
-                    nDeleteFailed += p->m_nDeleteFailed;
-                }
-            }
-            CPPUNIT_CHECK( nInsertSuccess == nDeleteSuccess );
-            size_t nGoalItem = c_nGoalItem;
-            CPPUNIT_CHECK( testMap.find( nGoalItem ));
-
-
-            CPPUNIT_MSG( "    Totals: Ins fail=" << nInsertFailed << " Del fail=" << nDeleteFailed );
-
-            // Check if the map contains all items
-            CPPUNIT_MSG( "    Check if the map contains all items" );
-            timer.reset();
-            for ( size_t i = 0; i < c_nMapSize; ++i ) {
-                CPPUNIT_CHECK_EX( testMap.find( i ), "key " << i );
-            }
-            CPPUNIT_MSG( "    Duration=" << timer.duration() );
-
-            check_before_cleanup( testMap );
-
-            testMap.clear();
-            additional_check( testMap );
-            print_stat( testMap );
-            additional_cleanup( testMap );
-        }
-
-        template <class MAP>
-        void test()
-        {
-            for ( size_t nLoadFactor = 1; nLoadFactor <= c_nMaxLoadFactor; nLoadFactor *= 2 ) {
-                CPPUNIT_MSG( "Load factor=" << nLoadFactor );
-                MAP testMap( c_nMapSize, nLoadFactor );
-                do_test( testMap );
-                if ( c_bPrintGCState )
-                    print_gc_state();
-            }
-        }
-
-        template <class MAP>
-        void test_nolf()
-        {
-            MAP testMap;
-            do_test<MAP>( testMap );
-            if ( c_bPrintGCState )
-                print_gc_state();
-        }
-
-        void setUpParams( const CppUnitMini::TestCfg& cfg ) {
-            c_nThreadCount = cfg.getULong("ThreadCount", 8 )        ; // thread count
-            c_nMapSize = cfg.getULong("MapSize", 1000000 );
-            c_nGoalItem = cfg.getULong("GoalItem", (unsigned long) (c_nMapSize / 2) );
-            c_nAttemptCount = cfg.getULong("AttemptCount", 100000 );
-            c_nMaxLoadFactor = cfg.getULong("MaxLoadFactor", 8 );
-            c_bPrintGCState = cfg.getBool("PrintGCStateFlag", true );
-        }
-
-#   include "map2/map_defs.h"
-        CDSUNIT_DECLARE_MichaelMap
-        CDSUNIT_DECLARE_SplitList
-        CDSUNIT_DECLARE_SkipListMap
-        CDSUNIT_DECLARE_EllenBinTreeMap
-        CDSUNIT_DECLARE_BronsonAVLTreeMap
-        CDSUNIT_DECLARE_StripedMap
-        CDSUNIT_DECLARE_RefinableMap
-        CDSUNIT_DECLARE_CuckooMap
-        CDSUNIT_DECLARE_StdMap
-
-        CPPUNIT_TEST_SUITE( Map_InsDel_Item_int )
-            CDSUNIT_TEST_MichaelMap
-            CDSUNIT_TEST_SplitList
-            CDSUNIT_TEST_SkipListMap
-            CDSUNIT_TEST_EllenBinTreeMap
-            CDSUNIT_TEST_BronsonAVLTreeMap
-            CDSUNIT_TEST_StripedMap
-            CDSUNIT_TEST_RefinableMap
-            CDSUNIT_TEST_CuckooMap
-            //CDSUNIT_TEST_StdMap       // very slow!!!
-        CPPUNIT_TEST_SUITE_END()
-
-    };
-
-    CPPUNIT_TEST_SUITE_REGISTRATION( Map_InsDel_Item_int );
+        setUpParams( m_Cfg.get( "Map_InsDel_Item_int" ));
+
+        run_MichaelMap(in_name, invert);
+        run_SplitList(in_name, invert);
+        run_SkipListMap(in_name, invert);
+        run_EllenBinTreeMap(in_name, invert);
+        run_BronsonAVLTreeMap(in_name, invert);
+        run_StripedMap(in_name, invert);
+        run_RefinableMap(in_name, invert);
+        run_CuckooMap(in_name, invert);
+
+        endTestCase();
+    }
 } // namespace map2
diff --git a/tests/unit/map2/map_insdel_item_int.h b/tests/unit/map2/map_insdel_item_int.h
new file mode 100644 (file)
index 0000000..cc11776
--- /dev/null
@@ -0,0 +1,280 @@
+//$$CDS-header$$
+
+#include "map2/map_types.h"
+#include "cppunit/thread.h"
+
+#include <vector>
+#include <algorithm>    // random_shuffle
+
+namespace map2 {
+
+#   define TEST_MAP(X)         void X() { test<MapTypes<key_type, value_type>::X >()    ; }
+#   define TEST_MAP_NOLF(X)    void X() { test_nolf<MapTypes<key_type, value_type>::X >()    ; }
+#   define TEST_MAP_EXTRACT(X)  TEST_MAP(X)
+#   define TEST_MAP_NOLF_EXTRACT(X) TEST_MAP_NOLF(X)
+
+    class Map_InsDel_Item_int: public CppUnitMini::TestCase
+    {
+        static size_t  c_nMapSize;        // map size
+        static size_t  c_nThreadCount;    // thread count
+        static size_t  c_nGoalItem;
+        static size_t  c_nAttemptCount;   // count of SUCCESS insert/delete for each thread
+        static size_t  c_nMaxLoadFactor;  // maximum load factor
+        static bool    c_bPrintGCState;
+
+        typedef CppUnitMini::TestCase Base;
+        typedef size_t  key_type;
+        typedef size_t  value_type;
+
+        template <class MAP>
+        class Inserter: public CppUnitMini::TestThread
+        {
+            MAP&     m_Map;
+
+            virtual Inserter *    clone()
+            {
+                return new Inserter( *this );
+            }
+
+            struct ensure_func
+            {
+                void operator()( bool bNew, std::pair<key_type const, value_type>& item )
+                {
+                    if ( bNew )
+                        item.second = item.first;
+                }
+                // for boost::container::flat_map
+                void operator()( bool bNew, std::pair<key_type, value_type>& item )
+                {
+                    if ( bNew )
+                        item.second = item.first;
+                }
+
+                // for BronsonAVLTreeMap
+                void operator()( bool bNew, key_type key, value_type& val )
+                {
+                    if ( bNew )
+                        val = key;
+                }
+            };
+
+        public:
+            size_t  m_nInsertSuccess;
+            size_t  m_nInsertFailed;
+
+        public:
+            Inserter( CppUnitMini::ThreadPool& pool, MAP& rMap )
+                : CppUnitMini::TestThread( pool )
+                , m_Map( rMap )
+            {}
+            Inserter( Inserter& src )
+                : CppUnitMini::TestThread( src )
+                , m_Map( src.m_Map )
+            {}
+
+            Map_InsDel_Item_int&  getTest()
+            {
+                return reinterpret_cast<Map_InsDel_Item_int&>( m_Pool.m_Test );
+            }
+
+            virtual void init() { cds::threading::Manager::attachThread()   ; }
+            virtual void fini() { cds::threading::Manager::detachThread()   ; }
+
+            virtual void test()
+            {
+                MAP& rMap = m_Map;
+
+                m_nInsertSuccess =
+                    m_nInsertFailed = 0;
+
+                size_t nGoalItem = c_nGoalItem;
+                for ( size_t nAttempt = 0; nAttempt < c_nAttemptCount; ) {
+                    if ( nAttempt % 2  == 0 ) {
+                        if ( rMap.insert( nGoalItem, nGoalItem )) {
+                            ++m_nInsertSuccess;
+                            ++nAttempt;
+                        }
+                        else
+                            ++m_nInsertFailed;
+                    }
+                    else {
+                        std::pair<bool, bool> ensureResult = rMap.ensure( nGoalItem, ensure_func() );
+                        if ( ensureResult.second ) {
+                            ++m_nInsertSuccess;
+                            ++nAttempt;
+                        }
+                        else
+                            ++m_nInsertFailed;
+                    }
+                }
+            }
+        };
+
+        template <class MAP>
+        class Deleter: public CppUnitMini::TestThread
+        {
+            MAP&     m_Map;
+
+            virtual Deleter *    clone()
+            {
+                return new Deleter( *this );
+            }
+        public:
+            size_t  m_nDeleteSuccess;
+            size_t  m_nDeleteFailed;
+
+        public:
+            Deleter( CppUnitMini::ThreadPool& pool, MAP& rMap )
+                : CppUnitMini::TestThread( pool )
+                , m_Map( rMap )
+            {}
+            Deleter( Deleter& src )
+                : CppUnitMini::TestThread( src )
+                , m_Map( src.m_Map )
+            {}
+
+            Map_InsDel_Item_int&  getTest()
+            {
+                return reinterpret_cast<Map_InsDel_Item_int&>( m_Pool.m_Test );
+            }
+
+            virtual void init() { cds::threading::Manager::attachThread()   ; }
+            virtual void fini() { cds::threading::Manager::detachThread()   ; }
+
+            virtual void test()
+            {
+                MAP& rMap = m_Map;
+
+                m_nDeleteSuccess =
+                    m_nDeleteFailed = 0;
+
+                size_t nGoalItem = c_nGoalItem;
+                for ( size_t nAttempt = 0; nAttempt < c_nAttemptCount; ) {
+                    if ( rMap.erase( nGoalItem )) {
+                        ++m_nDeleteSuccess;
+                        ++nAttempt;
+                    }
+                    else
+                        ++m_nDeleteFailed;
+                }
+            }
+        };
+
+    protected:
+
+        template <class MAP>
+        void do_test( MAP& testMap )
+        {
+            typedef Inserter<MAP>       InserterThread;
+            typedef Deleter<MAP>        DeleterThread;
+            cds::OS::Timer    timer;
+
+            // Fill the map
+            CPPUNIT_MSG( "  Fill map (" << c_nMapSize << " items)...");
+            timer.reset();
+            {
+                std::vector<key_type>   v;
+                v.reserve( c_nMapSize );
+                for ( size_t i = 0; i < c_nMapSize; ++i )
+                    v.push_back( i );
+                std::random_shuffle( v.begin(), v.end() );
+                for ( size_t i = 0; i < v.size(); ++i ) {
+                    CPPUNIT_ASSERT( testMap.insert( v[i], v[i] ));
+                }
+            }
+            CPPUNIT_MSG( "   Duration=" << timer.duration() );
+
+            CPPUNIT_MSG( "  Insert/delete the key " << c_nGoalItem << " (" << c_nAttemptCount << " successful times)...");
+            CppUnitMini::ThreadPool pool( *this );
+            pool.add( new InserterThread( pool, testMap ), (c_nThreadCount + 1) / 2 );
+            pool.add( new DeleterThread( pool, testMap ), (c_nThreadCount + 1) / 2 );
+            pool.run();
+            CPPUNIT_MSG( "   Duration=" << pool.avgDuration() );
+
+            size_t nInsertSuccess = 0;
+            size_t nInsertFailed = 0;
+            size_t nDeleteSuccess = 0;
+            size_t nDeleteFailed = 0;
+            for ( CppUnitMini::ThreadPool::iterator it = pool.begin(); it != pool.end(); ++it ) {
+                InserterThread * pThread = dynamic_cast<InserterThread *>( *it );
+                if ( pThread ) {
+                    CPPUNIT_CHECK( pThread->m_nInsertSuccess == c_nAttemptCount );
+                    nInsertSuccess += pThread->m_nInsertSuccess;
+                    nInsertFailed += pThread->m_nInsertFailed;
+                }
+                else {
+                    DeleterThread * p = static_cast<DeleterThread *>( *it );
+                    CPPUNIT_CHECK( p->m_nDeleteSuccess == c_nAttemptCount );
+                    nDeleteSuccess += p->m_nDeleteSuccess;
+                    nDeleteFailed += p->m_nDeleteFailed;
+                }
+            }
+            CPPUNIT_CHECK( nInsertSuccess == nDeleteSuccess );
+            size_t nGoalItem = c_nGoalItem;
+            CPPUNIT_CHECK( testMap.find( nGoalItem ));
+
+
+            CPPUNIT_MSG( "    Totals: Ins fail=" << nInsertFailed << " Del fail=" << nDeleteFailed );
+
+            // Check if the map contains all items
+            CPPUNIT_MSG( "    Check if the map contains all items" );
+            timer.reset();
+            for ( size_t i = 0; i < c_nMapSize; ++i ) {
+                CPPUNIT_CHECK_EX( testMap.find( i ), "key " << i );
+            }
+            CPPUNIT_MSG( "    Duration=" << timer.duration() );
+
+            check_before_cleanup( testMap );
+
+            testMap.clear();
+            additional_check( testMap );
+            print_stat( testMap );
+            additional_cleanup( testMap );
+        }
+
+        template <class MAP>
+        void test()
+        {
+            for ( size_t nLoadFactor = 1; nLoadFactor <= c_nMaxLoadFactor; nLoadFactor *= 2 ) {
+                CPPUNIT_MSG( "Load factor=" << nLoadFactor );
+                MAP testMap( c_nMapSize, nLoadFactor );
+                do_test( testMap );
+                if ( c_bPrintGCState )
+                    print_gc_state();
+            }
+        }
+
+        template <class MAP>
+        void test_nolf()
+        {
+            MAP testMap;
+            do_test<MAP>( testMap );
+            if ( c_bPrintGCState )
+                print_gc_state();
+        }
+
+        void setUpParams( const CppUnitMini::TestCfg& cfg );
+
+        void run_MichaelMap(const char *in_name, bool invert = false);
+        void run_SplitList(const char *in_name, bool invert = false);
+        void run_SkipListMap(const char *in_name, bool invert = false);
+        void run_StripedMap(const char *in_name, bool invert = false);
+        void run_RefinableMap(const char *in_name, bool invert = false);
+        void run_CuckooMap(const char *in_name, bool invert = false);
+        void run_EllenBinTreeMap(const char *in_name, bool invert = false);
+        void run_BronsonAVLTreeMap(const char *in_name, bool invert = false);
+
+        virtual void myRun(const char *in_name, bool invert = false);
+
+#   include "map2/map_defs.h"
+        CDSUNIT_DECLARE_MichaelMap
+        CDSUNIT_DECLARE_SplitList
+        CDSUNIT_DECLARE_SkipListMap
+        CDSUNIT_DECLARE_EllenBinTreeMap
+        CDSUNIT_DECLARE_BronsonAVLTreeMap
+        CDSUNIT_DECLARE_StripedMap
+        CDSUNIT_DECLARE_RefinableMap
+        CDSUNIT_DECLARE_CuckooMap
+        //CDSUNIT_DECLARE_StdMap    // very slow!
+    };
+} // namespace map2
diff --git a/tests/unit/map2/map_insdel_item_int_bronsonavltree.cpp b/tests/unit/map2/map_insdel_item_int_bronsonavltree.cpp
new file mode 100644 (file)
index 0000000..a2be151
--- /dev/null
@@ -0,0 +1,9 @@
+//$$CDS-header$$
+
+#include "map2/map_insdel_item_int.h"
+
+namespace map2 {
+    CPPUNIT_TEST_SUITE_PART( Map_InsDel_Item_int, run_BronsonAVLTreeMap )
+        CDSUNIT_TEST_BronsonAVLTreeMap
+    CPPUNIT_TEST_SUITE_END_PART()
+} // namespace map2
diff --git a/tests/unit/map2/map_insdel_item_int_cuckoo.cpp b/tests/unit/map2/map_insdel_item_int_cuckoo.cpp
new file mode 100644 (file)
index 0000000..6213c6f
--- /dev/null
@@ -0,0 +1,9 @@
+//$$CDS-header$$
+
+#include "map2/map_insdel_item_int.h"
+
+namespace map2 {
+    CPPUNIT_TEST_SUITE_PART( Map_InsDel_Item_int, run_CuckooMap )
+        CDSUNIT_TEST_CuckooMap
+    CPPUNIT_TEST_SUITE_END_PART()
+} // namespace map2
diff --git a/tests/unit/map2/map_insdel_item_int_ellentree.cpp b/tests/unit/map2/map_insdel_item_int_ellentree.cpp
new file mode 100644 (file)
index 0000000..dc810ae
--- /dev/null
@@ -0,0 +1,9 @@
+//$$CDS-header$$
+
+#include "map2/map_insdel_item_int.h"
+
+namespace map2 {
+    CPPUNIT_TEST_SUITE_PART( Map_InsDel_Item_int, run_EllenBinTreeMap )
+        CDSUNIT_TEST_EllenBinTreeMap
+    CPPUNIT_TEST_SUITE_END_PART()
+} // namespace map2
diff --git a/tests/unit/map2/map_insdel_item_int_michael.cpp b/tests/unit/map2/map_insdel_item_int_michael.cpp
new file mode 100644 (file)
index 0000000..578462f
--- /dev/null
@@ -0,0 +1,9 @@
+//$$CDS-header$$
+
+#include "map2/map_insdel_item_int.h"
+
+namespace map2 {
+    CPPUNIT_TEST_SUITE_PART( Map_InsDel_Item_int, run_MichaelMap )
+        CDSUNIT_TEST_MichaelMap
+    CPPUNIT_TEST_SUITE_END_PART()
+} // namespace map2
diff --git a/tests/unit/map2/map_insdel_item_int_refinable.cpp b/tests/unit/map2/map_insdel_item_int_refinable.cpp
new file mode 100644 (file)
index 0000000..5fc0aee
--- /dev/null
@@ -0,0 +1,9 @@
+//$$CDS-header$$
+
+#include "map2/map_insdel_item_int.h"
+
+namespace map2 {
+    CPPUNIT_TEST_SUITE_PART( Map_InsDel_Item_int, run_RefinableMap )
+        CDSUNIT_TEST_RefinableMap
+    CPPUNIT_TEST_SUITE_END_PART()
+} // namespace map2
diff --git a/tests/unit/map2/map_insdel_item_int_skip.cpp b/tests/unit/map2/map_insdel_item_int_skip.cpp
new file mode 100644 (file)
index 0000000..97bb844
--- /dev/null
@@ -0,0 +1,9 @@
+//$$CDS-header$$
+
+#include "map2/map_insdel_item_int.h"
+
+namespace map2 {
+    CPPUNIT_TEST_SUITE_PART( Map_InsDel_Item_int, run_SkipListMap )
+        CDSUNIT_TEST_SkipListMap
+    CPPUNIT_TEST_SUITE_END_PART()
+} // namespace map2
diff --git a/tests/unit/map2/map_insdel_item_int_split.cpp b/tests/unit/map2/map_insdel_item_int_split.cpp
new file mode 100644 (file)
index 0000000..8d6b5fc
--- /dev/null
@@ -0,0 +1,9 @@
+//$$CDS-header$$
+
+#include "map2/map_insdel_item_int.h"
+
+namespace map2 {
+    CPPUNIT_TEST_SUITE_PART( Map_InsDel_Item_int, run_SplitList )
+        CDSUNIT_TEST_SplitList
+    CPPUNIT_TEST_SUITE_END_PART()
+} // namespace map2
diff --git a/tests/unit/map2/map_insdel_item_int_striped.cpp b/tests/unit/map2/map_insdel_item_int_striped.cpp
new file mode 100644 (file)
index 0000000..6c7ce65
--- /dev/null
@@ -0,0 +1,9 @@
+//$$CDS-header$$
+
+#include "map2/map_insdel_item_int.h"
+
+namespace map2 {
+    CPPUNIT_TEST_SUITE_PART( Map_InsDel_Item_int, run_StripedMap )
+        CDSUNIT_TEST_StripedMap
+    CPPUNIT_TEST_SUITE_END_PART()
+} // namespace map2
index fd062d1c3bb3a9e3b184dd493075cdf65a9cd1f6..09980ce8d05a27f96f4fc82a050593c68affc20d 100644 (file)
 //$$CDS-header$$
 
-#include "map2/map_types.h"
-#include "cppunit/thread.h"
-
-#include <vector>
+#include "map2/map_insdel_item_string.h"
 
 namespace map2 {
+    CPPUNIT_TEST_SUITE_REGISTRATION( Map_InsDel_Item_string );
 
-#   define TEST_MAP(X)         void X() { test<MapTypes<key_type, value_type>::X >()    ; }
-#   define TEST_MAP_NOLF(X)    void X() { test_nolf<MapTypes<key_type, value_type>::X >()    ; }
-#   define TEST_MAP_EXTRACT(X)  TEST_MAP(X)
-#   define TEST_MAP_NOLF_EXTRACT(X) TEST_MAP_NOLF(X)
+    size_t Map_InsDel_Item_string::c_nMapSize = 1000000;
+    size_t Map_InsDel_Item_string::c_nThreadCount = 4;
+    size_t Map_InsDel_Item_string::c_nGoalItem = c_nMapSize / 2;
+    size_t Map_InsDel_Item_string::c_nAttemptCount = 100000;
+    size_t Map_InsDel_Item_string::c_nMaxLoadFactor = 8;
+    bool   Map_InsDel_Item_string::c_bPrintGCState = true;
 
-    namespace {
-        static size_t  c_nMapSize = 1000000    ;  // map size
-        static size_t  c_nThreadCount = 4      ;  // thread count
-        static size_t  c_nGoalItem = c_nMapSize / 2;
-        static size_t  c_nAttemptCount = 100000       ;   // count of SUCCESS insert/delete for each thread
-        static size_t  c_nMaxLoadFactor = 8    ;  // maximum load factor
-        static bool    c_bPrintGCState = true;
+    void Map_InsDel_Item_string::setUpParams( const CppUnitMini::TestCfg& cfg )
+    {
+        c_nThreadCount = cfg.getSizeT("ThreadCount", c_nThreadCount );
+        c_nMapSize = cfg.getSizeT("MapSize", c_nMapSize );
+        c_nGoalItem = cfg.getSizeT("GoalItemIndex", c_nGoalItem);
+        c_nAttemptCount = cfg.getSizeT("AttemptCount", c_nAttemptCount );
+        c_nMaxLoadFactor = cfg.getSizeT("MaxLoadFactor", c_nMaxLoadFactor );
+        c_bPrintGCState = cfg.getBool("PrintGCStateFlag", true );
     }
 
-    class Map_InsDel_Item_string: public CppUnitMini::TestCase
+    void Map_InsDel_Item_string::myRun(const char *in_name, bool invert /*= false*/)
     {
-        typedef std::string  key_type;
-        typedef size_t  value_type;
-
-        const std::vector<std::string> *  m_parrString;
-
-        template <class Map>
-        class Inserter: public CppUnitMini::TestThread
-        {
-            Map&     m_Map;
-
-            virtual Inserter *    clone()
-            {
-                return new Inserter( *this );
-            }
-        public:
-            size_t  m_nInsertSuccess;
-            size_t  m_nInsertFailed;
-
-        public:
-            Inserter( CppUnitMini::ThreadPool& pool, Map& rMap )
-                : CppUnitMini::TestThread( pool )
-                , m_Map( rMap )
-            {}
-            Inserter( Inserter& src )
-                : CppUnitMini::TestThread( src )
-                , m_Map( src.m_Map )
-            {}
-
-            Map_InsDel_Item_string&  getTest()
-            {
-                return reinterpret_cast<Map_InsDel_Item_string&>( m_Pool.m_Test );
-            }
-
-            virtual void init() { cds::threading::Manager::attachThread()   ; }
-            virtual void fini() { cds::threading::Manager::detachThread()   ; }
-
-            virtual void test()
-            {
-                Map& rMap = m_Map;
-
-                m_nInsertSuccess =
-                    m_nInsertFailed = 0;
-
-                size_t nGoalItem = c_nGoalItem;
-                std::string strGoal = (*getTest().m_parrString)[nGoalItem];
-
-                for ( size_t nAttempt = 0; nAttempt < c_nAttemptCount; ) {
-                    if ( rMap.insert( strGoal, nGoalItem )) {
-                        ++m_nInsertSuccess;
-                        ++nAttempt;
-                    }
-                    else
-                        ++m_nInsertFailed;
-                }
-            }
-        };
-
-        template <class Map>
-        class Deleter: public CppUnitMini::TestThread
-        {
-            Map&     m_Map;
-
-            struct erase_cleaner {
-                void operator ()(std::pair<typename Map::key_type const, typename Map::mapped_type>& val )
-                {
-                    val.second = 0;
-                }
-                // for boost::container::flat_map
-                void operator ()(std::pair< typename std::remove_const< typename Map::key_type >::type, typename Map::mapped_type>& val )
-                {
-                    val.second = 0;
-                }
-                // for BronsonAVLTreeMap
-                void operator()( typename Map::key_type const& /*key*/, typename Map::mapped_type& val )
-                {
-                    val = 0;
-                }
-            };
-
-            virtual Deleter *    clone()
-            {
-                return new Deleter( *this );
-            }
-        public:
-            size_t  m_nDeleteSuccess;
-            size_t  m_nDeleteFailed;
-
-        public:
-            Deleter( CppUnitMini::ThreadPool& pool, Map& rMap )
-                : CppUnitMini::TestThread( pool )
-                , m_Map( rMap )
-            {}
-            Deleter( Deleter& src )
-                : CppUnitMini::TestThread( src )
-                , m_Map( src.m_Map )
-            {}
-
-            Map_InsDel_Item_string&  getTest()
-            {
-                return reinterpret_cast<Map_InsDel_Item_string&>( m_Pool.m_Test );
-            }
-
-            virtual void init() { cds::threading::Manager::attachThread()   ; }
-            virtual void fini() { cds::threading::Manager::detachThread()   ; }
-
-            virtual void test()
-            {
-                Map& rMap = m_Map;
-
-                m_nDeleteSuccess =
-                    m_nDeleteFailed = 0;
-
-                size_t nGoalItem = c_nGoalItem;
-                std::string strGoal = (*getTest().m_parrString)[nGoalItem];
-
-                for ( size_t nAttempt = 0; nAttempt < c_nAttemptCount; ) {
-                    if ( rMap.erase( strGoal, erase_cleaner() )) {
-                        ++m_nDeleteSuccess;
-                        ++nAttempt;
-                    }
-                    else
-                        ++m_nDeleteFailed;
-                }
-            }
-        };
-
-    protected:
-
-        template <class Map>
-        void do_test( Map& testMap )
-        {
-            typedef Inserter<Map>       InserterThread;
-            typedef Deleter<Map>        DeleterThread;
-            cds::OS::Timer    timer;
-
-            // Fill the map
-            CPPUNIT_MSG( "  Fill map (" << c_nMapSize << " items)...");
-            timer.reset();
-            for ( size_t i = 0; i < c_nMapSize; ++i ) {
-                CPPUNIT_ASSERT_EX( testMap.insert( (*m_parrString)[i], i ), i );
-            }
-            CPPUNIT_MSG( "   Duration=" << timer.duration() );
-
-            CPPUNIT_MSG( "  Insert/delete the key " << c_nGoalItem << " (" << c_nAttemptCount << " successful times)...");
-            CppUnitMini::ThreadPool pool( *this );
-            pool.add( new InserterThread( pool, testMap ), (c_nThreadCount + 1) / 2 );
-            pool.add( new DeleterThread( pool, testMap ), (c_nThreadCount + 1) / 2 );
-            pool.run();
-            CPPUNIT_MSG( "   Duration=" << pool.avgDuration() );
-
-            size_t nInsertSuccess = 0;
-            size_t nInsertFailed = 0;
-            size_t nDeleteSuccess = 0;
-            size_t nDeleteFailed = 0;
-            for ( CppUnitMini::ThreadPool::iterator it = pool.begin(); it != pool.end(); ++it ) {
-                InserterThread * pThread = dynamic_cast<InserterThread *>( *it );
-                if ( pThread ) {
-                    CPPUNIT_CHECK( pThread->m_nInsertSuccess == c_nAttemptCount );
-                    nInsertSuccess += pThread->m_nInsertSuccess;
-                    nInsertFailed += pThread->m_nInsertFailed;
-                }
-                else {
-                    DeleterThread * p = static_cast<DeleterThread *>( *it );
-                    CPPUNIT_CHECK( p->m_nDeleteSuccess == c_nAttemptCount );
-                    nDeleteSuccess += p->m_nDeleteSuccess;
-                    nDeleteFailed += p->m_nDeleteFailed;
-                }
-            }
-            CPPUNIT_CHECK_EX( nInsertSuccess == nDeleteSuccess, "nInsertSuccess=" << nInsertSuccess << ", nDeleteSuccess=" << nDeleteSuccess );
-            CPPUNIT_MSG( "    Totals: Ins fail=" << nInsertFailed << " Del fail=" << nDeleteFailed );
-
-            // Check if the map contains all items
-            CPPUNIT_MSG( "    Check if the map contains all items" );
-            timer.reset();
-            for ( size_t i = 0; i < c_nMapSize; ++i ) {
-                CPPUNIT_CHECK_EX( testMap.find( (*m_parrString)[i] ), "Key \"" << (*m_parrString)[i] << "\" not found" );
-            }
-            CPPUNIT_MSG( "    Duration=" << timer.duration() );
-
-            check_before_cleanup( testMap );
-
-            testMap.clear();
-            additional_check( testMap );
-            print_stat( testMap );
-            additional_cleanup( testMap );
-        }
-
-        template <class Map>
-        void test()
-        {
-            m_parrString = &CppUnitMini::TestCase::getTestStrings();
-            if ( c_nMapSize > m_parrString->size() )
-                c_nMapSize = m_parrString->size();
-            if ( c_nGoalItem > m_parrString->size() )
-                c_nGoalItem = m_parrString->size() / 2;
-
-            CPPUNIT_MSG( "Thread count= " << c_nThreadCount
-                << " pass count=" << c_nAttemptCount
-                << " map size=" << c_nMapSize
-                );
-
-            for ( size_t nLoadFactor = 1; nLoadFactor <= c_nMaxLoadFactor; nLoadFactor *= 2 ) {
-                CPPUNIT_MSG( "Load factor=" << nLoadFactor );
-                Map  testMap( c_nMapSize, nLoadFactor );
-                do_test( testMap );
-                if ( c_bPrintGCState )
-                    print_gc_state();
-            }
-        }
-
-        template <typename Map>
-        void test_nolf()
-        {
-            m_parrString = &CppUnitMini::TestCase::getTestStrings();
-            if ( c_nMapSize > m_parrString->size() )
-                c_nMapSize = m_parrString->size();
-            if ( c_nGoalItem > m_parrString->size() )
-                c_nGoalItem = m_parrString->size() / 2;
-
-            CPPUNIT_MSG( "Thread count= " << c_nThreadCount
-                << " pass count=" << c_nAttemptCount
-                << " map size=" << c_nMapSize
-                );
-
-            Map testMap;
-            do_test( testMap );
-            if ( c_bPrintGCState )
-                print_gc_state();
-        }
-
-        void setUpParams( const CppUnitMini::TestCfg& cfg ) {
-            c_nThreadCount = cfg.getULong("ThreadCount", 8 )        ; // thread count
-            c_nMapSize = cfg.getULong("MapSize", 1000000 );
-            c_nGoalItem = cfg.getULong("GoalItemIndex", (unsigned long) (c_nMapSize / 2) );
-            c_nAttemptCount = cfg.getULong("AttemptCount", 100000 );
-            c_nMaxLoadFactor = cfg.getULong("MaxLoadFactor", 8 );
-            c_bPrintGCState = cfg.getBool("PrintGCStateFlag", true );
-        }
-
-#   include "map2/map_defs.h"
-        CDSUNIT_DECLARE_MichaelMap
-        CDSUNIT_DECLARE_SplitList
-        CDSUNIT_DECLARE_SkipListMap
-        CDSUNIT_DECLARE_EllenBinTreeMap
-        CDSUNIT_DECLARE_BronsonAVLTreeMap
-        CDSUNIT_DECLARE_StripedMap
-        CDSUNIT_DECLARE_RefinableMap
-        CDSUNIT_DECLARE_CuckooMap
-        CDSUNIT_DECLARE_StdMap
-
-        CPPUNIT_TEST_SUITE( Map_InsDel_Item_string )
-            CDSUNIT_TEST_MichaelMap
-            CDSUNIT_TEST_SplitList
-            CDSUNIT_TEST_SkipListMap
-            CDSUNIT_TEST_EllenBinTreeMap
-            CDSUNIT_TEST_BronsonAVLTreeMap
-            CDSUNIT_TEST_StripedMap
-            CDSUNIT_TEST_RefinableMap
-            CDSUNIT_TEST_CuckooMap
-            //CDSUNIT_TEST_StdMap       // very slow!!!
-        CPPUNIT_TEST_SUITE_END()
-
-    };
-
-    CPPUNIT_TEST_SUITE_REGISTRATION( Map_InsDel_Item_string );
+        setUpParams( m_Cfg.get( "Map_InsDel_Item_string" ));
+
+        run_MichaelMap(in_name, invert);
+        run_SplitList(in_name, invert);
+        run_SkipListMap(in_name, invert);
+        run_EllenBinTreeMap(in_name, invert);
+        run_BronsonAVLTreeMap(in_name, invert);
+        run_StripedMap(in_name, invert);
+        run_RefinableMap(in_name, invert);
+        run_CuckooMap(in_name, invert);
+
+        endTestCase();
+    }
 } // namespace map2
diff --git a/tests/unit/map2/map_insdel_item_string.h b/tests/unit/map2/map_insdel_item_string.h
new file mode 100644 (file)
index 0000000..b42450c
--- /dev/null
@@ -0,0 +1,279 @@
+//$$CDS-header$$
+
+#include "map2/map_types.h"
+#include "cppunit/thread.h"
+
+#include <vector>
+
+namespace map2 {
+
+#   define TEST_MAP(X)         void X() { test<MapTypes<key_type, value_type>::X >()    ; }
+#   define TEST_MAP_NOLF(X)    void X() { test_nolf<MapTypes<key_type, value_type>::X >()    ; }
+#   define TEST_MAP_EXTRACT(X)  TEST_MAP(X)
+#   define TEST_MAP_NOLF_EXTRACT(X) TEST_MAP_NOLF(X)
+
+    class Map_InsDel_Item_string: public CppUnitMini::TestCase
+    {
+        static size_t  c_nMapSize;      // map size
+        static size_t  c_nThreadCount;  // thread count
+        static size_t  c_nGoalItem;
+        static size_t  c_nAttemptCount; // count of SUCCESS insert/delete for each thread
+        static size_t  c_nMaxLoadFactor;// maximum load factor
+        static bool    c_bPrintGCState;
+
+        typedef CppUnitMini::TestCase Base;
+        typedef std::string  key_type;
+        typedef size_t  value_type;
+
+        const std::vector<std::string> *  m_parrString;
+
+        template <class Map>
+        class Inserter: public CppUnitMini::TestThread
+        {
+            Map&     m_Map;
+
+            virtual Inserter *    clone()
+            {
+                return new Inserter( *this );
+            }
+        public:
+            size_t  m_nInsertSuccess;
+            size_t  m_nInsertFailed;
+
+        public:
+            Inserter( CppUnitMini::ThreadPool& pool, Map& rMap )
+                : CppUnitMini::TestThread( pool )
+                , m_Map( rMap )
+            {}
+            Inserter( Inserter& src )
+                : CppUnitMini::TestThread( src )
+                , m_Map( src.m_Map )
+            {}
+
+            Map_InsDel_Item_string&  getTest()
+            {
+                return reinterpret_cast<Map_InsDel_Item_string&>( m_Pool.m_Test );
+            }
+
+            virtual void init() { cds::threading::Manager::attachThread()   ; }
+            virtual void fini() { cds::threading::Manager::detachThread()   ; }
+
+            virtual void test()
+            {
+                Map& rMap = m_Map;
+
+                m_nInsertSuccess =
+                    m_nInsertFailed = 0;
+
+                size_t nGoalItem = c_nGoalItem;
+                std::string strGoal = (*getTest().m_parrString)[nGoalItem];
+
+                for ( size_t nAttempt = 0; nAttempt < c_nAttemptCount; ) {
+                    if ( rMap.insert( strGoal, nGoalItem )) {
+                        ++m_nInsertSuccess;
+                        ++nAttempt;
+                    }
+                    else
+                        ++m_nInsertFailed;
+                }
+            }
+        };
+
+        template <class Map>
+        class Deleter: public CppUnitMini::TestThread
+        {
+            Map&     m_Map;
+
+            struct erase_cleaner {
+                void operator ()(std::pair<typename Map::key_type const, typename Map::mapped_type>& val )
+                {
+                    val.second = 0;
+                }
+                // for boost::container::flat_map
+                void operator ()(std::pair< typename std::remove_const< typename Map::key_type >::type, typename Map::mapped_type>& val )
+                {
+                    val.second = 0;
+                }
+                // for BronsonAVLTreeMap
+                void operator()( typename Map::key_type const& /*key*/, typename Map::mapped_type& val )
+                {
+                    val = 0;
+                }
+            };
+
+            virtual Deleter *    clone()
+            {
+                return new Deleter( *this );
+            }
+        public:
+            size_t  m_nDeleteSuccess;
+            size_t  m_nDeleteFailed;
+
+        public:
+            Deleter( CppUnitMini::ThreadPool& pool, Map& rMap )
+                : CppUnitMini::TestThread( pool )
+                , m_Map( rMap )
+            {}
+            Deleter( Deleter& src )
+                : CppUnitMini::TestThread( src )
+                , m_Map( src.m_Map )
+            {}
+
+            Map_InsDel_Item_string&  getTest()
+            {
+                return reinterpret_cast<Map_InsDel_Item_string&>( m_Pool.m_Test );
+            }
+
+            virtual void init() { cds::threading::Manager::attachThread()   ; }
+            virtual void fini() { cds::threading::Manager::detachThread()   ; }
+
+            virtual void test()
+            {
+                Map& rMap = m_Map;
+
+                m_nDeleteSuccess =
+                    m_nDeleteFailed = 0;
+
+                size_t nGoalItem = c_nGoalItem;
+                std::string strGoal = (*getTest().m_parrString)[nGoalItem];
+
+                for ( size_t nAttempt = 0; nAttempt < c_nAttemptCount; ) {
+                    if ( rMap.erase( strGoal, erase_cleaner() )) {
+                        ++m_nDeleteSuccess;
+                        ++nAttempt;
+                    }
+                    else
+                        ++m_nDeleteFailed;
+                }
+            }
+        };
+
+    protected:
+
+        template <class Map>
+        void do_test( Map& testMap )
+        {
+            typedef Inserter<Map>       InserterThread;
+            typedef Deleter<Map>        DeleterThread;
+            cds::OS::Timer    timer;
+
+            // Fill the map
+            CPPUNIT_MSG( "  Fill map (" << c_nMapSize << " items)...");
+            timer.reset();
+            for ( size_t i = 0; i < c_nMapSize; ++i ) {
+                CPPUNIT_ASSERT_EX( testMap.insert( (*m_parrString)[i], i ), i );
+            }
+            CPPUNIT_MSG( "   Duration=" << timer.duration() );
+
+            CPPUNIT_MSG( "  Insert/delete the key " << c_nGoalItem << " (" << c_nAttemptCount << " successful times)...");
+            CppUnitMini::ThreadPool pool( *this );
+            pool.add( new InserterThread( pool, testMap ), (c_nThreadCount + 1) / 2 );
+            pool.add( new DeleterThread( pool, testMap ), (c_nThreadCount + 1) / 2 );
+            pool.run();
+            CPPUNIT_MSG( "   Duration=" << pool.avgDuration() );
+
+            size_t nInsertSuccess = 0;
+            size_t nInsertFailed = 0;
+            size_t nDeleteSuccess = 0;
+            size_t nDeleteFailed = 0;
+            for ( CppUnitMini::ThreadPool::iterator it = pool.begin(); it != pool.end(); ++it ) {
+                InserterThread * pThread = dynamic_cast<InserterThread *>( *it );
+                if ( pThread ) {
+                    CPPUNIT_CHECK( pThread->m_nInsertSuccess == c_nAttemptCount );
+                    nInsertSuccess += pThread->m_nInsertSuccess;
+                    nInsertFailed += pThread->m_nInsertFailed;
+                }
+                else {
+                    DeleterThread * p = static_cast<DeleterThread *>( *it );
+                    CPPUNIT_CHECK( p->m_nDeleteSuccess == c_nAttemptCount );
+                    nDeleteSuccess += p->m_nDeleteSuccess;
+                    nDeleteFailed += p->m_nDeleteFailed;
+                }
+            }
+            CPPUNIT_CHECK_EX( nInsertSuccess == nDeleteSuccess, "nInsertSuccess=" << nInsertSuccess << ", nDeleteSuccess=" << nDeleteSuccess );
+            CPPUNIT_MSG( "    Totals: Ins fail=" << nInsertFailed << " Del fail=" << nDeleteFailed );
+
+            // Check if the map contains all items
+            CPPUNIT_MSG( "    Check if the map contains all items" );
+            timer.reset();
+            for ( size_t i = 0; i < c_nMapSize; ++i ) {
+                CPPUNIT_CHECK_EX( testMap.find( (*m_parrString)[i] ), "Key \"" << (*m_parrString)[i] << "\" not found" );
+            }
+            CPPUNIT_MSG( "    Duration=" << timer.duration() );
+
+            check_before_cleanup( testMap );
+
+            testMap.clear();
+            additional_check( testMap );
+            print_stat( testMap );
+            additional_cleanup( testMap );
+        }
+
+        template <class Map>
+        void test()
+        {
+            m_parrString = &CppUnitMini::TestCase::getTestStrings();
+            if ( c_nMapSize > m_parrString->size() )
+                c_nMapSize = m_parrString->size();
+            if ( c_nGoalItem > m_parrString->size() )
+                c_nGoalItem = m_parrString->size() / 2;
+
+            CPPUNIT_MSG( "Thread count= " << c_nThreadCount
+                << " pass count=" << c_nAttemptCount
+                << " map size=" << c_nMapSize
+                );
+
+            for ( size_t nLoadFactor = 1; nLoadFactor <= c_nMaxLoadFactor; nLoadFactor *= 2 ) {
+                CPPUNIT_MSG( "Load factor=" << nLoadFactor );
+                Map  testMap( c_nMapSize, nLoadFactor );
+                do_test( testMap );
+                if ( c_bPrintGCState )
+                    print_gc_state();
+            }
+        }
+
+        template <typename Map>
+        void test_nolf()
+        {
+            m_parrString = &CppUnitMini::TestCase::getTestStrings();
+            if ( c_nMapSize > m_parrString->size() )
+                c_nMapSize = m_parrString->size();
+            if ( c_nGoalItem > m_parrString->size() )
+                c_nGoalItem = m_parrString->size() / 2;
+
+            CPPUNIT_MSG( "Thread count= " << c_nThreadCount
+                << " pass count=" << c_nAttemptCount
+                << " map size=" << c_nMapSize
+                );
+
+            Map testMap;
+            do_test( testMap );
+            if ( c_bPrintGCState )
+                print_gc_state();
+        }
+
+        void setUpParams( const CppUnitMini::TestCfg& cfg );
+
+        void run_MichaelMap(const char *in_name, bool invert = false);
+        void run_SplitList(const char *in_name, bool invert = false);
+        void run_SkipListMap(const char *in_name, bool invert = false);
+        void run_StripedMap(const char *in_name, bool invert = false);
+        void run_RefinableMap(const char *in_name, bool invert = false);
+        void run_CuckooMap(const char *in_name, bool invert = false);
+        void run_EllenBinTreeMap(const char *in_name, bool invert = false);
+        void run_BronsonAVLTreeMap(const char *in_name, bool invert = false);
+
+        virtual void myRun(const char *in_name, bool invert = false);
+
+#   include "map2/map_defs.h"
+        CDSUNIT_DECLARE_MichaelMap
+        CDSUNIT_DECLARE_SplitList
+        CDSUNIT_DECLARE_SkipListMap
+        CDSUNIT_DECLARE_EllenBinTreeMap
+        CDSUNIT_DECLARE_BronsonAVLTreeMap
+        CDSUNIT_DECLARE_StripedMap
+        CDSUNIT_DECLARE_RefinableMap
+        CDSUNIT_DECLARE_CuckooMap
+        //CDSUNIT_DECLARE_StdMap  // very slow!
+    };
+} // namespace map2
diff --git a/tests/unit/map2/map_insdel_item_string_bronsonavltree.cpp b/tests/unit/map2/map_insdel_item_string_bronsonavltree.cpp
new file mode 100644 (file)
index 0000000..57c5e82
--- /dev/null
@@ -0,0 +1,9 @@
+//$$CDS-header$$
+
+#include "map2/map_insdel_item_string.h"
+
+namespace map2 {
+    CPPUNIT_TEST_SUITE_PART( Map_InsDel_Item_string, run_BronsonAVLTreeMap )
+        CDSUNIT_TEST_BronsonAVLTreeMap
+    CPPUNIT_TEST_SUITE_END_PART()
+} // namespace map2
diff --git a/tests/unit/map2/map_insdel_item_string_cuckoo.cpp b/tests/unit/map2/map_insdel_item_string_cuckoo.cpp
new file mode 100644 (file)
index 0000000..a7ec0dd
--- /dev/null
@@ -0,0 +1,9 @@
+//$$CDS-header$$
+
+#include "map2/map_insdel_item_string.h"
+
+namespace map2 {
+    CPPUNIT_TEST_SUITE_PART( Map_InsDel_Item_string, run_CuckooMap )
+        CDSUNIT_TEST_CuckooMap
+    CPPUNIT_TEST_SUITE_END_PART()
+} // namespace map2
diff --git a/tests/unit/map2/map_insdel_item_string_ellentree.cpp b/tests/unit/map2/map_insdel_item_string_ellentree.cpp
new file mode 100644 (file)
index 0000000..c2fff3f
--- /dev/null
@@ -0,0 +1,9 @@
+//$$CDS-header$$
+
+#include "map2/map_insdel_item_string.h"
+
+namespace map2 {
+    CPPUNIT_TEST_SUITE_PART( Map_InsDel_Item_string, run_EllenBinTreeMap )
+        CDSUNIT_TEST_EllenBinTreeMap
+    CPPUNIT_TEST_SUITE_END_PART()
+} // namespace map2
diff --git a/tests/unit/map2/map_insdel_item_string_michael.cpp b/tests/unit/map2/map_insdel_item_string_michael.cpp
new file mode 100644 (file)
index 0000000..e2a17a2
--- /dev/null
@@ -0,0 +1,9 @@
+//$$CDS-header$$
+
+#include "map2/map_insdel_item_string.h"
+
+namespace map2 {
+    CPPUNIT_TEST_SUITE_PART( Map_InsDel_Item_string, run_MichaelMap )
+        CDSUNIT_TEST_MichaelMap
+    CPPUNIT_TEST_SUITE_END_PART()
+} // namespace map2
diff --git a/tests/unit/map2/map_insdel_item_string_refinable.cpp b/tests/unit/map2/map_insdel_item_string_refinable.cpp
new file mode 100644 (file)
index 0000000..2d5819c
--- /dev/null
@@ -0,0 +1,9 @@
+//$$CDS-header$$
+
+#include "map2/map_insdel_item_string.h"
+
+namespace map2 {
+    CPPUNIT_TEST_SUITE_PART( Map_InsDel_Item_string, run_RefinableMap )
+        CDSUNIT_TEST_RefinableMap
+    CPPUNIT_TEST_SUITE_END_PART()
+} // namespace map2
diff --git a/tests/unit/map2/map_insdel_item_string_skip.cpp b/tests/unit/map2/map_insdel_item_string_skip.cpp
new file mode 100644 (file)
index 0000000..4a3fa18
--- /dev/null
@@ -0,0 +1,9 @@
+//$$CDS-header$$
+
+#include "map2/map_insdel_item_string.h"
+
+namespace map2 {
+    CPPUNIT_TEST_SUITE_PART( Map_InsDel_Item_string, run_SkipListMap )
+        CDSUNIT_TEST_SkipListMap
+    CPPUNIT_TEST_SUITE_END_PART()
+} // namespace map2
diff --git a/tests/unit/map2/map_insdel_item_string_split.cpp b/tests/unit/map2/map_insdel_item_string_split.cpp
new file mode 100644 (file)
index 0000000..ebb2bf0
--- /dev/null
@@ -0,0 +1,9 @@
+//$$CDS-header$$
+
+#include "map2/map_insdel_item_string.h"
+
+namespace map2 {
+    CPPUNIT_TEST_SUITE_PART( Map_InsDel_Item_string, run_SplitList )
+        CDSUNIT_TEST_SplitList
+    CPPUNIT_TEST_SUITE_END_PART()
+} // namespace map2
diff --git a/tests/unit/map2/map_insdel_item_string_striped.cpp b/tests/unit/map2/map_insdel_item_string_striped.cpp
new file mode 100644 (file)
index 0000000..be0ba3d
--- /dev/null
@@ -0,0 +1,9 @@
+//$$CDS-header$$
+
+#include "map2/map_insdel_item_string.h"
+
+namespace map2 {
+    CPPUNIT_TEST_SUITE_PART( Map_InsDel_Item_string, run_StripedMap )
+        CDSUNIT_TEST_StripedMap
+    CPPUNIT_TEST_SUITE_END_PART()
+} // namespace map2
index 6fab9045e1c78812c49e0cb0c7c16c766544de34..7be437c29cad51d61285e674aa8cca0373593610 100644 (file)
 //$$CDS-header$$
 
-#include "map2/map_types.h"
-#include "cppunit/thread.h"
-
-#include <vector>
+#include "map2/map_insdel_string.h"
 
 namespace map2 {
+    CPPUNIT_TEST_SUITE_REGISTRATION( Map_InsDel_string );
 
-#   define TEST_MAP(X)         void X() { test<MapTypes<key_type, value_type>::X >()    ; }
-#   define TEST_MAP_NOLF(X)    void X() { test_nolf<MapTypes<key_type, value_type>::X >()    ; }
-#   define TEST_MAP_EXTRACT(X)  TEST_MAP(X)
-#   define TEST_MAP_NOLF_EXTRACT(X) TEST_MAP_NOLF(X)
+    size_t Map_InsDel_string::c_nMapSize = 1000000;
+    size_t Map_InsDel_string::c_nInsertThreadCount = 4;
+    size_t Map_InsDel_string::c_nDeleteThreadCount = 4;
+    size_t Map_InsDel_string::c_nThreadPassCount = 4;
+    size_t Map_InsDel_string::c_nMaxLoadFactor = 8;
+    bool   Map_InsDel_string::c_bPrintGCState = true;
 
-    namespace {
-        static size_t  c_nMapSize = 1000000    ;  // map size
-        static size_t  c_nInsertThreadCount = 4;  // count of insertion thread
-        static size_t  c_nDeleteThreadCount = 4;  // count of deletion thread
-        static size_t  c_nThreadPassCount = 4  ;  // pass count for each thread
-        static size_t  c_nMaxLoadFactor = 8    ;  // maximum load factor
-        static bool    c_bPrintGCState = true;
+    void Map_InsDel_string::setUpParams( const CppUnitMini::TestCfg& cfg ) 
+    {
+        c_nInsertThreadCount = cfg.getSizeT("InsertThreadCount", c_nInsertThreadCount );
+        c_nDeleteThreadCount = cfg.getSizeT("DeleteThreadCount", c_nDeleteThreadCount );
+        c_nThreadPassCount = cfg.getSizeT("ThreadPassCount", c_nThreadPassCount );
+        c_nMapSize = cfg.getSizeT("MapSize", c_nMapSize );
+        c_nMaxLoadFactor = cfg.getSizeT("MaxLoadFactor", c_nMaxLoadFactor );
+        c_bPrintGCState = cfg.getBool("PrintGCStateFlag", c_bPrintGCState );
     }
 
-    class Map_InsDel_string: public CppUnitMini::TestCase
+    void Map_InsDel_string::myRun(const char *in_name, bool invert /*= false*/)
     {
-        typedef std::string key_type;
-        typedef size_t      value_type;
-
-        const std::vector<std::string> *  m_parrString;
-
-        template <class MAP>
-        class Inserter: public CppUnitMini::TestThread
-        {
-            MAP&     m_Map;
-
-            virtual Inserter *    clone()
-            {
-                return new Inserter( *this );
-            }
-        public:
-            size_t  m_nInsertSuccess;
-            size_t  m_nInsertFailed;
-
-        public:
-            Inserter( CppUnitMini::ThreadPool& pool, MAP& rMap )
-                : CppUnitMini::TestThread( pool )
-                , m_Map( rMap )
-            {}
-            Inserter( Inserter& src )
-                : CppUnitMini::TestThread( src )
-                , m_Map( src.m_Map )
-            {}
-
-            Map_InsDel_string&  getTest()
-            {
-                return reinterpret_cast<Map_InsDel_string&>( m_Pool.m_Test );
-            }
-
-            virtual void init() { cds::threading::Manager::attachThread()   ; }
-            virtual void fini() { cds::threading::Manager::detachThread()   ; }
-
-            virtual void test()
-            {
-                MAP& rMap = m_Map;
-
-                m_nInsertSuccess =
-                    m_nInsertFailed = 0;
-
-                const std::vector<std::string>& arrString = *getTest().m_parrString;
-                size_t nArrSize = arrString.size();
-
-                if ( m_nThreadNo & 1 ) {
-                    for ( size_t nPass = 0; nPass < c_nThreadPassCount; ++nPass ) {
-                        for ( size_t nItem = 0; nItem < c_nMapSize; ++nItem ) {
-                            if ( rMap.insert( arrString[nItem % nArrSize], nItem * 8 ) )
-                                ++m_nInsertSuccess;
-                            else
-                                ++m_nInsertFailed;
-                        }
-                    }
-                }
-                else {
-                    for ( size_t nPass = 0; nPass < c_nThreadPassCount; ++nPass ) {
-                        for ( size_t nItem = c_nMapSize; nItem > 0; --nItem ) {
-                            if ( rMap.insert( arrString[nItem % nArrSize], nItem * 8 ) )
-                                ++m_nInsertSuccess;
-                            else
-                                ++m_nInsertFailed;
-                        }
-                    }
-                }
-            }
-        };
-
-        template <class MAP>
-        class Deleter: public CppUnitMini::TestThread
-        {
-            MAP&     m_Map;
-
-            virtual Deleter *    clone()
-            {
-                return new Deleter( *this );
-            }
-        public:
-            size_t  m_nDeleteSuccess;
-            size_t  m_nDeleteFailed;
-
-        public:
-            Deleter( CppUnitMini::ThreadPool& pool, MAP& rMap )
-                : CppUnitMini::TestThread( pool )
-                , m_Map( rMap )
-            {}
-            Deleter( Deleter& src )
-                : CppUnitMini::TestThread( src )
-                , m_Map( src.m_Map )
-            {}
-
-            Map_InsDel_string&  getTest()
-            {
-                return reinterpret_cast<Map_InsDel_string&>( m_Pool.m_Test );
-            }
-
-            virtual void init() { cds::threading::Manager::attachThread()   ; }
-            virtual void fini() { cds::threading::Manager::detachThread()   ; }
-
-            virtual void test()
-            {
-                MAP& rMap = m_Map;
-
-                m_nDeleteSuccess =
-                    m_nDeleteFailed = 0;
-
-                const std::vector<std::string>& arrString = *getTest().m_parrString;
-                size_t nArrSize = arrString.size();
-
-                if ( m_nThreadNo & 1 ) {
-                    for ( size_t nPass = 0; nPass < c_nThreadPassCount; ++nPass ) {
-                        for ( size_t nItem = 0; nItem < c_nMapSize; ++nItem ) {
-                            if ( rMap.erase( arrString[nItem % nArrSize] ) )
-                                ++m_nDeleteSuccess;
-                            else
-                                ++m_nDeleteFailed;
-                        }
-                    }
-                }
-                else {
-                    for ( size_t nPass = 0; nPass < c_nThreadPassCount; ++nPass ) {
-                        for ( size_t nItem = c_nMapSize; nItem > 0; --nItem ) {
-                            if ( rMap.erase( arrString[nItem % nArrSize] ) )
-                                ++m_nDeleteSuccess;
-                            else
-                                ++m_nDeleteFailed;
-                        }
-                    }
-                }
-            }
-        };
-
-    protected:
-
-        template <class MAP>
-        void do_test( MAP& testMap )
-        {
-            typedef Inserter<MAP>       InserterThread;
-            typedef Deleter<MAP>        DeleterThread;
-            cds::OS::Timer    timer;
-
-            CppUnitMini::ThreadPool pool( *this );
-            pool.add( new InserterThread( pool, testMap ), c_nInsertThreadCount );
-            pool.add( new DeleterThread( pool, testMap ), c_nDeleteThreadCount );
-            pool.run();
-            CPPUNIT_MSG( "   Duration=" << pool.avgDuration() );
-
-            size_t nInsertSuccess = 0;
-            size_t nInsertFailed = 0;
-            size_t nDeleteSuccess = 0;
-            size_t nDeleteFailed = 0;
-            for ( CppUnitMini::ThreadPool::iterator it = pool.begin(); it != pool.end(); ++it ) {
-                InserterThread * pThread = dynamic_cast<InserterThread *>( *it );
-                if ( pThread ) {
-                    nInsertSuccess += pThread->m_nInsertSuccess;
-                    nInsertFailed += pThread->m_nInsertFailed;
-                }
-                else {
-                    DeleterThread * p = static_cast<DeleterThread *>( *it );
-                    nDeleteSuccess += p->m_nDeleteSuccess;
-                    nDeleteFailed += p->m_nDeleteFailed;
-                }
-            }
-
-            CPPUNIT_MSG( "    Totals: Ins succ=" << nInsertSuccess
-                << " Del succ=" << nDeleteSuccess << "\n"
-                      << "          : Ins fail=" << nInsertFailed
-                << " Del fail=" << nDeleteFailed
-                << " Map size=" << testMap.size()
-                );
-
-            check_before_cleanup( testMap );
-
-            CPPUNIT_MSG( "  Clear map (single-threaded)..." );
-            timer.reset();
-            for ( size_t i = 0; i < m_parrString->size(); ++i )
-                testMap.erase( (*m_parrString)[i] );
-            CPPUNIT_MSG( "   Duration=" << timer.duration() );
-            CPPUNIT_CHECK( testMap.empty() );
-
-            additional_check( testMap );
-            print_stat( testMap );
-            additional_cleanup( testMap );
-        }
-
-        template <class MAP>
-        void test()
-        {
-            m_parrString = &CppUnitMini::TestCase::getTestStrings();
-
-            CPPUNIT_MSG( "Thread count: insert=" << c_nInsertThreadCount
-                << " delete=" << c_nDeleteThreadCount
-                << " pass count=" << c_nThreadPassCount
-                << " map size=" << c_nMapSize
-                );
-
-            for ( size_t nLoadFactor = 1; nLoadFactor <= c_nMaxLoadFactor; nLoadFactor *= 2 ) {
-                CPPUNIT_MSG( "Load factor=" << nLoadFactor );
-                MAP  testMap( c_nMapSize, nLoadFactor );
-                do_test( testMap );
-                if ( c_bPrintGCState )
-                    print_gc_state();
-            }
-        }
-
-        template <class MAP>
-        void test_nolf()
-        {
-            m_parrString = &CppUnitMini::TestCase::getTestStrings();
-
-            CPPUNIT_MSG( "Thread count: insert=" << c_nInsertThreadCount
-                << " delete=" << c_nDeleteThreadCount
-                << " pass count=" << c_nThreadPassCount
-                << " map size=" << c_nMapSize
-                );
-
-            MAP testMap;
-            do_test( testMap );
-            if ( c_bPrintGCState )
-                print_gc_state();
-        }
-
-        void setUpParams( const CppUnitMini::TestCfg& cfg ) {
-            c_nInsertThreadCount = cfg.getULong("InsertThreadCount", 4 );
-            c_nDeleteThreadCount = cfg.getULong("DeleteThreadCount", 4 );
-            c_nThreadPassCount = cfg.getULong("ThreadPassCount", 4 );
-            c_nMapSize = cfg.getULong("MapSize", 1000000 );
-            c_nMaxLoadFactor = cfg.getULong("MaxLoadFactor", 8 );
-            c_bPrintGCState = cfg.getBool("PrintGCStateFlag", true );
-        }
-
-#   include "map2/map_defs.h"
-        CDSUNIT_DECLARE_MichaelMap
-        CDSUNIT_DECLARE_SplitList
-        CDSUNIT_DECLARE_SkipListMap
-        CDSUNIT_DECLARE_EllenBinTreeMap
-        CDSUNIT_DECLARE_BronsonAVLTreeMap
-        CDSUNIT_DECLARE_StripedMap
-        CDSUNIT_DECLARE_RefinableMap
-        CDSUNIT_DECLARE_CuckooMap
-        CDSUNIT_DECLARE_StdMap
-
-        CPPUNIT_TEST_SUITE( Map_InsDel_string )
-            CDSUNIT_TEST_MichaelMap
-            CDSUNIT_TEST_SplitList
-            CDSUNIT_TEST_SkipListMap
-            CDSUNIT_TEST_EllenBinTreeMap
-            CDSUNIT_TEST_BronsonAVLTreeMap
-            CDSUNIT_TEST_StripedMap
-            CDSUNIT_TEST_RefinableMap
-            CDSUNIT_TEST_CuckooMap
-            CDSUNIT_TEST_StdMap
-        CPPUNIT_TEST_SUITE_END()
-
-    };
-
-    CPPUNIT_TEST_SUITE_REGISTRATION( Map_InsDel_string );
+        setUpParams( m_Cfg.get( "Map_InsDel_string" ));
+
+        run_MichaelMap(in_name, invert);
+        run_SplitList(in_name, invert);
+        run_SkipListMap(in_name, invert);
+        run_EllenBinTreeMap(in_name, invert);
+        run_BronsonAVLTreeMap(in_name, invert);
+        run_StripedMap(in_name, invert);
+        run_RefinableMap(in_name, invert);
+        run_CuckooMap(in_name, invert);
+        run_StdMap(in_name, invert);
+
+        endTestCase();
+    }
 } // namespace map2
diff --git a/tests/unit/map2/map_insdel_string.h b/tests/unit/map2/map_insdel_string.h
new file mode 100644 (file)
index 0000000..334b291
--- /dev/null
@@ -0,0 +1,274 @@
+//$$CDS-header$$
+
+#include "map2/map_types.h"
+#include "cppunit/thread.h"
+
+#include <vector>
+
+namespace map2 {
+
+#   define TEST_MAP(X)         void X() { test<MapTypes<key_type, value_type>::X >()    ; }
+#   define TEST_MAP_NOLF(X)    void X() { test_nolf<MapTypes<key_type, value_type>::X >()    ; }
+#   define TEST_MAP_EXTRACT(X)  TEST_MAP(X)
+#   define TEST_MAP_NOLF_EXTRACT(X) TEST_MAP_NOLF(X)
+
+    class Map_InsDel_string: public CppUnitMini::TestCase
+    {
+        static size_t  c_nMapSize;            // map size
+        static size_t  c_nInsertThreadCount;  // count of insertion thread
+        static size_t  c_nDeleteThreadCount;  // count of deletion thread
+        static size_t  c_nThreadPassCount;    // pass count for each thread
+        static size_t  c_nMaxLoadFactor;      // maximum load factor
+        static bool    c_bPrintGCState;
+
+        typedef CppUnitMini::TestCase Base;
+        typedef std::string key_type;
+        typedef size_t      value_type;
+
+        const std::vector<std::string> *  m_parrString;
+
+        template <class MAP>
+        class Inserter: public CppUnitMini::TestThread
+        {
+            MAP&     m_Map;
+
+            virtual Inserter *    clone()
+            {
+                return new Inserter( *this );
+            }
+        public:
+            size_t  m_nInsertSuccess;
+            size_t  m_nInsertFailed;
+
+        public:
+            Inserter( CppUnitMini::ThreadPool& pool, MAP& rMap )
+                : CppUnitMini::TestThread( pool )
+                , m_Map( rMap )
+            {}
+            Inserter( Inserter& src )
+                : CppUnitMini::TestThread( src )
+                , m_Map( src.m_Map )
+            {}
+
+            Map_InsDel_string&  getTest()
+            {
+                return reinterpret_cast<Map_InsDel_string&>( m_Pool.m_Test );
+            }
+
+            virtual void init() { cds::threading::Manager::attachThread()   ; }
+            virtual void fini() { cds::threading::Manager::detachThread()   ; }
+
+            virtual void test()
+            {
+                MAP& rMap = m_Map;
+
+                m_nInsertSuccess =
+                    m_nInsertFailed = 0;
+
+                const std::vector<std::string>& arrString = *getTest().m_parrString;
+                size_t nArrSize = arrString.size();
+
+                if ( m_nThreadNo & 1 ) {
+                    for ( size_t nPass = 0; nPass < c_nThreadPassCount; ++nPass ) {
+                        for ( size_t nItem = 0; nItem < c_nMapSize; ++nItem ) {
+                            if ( rMap.insert( arrString[nItem % nArrSize], nItem * 8 ) )
+                                ++m_nInsertSuccess;
+                            else
+                                ++m_nInsertFailed;
+                        }
+                    }
+                }
+                else {
+                    for ( size_t nPass = 0; nPass < c_nThreadPassCount; ++nPass ) {
+                        for ( size_t nItem = c_nMapSize; nItem > 0; --nItem ) {
+                            if ( rMap.insert( arrString[nItem % nArrSize], nItem * 8 ) )
+                                ++m_nInsertSuccess;
+                            else
+                                ++m_nInsertFailed;
+                        }
+                    }
+                }
+            }
+        };
+
+        template <class MAP>
+        class Deleter: public CppUnitMini::TestThread
+        {
+            MAP&     m_Map;
+
+            virtual Deleter *    clone()
+            {
+                return new Deleter( *this );
+            }
+        public:
+            size_t  m_nDeleteSuccess;
+            size_t  m_nDeleteFailed;
+
+        public:
+            Deleter( CppUnitMini::ThreadPool& pool, MAP& rMap )
+                : CppUnitMini::TestThread( pool )
+                , m_Map( rMap )
+            {}
+            Deleter( Deleter& src )
+                : CppUnitMini::TestThread( src )
+                , m_Map( src.m_Map )
+            {}
+
+            Map_InsDel_string&  getTest()
+            {
+                return reinterpret_cast<Map_InsDel_string&>( m_Pool.m_Test );
+            }
+
+            virtual void init() { cds::threading::Manager::attachThread()   ; }
+            virtual void fini() { cds::threading::Manager::detachThread()   ; }
+
+            virtual void test()
+            {
+                MAP& rMap = m_Map;
+
+                m_nDeleteSuccess =
+                    m_nDeleteFailed = 0;
+
+                const std::vector<std::string>& arrString = *getTest().m_parrString;
+                size_t nArrSize = arrString.size();
+
+                if ( m_nThreadNo & 1 ) {
+                    for ( size_t nPass = 0; nPass < c_nThreadPassCount; ++nPass ) {
+                        for ( size_t nItem = 0; nItem < c_nMapSize; ++nItem ) {
+                            if ( rMap.erase( arrString[nItem % nArrSize] ) )
+                                ++m_nDeleteSuccess;
+                            else
+                                ++m_nDeleteFailed;
+                        }
+                    }
+                }
+                else {
+                    for ( size_t nPass = 0; nPass < c_nThreadPassCount; ++nPass ) {
+                        for ( size_t nItem = c_nMapSize; nItem > 0; --nItem ) {
+                            if ( rMap.erase( arrString[nItem % nArrSize] ) )
+                                ++m_nDeleteSuccess;
+                            else
+                                ++m_nDeleteFailed;
+                        }
+                    }
+                }
+            }
+        };
+
+    protected:
+
+        template <class MAP>
+        void do_test( MAP& testMap )
+        {
+            typedef Inserter<MAP>       InserterThread;
+            typedef Deleter<MAP>        DeleterThread;
+            cds::OS::Timer    timer;
+
+            CppUnitMini::ThreadPool pool( *this );
+            pool.add( new InserterThread( pool, testMap ), c_nInsertThreadCount );
+            pool.add( new DeleterThread( pool, testMap ), c_nDeleteThreadCount );
+            pool.run();
+            CPPUNIT_MSG( "   Duration=" << pool.avgDuration() );
+
+            size_t nInsertSuccess = 0;
+            size_t nInsertFailed = 0;
+            size_t nDeleteSuccess = 0;
+            size_t nDeleteFailed = 0;
+            for ( CppUnitMini::ThreadPool::iterator it = pool.begin(); it != pool.end(); ++it ) {
+                InserterThread * pThread = dynamic_cast<InserterThread *>( *it );
+                if ( pThread ) {
+                    nInsertSuccess += pThread->m_nInsertSuccess;
+                    nInsertFailed += pThread->m_nInsertFailed;
+                }
+                else {
+                    DeleterThread * p = static_cast<DeleterThread *>( *it );
+                    nDeleteSuccess += p->m_nDeleteSuccess;
+                    nDeleteFailed += p->m_nDeleteFailed;
+                }
+            }
+
+            CPPUNIT_MSG( "    Totals: Ins succ=" << nInsertSuccess
+                << " Del succ=" << nDeleteSuccess << "\n"
+                      << "          : Ins fail=" << nInsertFailed
+                << " Del fail=" << nDeleteFailed
+                << " Map size=" << testMap.size()
+                );
+
+            check_before_cleanup( testMap );
+
+            CPPUNIT_MSG( "  Clear map (single-threaded)..." );
+            timer.reset();
+            for ( size_t i = 0; i < m_parrString->size(); ++i )
+                testMap.erase( (*m_parrString)[i] );
+            CPPUNIT_MSG( "   Duration=" << timer.duration() );
+            CPPUNIT_CHECK( testMap.empty() );
+
+            additional_check( testMap );
+            print_stat( testMap );
+            additional_cleanup( testMap );
+        }
+
+        template <class MAP>
+        void test()
+        {
+            m_parrString = &CppUnitMini::TestCase::getTestStrings();
+
+            CPPUNIT_MSG( "Thread count: insert=" << c_nInsertThreadCount
+                << " delete=" << c_nDeleteThreadCount
+                << " pass count=" << c_nThreadPassCount
+                << " map size=" << c_nMapSize
+                );
+
+            for ( size_t nLoadFactor = 1; nLoadFactor <= c_nMaxLoadFactor; nLoadFactor *= 2 ) {
+                CPPUNIT_MSG( "Load factor=" << nLoadFactor );
+                MAP  testMap( c_nMapSize, nLoadFactor );
+                do_test( testMap );
+                if ( c_bPrintGCState )
+                    print_gc_state();
+            }
+        }
+
+        template <class MAP>
+        void test_nolf()
+        {
+            m_parrString = &CppUnitMini::TestCase::getTestStrings();
+
+            CPPUNIT_MSG( "Thread count: insert=" << c_nInsertThreadCount
+                << " delete=" << c_nDeleteThreadCount
+                << " pass count=" << c_nThreadPassCount
+                << " map size=" << c_nMapSize
+                );
+
+            MAP testMap;
+            do_test( testMap );
+            if ( c_bPrintGCState )
+                print_gc_state();
+        }
+
+        void setUpParams( const CppUnitMini::TestCfg& cfg );
+
+        void run_MichaelMap(const char *in_name, bool invert = false);
+        void run_SplitList(const char *in_name, bool invert = false);
+        void run_StripedMap(const char *in_name, bool invert = false);
+        void run_RefinableMap(const char *in_name, bool invert = false);
+        void run_CuckooMap(const char *in_name, bool invert = false);
+        void run_SkipListMap(const char *in_name, bool invert = false);
+        void run_EllenBinTreeMap(const char *in_name, bool invert = false);
+        void run_BronsonAVLTreeMap(const char *in_name, bool invert = false);
+        void run_StdMap(const char *in_name, bool invert = false);
+
+        virtual void myRun(const char *in_name, bool invert = false);
+
+
+#   include "map2/map_defs.h"
+        CDSUNIT_DECLARE_MichaelMap
+        CDSUNIT_DECLARE_SplitList
+        CDSUNIT_DECLARE_SkipListMap
+        CDSUNIT_DECLARE_EllenBinTreeMap
+        CDSUNIT_DECLARE_BronsonAVLTreeMap
+        CDSUNIT_DECLARE_StripedMap
+        CDSUNIT_DECLARE_RefinableMap
+        CDSUNIT_DECLARE_CuckooMap
+        CDSUNIT_DECLARE_StdMap
+    };
+} // namespace map2
diff --git a/tests/unit/map2/map_insdel_string_bronsonavltree.cpp b/tests/unit/map2/map_insdel_string_bronsonavltree.cpp
new file mode 100644 (file)
index 0000000..89fe877
--- /dev/null
@@ -0,0 +1,9 @@
+//$$CDS-header$$
+
+#include "map2/map_insdel_string.h"
+
+namespace map2 {
+    CPPUNIT_TEST_SUITE_PART( Map_InsDel_string, run_BronsonAVLTreeMap )
+        CDSUNIT_TEST_BronsonAVLTreeMap
+    CPPUNIT_TEST_SUITE_END_PART()
+} // namespace map2
diff --git a/tests/unit/map2/map_insdel_string_cuckoo.cpp b/tests/unit/map2/map_insdel_string_cuckoo.cpp
new file mode 100644 (file)
index 0000000..a6b218b
--- /dev/null
@@ -0,0 +1,9 @@
+//$$CDS-header$$
+
+#include "map2/map_insdel_string.h"
+
+namespace map2 {
+    CPPUNIT_TEST_SUITE_PART( Map_InsDel_string, run_CuckooMap )
+        CDSUNIT_TEST_CuckooMap
+    CPPUNIT_TEST_SUITE_END_PART()
+} // namespace map2
diff --git a/tests/unit/map2/map_insdel_string_ellentree.cpp b/tests/unit/map2/map_insdel_string_ellentree.cpp
new file mode 100644 (file)
index 0000000..8fbeeb2
--- /dev/null
@@ -0,0 +1,9 @@
+//$$CDS-header$$
+
+#include "map2/map_insdel_string.h"
+
+namespace map2 {
+    CPPUNIT_TEST_SUITE_PART( Map_InsDel_string, run_EllenBinTreeMap )
+        CDSUNIT_TEST_EllenBinTreeMap
+    CPPUNIT_TEST_SUITE_END_PART()
+} // namespace map2
diff --git a/tests/unit/map2/map_insdel_string_michael.cpp b/tests/unit/map2/map_insdel_string_michael.cpp
new file mode 100644 (file)
index 0000000..b679209
--- /dev/null
@@ -0,0 +1,9 @@
+//$$CDS-header$$
+
+#include "map2/map_insdel_string.h"
+
+namespace map2 {
+    CPPUNIT_TEST_SUITE_PART( Map_InsDel_string, run_MichaelMap )
+        CDSUNIT_TEST_MichaelMap
+    CPPUNIT_TEST_SUITE_END_PART()
+} // namespace map2
diff --git a/tests/unit/map2/map_insdel_string_refinable.cpp b/tests/unit/map2/map_insdel_string_refinable.cpp
new file mode 100644 (file)
index 0000000..0dcd44f
--- /dev/null
@@ -0,0 +1,9 @@
+//$$CDS-header$$
+
+#include "map2/map_insdel_string.h"
+
+namespace map2 {
+    CPPUNIT_TEST_SUITE_PART( Map_InsDel_string, run_RefinableMap )
+        CDSUNIT_TEST_RefinableMap
+    CPPUNIT_TEST_SUITE_END_PART()
+} // namespace map2
diff --git a/tests/unit/map2/map_insdel_string_skip.cpp b/tests/unit/map2/map_insdel_string_skip.cpp
new file mode 100644 (file)
index 0000000..2cfcbf6
--- /dev/null
@@ -0,0 +1,9 @@
+//$$CDS-header$$
+
+#include "map2/map_insdel_string.h"
+
+namespace map2 {
+    CPPUNIT_TEST_SUITE_PART( Map_InsDel_string, run_SkipListMap )
+        CDSUNIT_TEST_SkipListMap
+    CPPUNIT_TEST_SUITE_END_PART()
+} // namespace map2
diff --git a/tests/unit/map2/map_insdel_string_split.cpp b/tests/unit/map2/map_insdel_string_split.cpp
new file mode 100644 (file)
index 0000000..be6342d
--- /dev/null
@@ -0,0 +1,9 @@
+//$$CDS-header$$
+
+#include "map2/map_insdel_string.h"
+
+namespace map2 {
+    CPPUNIT_TEST_SUITE_PART( Map_InsDel_string, run_SplitList )
+        CDSUNIT_TEST_SplitList
+    CPPUNIT_TEST_SUITE_END_PART()
+} // namespace map2
diff --git a/tests/unit/map2/map_insdel_string_std.cpp b/tests/unit/map2/map_insdel_string_std.cpp
new file mode 100644 (file)
index 0000000..f7a7e2b
--- /dev/null
@@ -0,0 +1,9 @@
+//$$CDS-header$$
+
+#include "map2/map_insdel_string.h"
+
+namespace map2 {
+    CPPUNIT_TEST_SUITE_PART( Map_InsDel_string, run_StdMap )
+        CDSUNIT_TEST_StdMap
+    CPPUNIT_TEST_SUITE_END_PART()
+} // namespace map2
diff --git a/tests/unit/map2/map_insdel_string_striped.cpp b/tests/unit/map2/map_insdel_string_striped.cpp
new file mode 100644 (file)
index 0000000..2c772fc
--- /dev/null
@@ -0,0 +1,9 @@
+//$$CDS-header$$
+
+#include "map2/map_insdel_string.h"
+
+namespace map2 {
+    CPPUNIT_TEST_SUITE_PART( Map_InsDel_string, run_StripedMap )
+        CDSUNIT_TEST_StripedMap
+    CPPUNIT_TEST_SUITE_END_PART()
+} // namespace map2
index 83965cb81a858605e6cfe45b702fd73cd1f069e6..28df1fac25e2e7d1cb14c4c0b6372d677c4bd203 100644 (file)
 //$$CDS-header$$
 
-#include "map2/map_types.h"
-#include "cppunit/thread.h"
-#include <algorithm> // random_shuffle
-#include <vector>
+#include "map2/map_insdelfind.h"
 
 namespace map2 {
+    CPPUNIT_TEST_SUITE_REGISTRATION( Map_InsDelFind );
 
-#   define TEST_MAP(X)         void X() { test<MapTypes<key_type, value_type>::X >()    ; }
-#   define TEST_MAP_NOLF(X)    void X() { test_nolf<MapTypes<key_type, value_type>::X >()    ; }
-#   define TEST_MAP_EXTRACT(X)  TEST_MAP(X)
-#   define TEST_MAP_NOLF_EXTRACT(X) TEST_MAP_NOLF(X)
+    size_t  Map_InsDelFind::c_nInitialMapSize = 500000;
+    size_t  Map_InsDelFind::c_nThreadCount = 8;
+    size_t  Map_InsDelFind::c_nMaxLoadFactor = 8;
+    unsigned int Map_InsDelFind::c_nInsertPercentage = 5;
+    unsigned int Map_InsDelFind::c_nDeletePercentage = 5;
+    unsigned int Map_InsDelFind::c_nDuration = 30;
+    bool    Map_InsDelFind::c_bPrintGCState = true;
 
-    namespace {
-        static size_t  c_nInitialMapSize = 500000   ;  // initial map size
-        static size_t  c_nThreadCount = 8           ;  // thread count
-        static size_t  c_nMaxLoadFactor = 8         ;  // maximum load factor
-        static unsigned int c_nInsertPercentage = 5;
-        static unsigned int c_nDeletePercentage = 5;
-        static unsigned int c_nDuration = 30        ;  // test duration, seconds
-        static bool    c_bPrintGCState = true;
+    void Map_InsDelFind::setUpParams( const CppUnitMini::TestCfg& cfg )
+    {
+        c_nInitialMapSize = cfg.getSizeT("InitialMapSize", c_nInitialMapSize );
+        c_nThreadCount = cfg.getSizeT("ThreadCount", c_nThreadCount );
+        c_nMaxLoadFactor = cfg.getSizeT("MaxLoadFactor", c_nMaxLoadFactor );
+        c_nInsertPercentage = cfg.getUInt("InsertPercentage", c_nInsertPercentage );
+        c_nDeletePercentage = cfg.getUInt("DeletePercentage", c_nDeletePercentage );
+        c_nDuration = cfg.getUInt("Duration", c_nDuration );
+        c_bPrintGCState = cfg.getBool("PrintGCStateFlag", c_bPrintGCState );
+
+        if ( c_nThreadCount == 0 )
+            c_nThreadCount = cds::OS::topology::processor_count() * 2;
+
+        CPPUNIT_ASSERT( c_nInsertPercentage + c_nDeletePercentage <= 100 );
+
+        actions * pFirst = m_arrShuffle;
+        actions * pLast = m_arrShuffle + c_nInsertPercentage;
+        std::fill( pFirst, pLast, do_insert );
+        pFirst = pLast;
+        pLast += c_nDeletePercentage;
+        std::fill( pFirst, pLast, do_delete );
+        pFirst = pLast;
+        pLast = m_arrShuffle + sizeof(m_arrShuffle)/sizeof(m_arrShuffle[0]);
+        std::fill( pFirst, pLast, do_find );
+        std::random_shuffle( m_arrShuffle, pLast );
     }
 
-    class Map_InsDelFind: public CppUnitMini::TestCase
+    void Map_InsDelFind::myRun(const char *in_name, bool invert /*= false*/)
     {
-    public:
-        enum actions
-        {
-            do_find,
-            do_insert,
-            do_delete
-        };
-        static const unsigned int c_nShuffleSize = 100;
-        actions m_arrShuffle[c_nShuffleSize];
-
-    protected:
-        typedef size_t  key_type;
-        typedef size_t  value_type;
-
-        template <class MAP>
-        class WorkThread: public CppUnitMini::TestThread
-        {
-            MAP&     m_Map;
-
-            virtual WorkThread *    clone()
-            {
-                return new WorkThread( *this );
-            }
-        public:
-            size_t  m_nInsertSuccess;
-            size_t  m_nInsertFailed;
-            size_t  m_nDeleteSuccess;
-            size_t  m_nDeleteFailed;
-            size_t  m_nFindSuccess;
-            size_t  m_nFindFailed;
-
-        public:
-            WorkThread( CppUnitMini::ThreadPool& pool, MAP& rMap )
-                : CppUnitMini::TestThread( pool )
-                , m_Map( rMap )
-            {}
-            WorkThread( WorkThread& src )
-                : CppUnitMini::TestThread( src )
-                , m_Map( src.m_Map )
-            {}
-
-            Map_InsDelFind&  getTest()
-            {
-                return reinterpret_cast<Map_InsDelFind&>( m_Pool.m_Test );
-            }
-
-            virtual void init() { cds::threading::Manager::attachThread()   ; }
-            virtual void fini() { cds::threading::Manager::detachThread()   ; }
-
-            virtual void test()
-            {
-                MAP& rMap = m_Map;
-
-                m_nInsertSuccess =
-                    m_nInsertFailed =
-                    m_nDeleteSuccess =
-                    m_nDeleteFailed =
-                    m_nFindSuccess =
-                    m_nFindFailed = 0;
-
-                actions * pAct = getTest().m_arrShuffle;
-                unsigned int i = 0;
-                size_t const nNormalize = size_t(-1) / (c_nInitialMapSize * 2);
-
-                size_t nRand = 0;
-                while ( !time_elapsed() ) {
-                    nRand = cds::bitop::RandXorShift(nRand);
-                    size_t n = nRand / nNormalize;
-                    switch ( pAct[i] ) {
-                    case do_find:
-                        if ( rMap.find( n ))
-                            ++m_nFindSuccess;
-                        else
-                            ++m_nFindFailed;
-                        break;
-                    case do_insert:
-                        if ( rMap.insert( n, n ))
-                            ++m_nInsertSuccess;
-                        else
-                            ++m_nInsertFailed;
-                        break;
-                    case do_delete:
-                        if ( rMap.erase( n ))
-                            ++m_nDeleteSuccess;
-                        else
-                            ++m_nDeleteFailed;
-                        break;
-                    }
-
-                    if ( ++i >= c_nShuffleSize )
-                        i = 0;
-                }
-            }
-        };
-
-    protected:
-        template <class MAP>
-        void do_test( MAP& testMap )
-        {
-            typedef WorkThread<MAP> work_thread;
-            cds::OS::Timer    timer;
-
-            // fill map - only odd number
-            {
-                std::vector<size_t> arr;
-                arr.reserve( c_nInitialMapSize );
-                for ( size_t i = 0; i < c_nInitialMapSize; ++i )
-                    arr.push_back( i * 2 + 1);
-                std::random_shuffle( arr.begin(), arr.end() );
-                for ( size_t i = 0; i < c_nInitialMapSize; ++i )
-                    testMap.insert( arr[i], arr[i] );
-            }
-            CPPUNIT_MSG( "   Insert " << c_nInitialMapSize << " items time (single-threaded)=" << timer.duration() );
-
-            timer.reset();
-            CppUnitMini::ThreadPool pool( *this );
-            pool.add( new work_thread( pool, testMap ), c_nThreadCount );
-            pool.run( c_nDuration );
-            //CPPUNIT_MSG( "   Duration=" << pool.avgDuration() );
-
-            size_t nInsertSuccess = 0;
-            size_t nInsertFailed = 0;
-            size_t nDeleteSuccess = 0;
-            size_t nDeleteFailed = 0;
-            size_t nFindSuccess = 0;
-            size_t nFindFailed = 0;
-            for ( CppUnitMini::ThreadPool::iterator it = pool.begin(); it != pool.end(); ++it ) {
-                work_thread * pThread = static_cast<work_thread *>( *it );
-                assert( pThread != nullptr );
-                nInsertSuccess += pThread->m_nInsertSuccess;
-                nInsertFailed += pThread->m_nInsertFailed;
-                nDeleteSuccess += pThread->m_nDeleteSuccess;
-                nDeleteFailed += pThread->m_nDeleteFailed;
-                nFindSuccess += pThread->m_nFindSuccess;
-                nFindFailed += pThread->m_nFindFailed;
-            }
-
-            size_t nTotalOps = nInsertSuccess + nInsertFailed + nDeleteSuccess + nDeleteFailed + nFindSuccess + nFindFailed;
-
-            CPPUNIT_MSG( "  Totals (success/failed): \n\t"
-                      << "      Insert=" << nInsertSuccess << '/' << nInsertFailed << "\n\t"
-                      << "      Delete=" << nDeleteSuccess << '/' << nDeleteFailed << "\n\t"
-                      << "        Find=" << nFindSuccess   << '/' << nFindFailed   << "\n\t"
-                      << "       Speed=" << (nFindSuccess + nFindFailed) / c_nDuration << " find/sec\n\t"
-                      << "             " << (nInsertSuccess + nDeleteSuccess) / c_nDuration << " modify/sec\n\t"
-                      << "   Total ops=" << nTotalOps << "\n\t"
-                      << "       speed=" << nTotalOps / c_nDuration << " ops/sec\n\t"
-                      << "      Map size=" << testMap.size()
-                );
-
-
-            check_before_cleanup( testMap );
-
-            CPPUNIT_MSG( "  Clear map (single-threaded)..." );
-            timer.reset();
-            testMap.clear();
-            CPPUNIT_MSG( "   Duration=" << timer.duration() );
-            CPPUNIT_ASSERT_EX( testMap.empty(), ((long long) testMap.size()) );
-
-            additional_check( testMap );
-            print_stat( testMap );
-            additional_cleanup( testMap );
-        }
-
-        template <class MAP>
-        void test()
-        {
-            CPPUNIT_MSG( "Thread count=" << c_nThreadCount
-                << " initial map size=" << c_nInitialMapSize
-                << " insert=" << c_nInsertPercentage << '%'
-                << " delete=" << c_nDeletePercentage << '%'
-                << " duration=" << c_nDuration << "s"
-                );
-
-            for ( size_t nLoadFactor = 1; nLoadFactor <= c_nMaxLoadFactor; nLoadFactor *= 2 ) {
-                CPPUNIT_MSG( "Load factor=" << nLoadFactor );
-                MAP  testMap( c_nInitialMapSize, nLoadFactor );
-                do_test( testMap );
-                if ( c_bPrintGCState )
-                    print_gc_state();
-            }
-
-        }
-
-        template <class MAP>
-        void test_nolf()
-        {
-            CPPUNIT_MSG( "Thread count=" << c_nThreadCount
-                << " initial map size=" << c_nInitialMapSize
-                << " insert=" << c_nInsertPercentage << '%'
-                << " delete=" << c_nDeletePercentage << '%'
-                << " duration=" << c_nDuration << "s"
-                );
-
-            MAP testMap;
-            do_test( testMap );
-            if ( c_bPrintGCState )
-                print_gc_state();
-        }
-
-        void setUpParams( const CppUnitMini::TestCfg& cfg ) {
-            c_nInitialMapSize = cfg.getULong("InitialMapSize", 500000 );
-            c_nThreadCount = cfg.getULong("ThreadCount", 8 );
-            c_nMaxLoadFactor = cfg.getULong("MaxLoadFactor", 8 );
-            c_nInsertPercentage = cfg.getUInt("InsertPercentage", 5 );
-            c_nDeletePercentage = cfg.getUInt("DeletePercentage", 5 );
-            c_nDuration = cfg.getUInt("Duration", 30 );
-            c_bPrintGCState = cfg.getBool("PrintGCStateFlag", true );
-
-            if ( c_nThreadCount == 0 )
-                c_nThreadCount = cds::OS::topology::processor_count() * 2;
-
-            CPPUNIT_ASSERT( c_nInsertPercentage + c_nDeletePercentage <= 100 );
-
-            actions * pFirst = m_arrShuffle;
-            actions * pLast = m_arrShuffle + c_nInsertPercentage;
-            std::fill( pFirst, pLast, do_insert );
-            pFirst = pLast;
-            pLast += c_nDeletePercentage;
-            std::fill( pFirst, pLast, do_delete );
-            pFirst = pLast;
-            pLast = m_arrShuffle + sizeof(m_arrShuffle)/sizeof(m_arrShuffle[0]);
-            std::fill( pFirst, pLast, do_find );
-            std::random_shuffle( m_arrShuffle, pLast );
-        }
-
-#   include "map2/map_defs.h"
-        CDSUNIT_DECLARE_MichaelMap
-        CDSUNIT_DECLARE_SplitList
-        CDSUNIT_DECLARE_SkipListMap
-        CDSUNIT_DECLARE_EllenBinTreeMap
-        CDSUNIT_DECLARE_BronsonAVLTreeMap
-        CDSUNIT_DECLARE_StripedMap
-        CDSUNIT_DECLARE_RefinableMap
-        CDSUNIT_DECLARE_CuckooMap
-        CDSUNIT_DECLARE_StdMap
-
-        CPPUNIT_TEST_SUITE( Map_InsDelFind )
-            CDSUNIT_TEST_MichaelMap
-            CDSUNIT_TEST_SplitList
-            CDSUNIT_TEST_SkipListMap
-            CDSUNIT_TEST_EllenBinTreeMap
-            CDSUNIT_TEST_BronsonAVLTreeMap
-            CDSUNIT_TEST_StripedMap
-            CDSUNIT_TEST_RefinableMap
-            CDSUNIT_TEST_CuckooMap
-            CDSUNIT_TEST_StdMap
-        CPPUNIT_TEST_SUITE_END()
-    };
-
-    CPPUNIT_TEST_SUITE_REGISTRATION( Map_InsDelFind );
+        setUpParams( m_Cfg.get( "Map_InsDelFind" ));
+
+        run_MichaelMap(in_name, invert);
+        run_SplitList(in_name, invert);
+        run_SkipListMap(in_name, invert);
+        run_EllenBinTreeMap(in_name, invert);
+        run_BronsonAVLTreeMap(in_name, invert);
+        run_StripedMap(in_name, invert);
+        run_RefinableMap(in_name, invert);
+        run_CuckooMap(in_name, invert);
+        run_StdMap(in_name, invert);
+
+        endTestCase();
+    }
 } // namespace map2
diff --git a/tests/unit/map2/map_insdelfind.h b/tests/unit/map2/map_insdelfind.h
new file mode 100644 (file)
index 0000000..c5e36f1
--- /dev/null
@@ -0,0 +1,251 @@
+//$$CDS-header$$
+
+#include "map2/map_types.h"
+#include "cppunit/thread.h"
+#include <algorithm> // random_shuffle
+#include <vector>
+
+namespace map2 {
+
+#   define TEST_MAP(X)         void X() { test<MapTypes<key_type, value_type>::X >()    ; }
+#   define TEST_MAP_NOLF(X)    void X() { test_nolf<MapTypes<key_type, value_type>::X >()    ; }
+#   define TEST_MAP_EXTRACT(X)  TEST_MAP(X)
+#   define TEST_MAP_NOLF_EXTRACT(X) TEST_MAP_NOLF(X)
+
+    class Map_InsDelFind: public CppUnitMini::TestCase
+    {
+        static size_t  c_nInitialMapSize;   // initial map size
+        static size_t  c_nThreadCount;      // thread count
+        static size_t  c_nMaxLoadFactor;    // maximum load factor
+        static unsigned int c_nInsertPercentage;
+        static unsigned int c_nDeletePercentage;
+        static unsigned int c_nDuration;    // test duration, seconds
+        static bool    c_bPrintGCState;
+
+    public:
+        enum actions
+        {
+            do_find,
+            do_insert,
+            do_delete
+        };
+        static const unsigned int c_nShuffleSize = 100;
+        actions m_arrShuffle[c_nShuffleSize];
+
+    protected:
+        typedef CppUnitMini::TestCase Base;
+        typedef size_t  key_type;
+        typedef size_t  value_type;
+
+        template <class MAP>
+        class WorkThread: public CppUnitMini::TestThread
+        {
+            MAP&     m_Map;
+
+            virtual WorkThread *    clone()
+            {
+                return new WorkThread( *this );
+            }
+        public:
+            size_t  m_nInsertSuccess;
+            size_t  m_nInsertFailed;
+            size_t  m_nDeleteSuccess;
+            size_t  m_nDeleteFailed;
+            size_t  m_nFindSuccess;
+            size_t  m_nFindFailed;
+
+        public:
+            WorkThread( CppUnitMini::ThreadPool& pool, MAP& rMap )
+                : CppUnitMini::TestThread( pool )
+                , m_Map( rMap )
+            {}
+            WorkThread( WorkThread& src )
+                : CppUnitMini::TestThread( src )
+                , m_Map( src.m_Map )
+            {}
+
+            Map_InsDelFind&  getTest()
+            {
+                return reinterpret_cast<Map_InsDelFind&>( m_Pool.m_Test );
+            }
+
+            virtual void init() { cds::threading::Manager::attachThread()   ; }
+            virtual void fini() { cds::threading::Manager::detachThread()   ; }
+
+            virtual void test()
+            {
+                MAP& rMap = m_Map;
+
+                m_nInsertSuccess =
+                    m_nInsertFailed =
+                    m_nDeleteSuccess =
+                    m_nDeleteFailed =
+                    m_nFindSuccess =
+                    m_nFindFailed = 0;
+
+                actions * pAct = getTest().m_arrShuffle;
+                unsigned int i = 0;
+                size_t const nNormalize = size_t(-1) / (c_nInitialMapSize * 2);
+
+                size_t nRand = 0;
+                while ( !time_elapsed() ) {
+                    nRand = cds::bitop::RandXorShift(nRand);
+                    size_t n = nRand / nNormalize;
+                    switch ( pAct[i] ) {
+                    case do_find:
+                        if ( rMap.find( n ))
+                            ++m_nFindSuccess;
+                        else
+                            ++m_nFindFailed;
+                        break;
+                    case do_insert:
+                        if ( rMap.insert( n, n ))
+                            ++m_nInsertSuccess;
+                        else
+                            ++m_nInsertFailed;
+                        break;
+                    case do_delete:
+                        if ( rMap.erase( n ))
+                            ++m_nDeleteSuccess;
+                        else
+                            ++m_nDeleteFailed;
+                        break;
+                    }
+
+                    if ( ++i >= c_nShuffleSize )
+                        i = 0;
+                }
+            }
+        };
+
+    protected:
+        template <class MAP>
+        void do_test( MAP& testMap )
+        {
+            typedef WorkThread<MAP> work_thread;
+            cds::OS::Timer    timer;
+
+            // fill map - only odd number
+            {
+                std::vector<size_t> arr;
+                arr.reserve( c_nInitialMapSize );
+                for ( size_t i = 0; i < c_nInitialMapSize; ++i )
+                    arr.push_back( i * 2 + 1);
+                std::random_shuffle( arr.begin(), arr.end() );
+                for ( size_t i = 0; i < c_nInitialMapSize; ++i )
+                    testMap.insert( arr[i], arr[i] );
+            }
+            CPPUNIT_MSG( "   Insert " << c_nInitialMapSize << " items time (single-threaded)=" << timer.duration() );
+
+            timer.reset();
+            CppUnitMini::ThreadPool pool( *this );
+            pool.add( new work_thread( pool, testMap ), c_nThreadCount );
+            pool.run( c_nDuration );
+            //CPPUNIT_MSG( "   Duration=" << pool.avgDuration() );
+
+            size_t nInsertSuccess = 0;
+            size_t nInsertFailed = 0;
+            size_t nDeleteSuccess = 0;
+            size_t nDeleteFailed = 0;
+            size_t nFindSuccess = 0;
+            size_t nFindFailed = 0;
+            for ( CppUnitMini::ThreadPool::iterator it = pool.begin(); it != pool.end(); ++it ) {
+                work_thread * pThread = static_cast<work_thread *>( *it );
+                assert( pThread != nullptr );
+                nInsertSuccess += pThread->m_nInsertSuccess;
+                nInsertFailed += pThread->m_nInsertFailed;
+                nDeleteSuccess += pThread->m_nDeleteSuccess;
+                nDeleteFailed += pThread->m_nDeleteFailed;
+                nFindSuccess += pThread->m_nFindSuccess;
+                nFindFailed += pThread->m_nFindFailed;
+            }
+
+            size_t nTotalOps = nInsertSuccess + nInsertFailed + nDeleteSuccess + nDeleteFailed + nFindSuccess + nFindFailed;
+
+            CPPUNIT_MSG( "  Totals (success/failed): \n\t"
+                      << "      Insert=" << nInsertSuccess << '/' << nInsertFailed << "\n\t"
+                      << "      Delete=" << nDeleteSuccess << '/' << nDeleteFailed << "\n\t"
+                      << "        Find=" << nFindSuccess   << '/' << nFindFailed   << "\n\t"
+                      << "       Speed=" << (nFindSuccess + nFindFailed) / c_nDuration << " find/sec\n\t"
+                      << "             " << (nInsertSuccess + nDeleteSuccess) / c_nDuration << " modify/sec\n\t"
+                      << "   Total ops=" << nTotalOps << "\n\t"
+                      << "       speed=" << nTotalOps / c_nDuration << " ops/sec\n\t"
+                      << "      Map size=" << testMap.size()
+                );
+
+
+            check_before_cleanup( testMap );
+
+            CPPUNIT_MSG( "  Clear map (single-threaded)..." );
+            timer.reset();
+            testMap.clear();
+            CPPUNIT_MSG( "   Duration=" << timer.duration() );
+            CPPUNIT_ASSERT_EX( testMap.empty(), ((long long) testMap.size()) );
+
+            additional_check( testMap );
+            print_stat( testMap );
+            additional_cleanup( testMap );
+        }
+
+        template <class MAP>
+        void test()
+        {
+            CPPUNIT_MSG( "Thread count=" << c_nThreadCount
+                << " initial map size=" << c_nInitialMapSize
+                << " insert=" << c_nInsertPercentage << '%'
+                << " delete=" << c_nDeletePercentage << '%'
+                << " duration=" << c_nDuration << "s"
+                );
+
+            for ( size_t nLoadFactor = 1; nLoadFactor <= c_nMaxLoadFactor; nLoadFactor *= 2 ) {
+                CPPUNIT_MSG( "Load factor=" << nLoadFactor );
+                MAP  testMap( c_nInitialMapSize, nLoadFactor );
+                do_test( testMap );
+                if ( c_bPrintGCState )
+                    print_gc_state();
+            }
+
+        }
+
+        template <class MAP>
+        void test_nolf()
+        {
+            CPPUNIT_MSG( "Thread count=" << c_nThreadCount
+                << " initial map size=" << c_nInitialMapSize
+                << " insert=" << c_nInsertPercentage << '%'
+                << " delete=" << c_nDeletePercentage << '%'
+                << " duration=" << c_nDuration << "s"
+                );
+
+            MAP testMap;
+            do_test( testMap );
+            if ( c_bPrintGCState )
+                print_gc_state();
+        }
+
+        void setUpParams( const CppUnitMini::TestCfg& cfg );
+
+        void run_MichaelMap(const char *in_name, bool invert = false);
+        void run_SplitList(const char *in_name, bool invert = false);
+        void run_StripedMap(const char *in_name, bool invert = false);
+        void run_RefinableMap(const char *in_name, bool invert = false);
+        void run_CuckooMap(const char *in_name, bool invert = false);
+        void run_SkipListMap(const char *in_name, bool invert = false);
+        void run_EllenBinTreeMap(const char *in_name, bool invert = false);
+        void run_BronsonAVLTreeMap(const char *in_name, bool invert = false);
+        void run_StdMap(const char *in_name, bool invert = false);
+
+        virtual void myRun(const char *in_name, bool invert = false);
+
+#   include "map2/map_defs.h"
+        CDSUNIT_DECLARE_MichaelMap
+        CDSUNIT_DECLARE_SplitList
+        CDSUNIT_DECLARE_SkipListMap
+        CDSUNIT_DECLARE_EllenBinTreeMap
+        CDSUNIT_DECLARE_BronsonAVLTreeMap
+        CDSUNIT_DECLARE_StripedMap
+        CDSUNIT_DECLARE_RefinableMap
+        CDSUNIT_DECLARE_CuckooMap
+        CDSUNIT_DECLARE_StdMap
+    };
+} // namespace map2
diff --git a/tests/unit/map2/map_insdelfind_bronsonavltree.cpp b/tests/unit/map2/map_insdelfind_bronsonavltree.cpp
new file mode 100644 (file)
index 0000000..7d1731e
--- /dev/null
@@ -0,0 +1,9 @@
+//$$CDS-header$$
+
+#include "map2/map_insdelfind.h"
+
+namespace map2 {
+    CPPUNIT_TEST_SUITE_PART( Map_InsDelFind, run_BronsonAVLTreeMap )
+        CDSUNIT_TEST_BronsonAVLTreeMap
+    CPPUNIT_TEST_SUITE_END_PART()
+} // namespace map2
diff --git a/tests/unit/map2/map_insdelfind_cuckoo.cpp b/tests/unit/map2/map_insdelfind_cuckoo.cpp
new file mode 100644 (file)
index 0000000..10e1749
--- /dev/null
@@ -0,0 +1,9 @@
+//$$CDS-header$$
+
+#include "map2/map_insdelfind.h"
+
+namespace map2 {
+    CPPUNIT_TEST_SUITE_PART( Map_InsDelFind, run_CuckooMap )
+        CDSUNIT_TEST_CuckooMap
+    CPPUNIT_TEST_SUITE_END_PART()
+} // namespace map2
diff --git a/tests/unit/map2/map_insdelfind_ellentree.cpp b/tests/unit/map2/map_insdelfind_ellentree.cpp
new file mode 100644 (file)
index 0000000..22b6695
--- /dev/null
@@ -0,0 +1,9 @@
+//$$CDS-header$$
+
+#include "map2/map_insdelfind.h"
+
+namespace map2 {
+    CPPUNIT_TEST_SUITE_PART( Map_InsDelFind, run_EllenBinTreeMap )
+        CDSUNIT_TEST_EllenBinTreeMap
+    CPPUNIT_TEST_SUITE_END_PART()
+} // namespace map2
diff --git a/tests/unit/map2/map_insdelfind_michael.cpp b/tests/unit/map2/map_insdelfind_michael.cpp
new file mode 100644 (file)
index 0000000..dbc0487
--- /dev/null
@@ -0,0 +1,9 @@
+//$$CDS-header$$
+
+#include "map2/map_insdelfind.h"
+
+namespace map2 {
+    CPPUNIT_TEST_SUITE_PART( Map_InsDelFind, run_MichaelMap )
+        CDSUNIT_TEST_MichaelMap
+    CPPUNIT_TEST_SUITE_END_PART()
+} // namespace map2
diff --git a/tests/unit/map2/map_insdelfind_refinable.cpp b/tests/unit/map2/map_insdelfind_refinable.cpp
new file mode 100644 (file)
index 0000000..a1bbde4
--- /dev/null
@@ -0,0 +1,9 @@
+//$$CDS-header$$
+
+#include "map2/map_insdelfind.h"
+
+namespace map2 {
+    CPPUNIT_TEST_SUITE_PART( Map_InsDelFind, run_RefinableMap )
+        CDSUNIT_TEST_RefinableMap
+    CPPUNIT_TEST_SUITE_END_PART()
+} // namespace map2
diff --git a/tests/unit/map2/map_insdelfind_skip.cpp b/tests/unit/map2/map_insdelfind_skip.cpp
new file mode 100644 (file)
index 0000000..861ffae
--- /dev/null
@@ -0,0 +1,9 @@
+//$$CDS-header$$
+
+#include "map2/map_insdelfind.h"
+
+namespace map2 {
+    CPPUNIT_TEST_SUITE_PART( Map_InsDelFind, run_SkipListMap )
+        CDSUNIT_TEST_SkipListMap
+    CPPUNIT_TEST_SUITE_END_PART()
+} // namespace map2
diff --git a/tests/unit/map2/map_insdelfind_split.cpp b/tests/unit/map2/map_insdelfind_split.cpp
new file mode 100644 (file)
index 0000000..c5b3c7c
--- /dev/null
@@ -0,0 +1,9 @@
+//$$CDS-header$$
+
+#include "map2/map_insdelfind.h"
+
+namespace map2 {
+    CPPUNIT_TEST_SUITE_PART( Map_InsDelFind, run_SplitList )
+        CDSUNIT_TEST_SplitList
+    CPPUNIT_TEST_SUITE_END_PART()
+} // namespace map2
diff --git a/tests/unit/map2/map_insdelfind_std.cpp b/tests/unit/map2/map_insdelfind_std.cpp
new file mode 100644 (file)
index 0000000..b608a9b
--- /dev/null
@@ -0,0 +1,9 @@
+//$$CDS-header$$
+
+#include "map2/map_insdelfind.h"
+
+namespace map2 {
+    CPPUNIT_TEST_SUITE_PART( Map_InsDelFind, run_StdMap )
+        CDSUNIT_TEST_StdMap
+    CPPUNIT_TEST_SUITE_END_PART()
+} // namespace map2
diff --git a/tests/unit/map2/map_insdelfind_striped.cpp b/tests/unit/map2/map_insdelfind_striped.cpp
new file mode 100644 (file)
index 0000000..9384ffd
--- /dev/null
@@ -0,0 +1,9 @@
+//$$CDS-header$$
+
+#include "map2/map_insdelfind.h"
+
+namespace map2 {
+    CPPUNIT_TEST_SUITE_PART( Map_InsDelFind, run_StripedMap )
+        CDSUNIT_TEST_StripedMap
+    CPPUNIT_TEST_SUITE_END_PART()
+} // namespace map2
index c2b21bfc77b820ce3b682ed4e60ea0d639eb501a..119f1078311aa4ea7e884b9f89c067fdcbe6e0a2 100644 (file)
 //$$CDS-header$$
 
-#include "map2/map_types.h"
-#include "cppunit/thread.h"
-
-#include <cds/os/topology.h>
-#include <vector>
-#include <algorithm> // random_shuffle
+#include "map2/map_insfind_int.h"
 
 namespace map2 {
+    CPPUNIT_TEST_SUITE_REGISTRATION( Map_InsFind_int );
 
-#    define TEST_MAP(X)         void X() { test<MapTypes<key_type, value_type>::X >()    ; }
-#    define TEST_MAP_NOLF(X)    void X() { test_nolf<MapTypes<key_type, value_type>::X >()    ; }
-#   define TEST_MAP_EXTRACT(X)  TEST_MAP(X)
-#   define TEST_MAP_NOLF_EXTRACT(X) TEST_MAP_NOLF(X)
+    size_t Map_InsFind_int::c_nMapSize = 1000000    ;  // map size
+    size_t Map_InsFind_int::c_nThreadCount = 4      ;  // count of insertion thread
+    size_t Map_InsFind_int::c_nMaxLoadFactor = 8    ;  // maximum load factor
+    bool   Map_InsFind_int::c_bPrintGCState = true;
 
-    namespace {
-        static size_t  c_nMapSize = 1000000    ;  // map size
-        static size_t  c_nThreadCount = 4      ;  // count of insertion thread
-        static size_t  c_nMaxLoadFactor = 8    ;  // maximum load factor
-        static bool    c_bPrintGCState = true;
+    void Map_InsFind_int::setUpParams( const CppUnitMini::TestCfg& cfg )
+    {
+        c_nThreadCount = cfg.getULong("ThreadCount", 0 );
+        c_nMapSize = cfg.getULong("MapSize", static_cast<unsigned long>(c_nMapSize));
+        c_nMaxLoadFactor = cfg.getULong("MaxLoadFactor", static_cast<unsigned long>(c_nMaxLoadFactor));
+        c_bPrintGCState = cfg.getBool("PrintGCStateFlag", true );
+        if ( c_nThreadCount == 0 )
+            c_nThreadCount = cds::OS::topology::processor_count();
     }
 
-    class Map_InsFind_int: public CppUnitMini::TestCase
+    void Map_InsFind_int::myRun(const char *in_name, bool invert /*= false*/)
     {
-        typedef size_t  key_type;
-        typedef size_t  value_type;
-
-        template <typename Iterator, typename Map>
-        static bool check_result( Iterator const& it, Map const& map )
-        {
-            return it != map.end();
-        }
-        template <typename Map>
-        static bool check_result( bool b, Map const& )
-        {
-            return b;
-        }
-
-        template <class Map>
-        class Inserter: public CppUnitMini::TestThread
-        {
-            Map&     m_Map;
-            std::vector<size_t> m_arrVal;
-
-            virtual Inserter *    clone()
-            {
-                return new Inserter( *this );
-            }
-
-            void make_array()
-            {
-                size_t const nSize = c_nMapSize / c_nThreadCount + 1;
-                m_arrVal.resize( nSize );
-                size_t nItem = m_nThreadNo;
-                for ( size_t i = 0; i < nSize; nItem += c_nThreadCount, ++i )
-                    m_arrVal[i] = nItem;
-                std::random_shuffle( m_arrVal.begin(), m_arrVal.end() );
-            }
-        public:
-            size_t  m_nInsertSuccess;
-            size_t  m_nInsertFailed;
-            size_t  m_nFindSuccess;
-            size_t  m_nFindFail;
-
-        public:
-            Inserter( CppUnitMini::ThreadPool& pool, Map& rMap )
-                : CppUnitMini::TestThread( pool )
-                , m_Map( rMap )
-            {}
-            Inserter( Inserter& src )
-                : CppUnitMini::TestThread( src )
-                , m_Map( src.m_Map )
-            {}
-
-            Map_InsFind_int&  getTest()
-            {
-                return reinterpret_cast<Map_InsFind_int&>( m_Pool.m_Test );
-            }
-
-            virtual void init()
-            {
-                cds::threading::Manager::attachThread();
-                make_array();
-            }
-            virtual void fini() { cds::threading::Manager::detachThread()   ; }
-
-            virtual void test()
-            {
-                Map& rMap = m_Map;
-
-                m_nInsertSuccess =
-                    m_nInsertFailed =
-                    m_nFindSuccess =
-                    m_nFindFail = 0;
-
-                size_t const nArrSize = m_arrVal.size();
-                for ( size_t i = 0; i < nArrSize; ++i ) {
-                    size_t const nItem = m_arrVal[i];
-                    if ( check_result( rMap.insert( nItem, nItem * 8 ), rMap ))
-                        ++m_nInsertSuccess;
-                    else
-                        ++m_nInsertFailed;
-
-                    for ( size_t k = 0; k <= i; ++k ) {
-                        if ( check_result( rMap.find( m_arrVal[k] ), rMap ))
-                            ++m_nFindSuccess;
-                        else
-                            ++m_nFindFail;
-                    }
-                }
-            }
-        };
-
-    protected:
-
-        template <class Map>
-        void do_test( Map& testMap )
-        {
-            typedef Inserter<Map>       InserterThread;
-            cds::OS::Timer    timer;
-
-            CppUnitMini::ThreadPool pool( *this );
-            pool.add( new InserterThread( pool, testMap ), c_nThreadCount );
-            pool.run();
-            CPPUNIT_MSG( "   Duration=" << pool.avgDuration() );
-
-            size_t nInsertSuccess = 0;
-            size_t nInsertFailed = 0;
-            size_t nFindSuccess = 0;
-            size_t nFindFailed = 0;
-            for ( CppUnitMini::ThreadPool::iterator it = pool.begin(); it != pool.end(); ++it ) {
-                InserterThread * pThread = static_cast<InserterThread *>( *it );
-
-                nInsertSuccess += pThread->m_nInsertSuccess;
-                nInsertFailed += pThread->m_nInsertFailed;
-                nFindSuccess += pThread->m_nFindSuccess;
-                nFindFailed += pThread->m_nFindFail;
-            }
-
-            CPPUNIT_MSG( "    Totals: Ins succ=" << nInsertSuccess << " fail=" << nInsertFailed << "\n"
-                      << "           Find succ=" << nFindSuccess << " fail=" << nFindFailed
-            );
-
-            CPPUNIT_CHECK( nInsertFailed == 0 );
-            CPPUNIT_CHECK( nFindFailed == 0 );
-
-            check_before_cleanup( testMap );
-
-            testMap.clear();
-            additional_check( testMap );
-            print_stat( testMap );
-            additional_cleanup( testMap );
-        }
-
-        template <class Map>
-        void test()
-        {
-            static_assert( (!std::is_same< typename Map::item_counter, cds::atomicity::empty_item_counter >::value),
-                "Empty item counter is not suitable for this test");
-
-            CPPUNIT_MSG( "Thread count: " << c_nThreadCount
-                << " map size=" << c_nMapSize
-                );
-
-            for ( size_t nLoadFactor = 1; nLoadFactor <= c_nMaxLoadFactor; nLoadFactor *= 2 ) {
-                CPPUNIT_MSG( "Load factor=" << nLoadFactor );
-                Map  testMap( c_nMapSize, nLoadFactor );
-                do_test( testMap );
-                if ( c_bPrintGCState )
-                    print_gc_state();
-            }
-        }
-
-        template <class Map>
-        void test_nolf()
-        {
-            static_assert( (!std::is_same< typename Map::item_counter, cds::atomicity::empty_item_counter >::value),
-                "Empty item counter is not suitable for this test");
-
-            CPPUNIT_MSG( "Thread count: " << c_nThreadCount
-                << " map size=" << c_nMapSize
-                );
-
-            Map testMap;
-            do_test( testMap );
-            if ( c_bPrintGCState )
-                print_gc_state();
-        }
-
-        void setUpParams( const CppUnitMini::TestCfg& cfg ) {
-            c_nThreadCount = cfg.getULong("ThreadCount", 0 );
-            c_nMapSize = cfg.getULong("MapSize", 10000 );
-            c_nMaxLoadFactor = cfg.getULong("MaxLoadFactor", 8 );
-            c_bPrintGCState = cfg.getBool("PrintGCStateFlag", true );
-            if ( c_nThreadCount == 0 )
-                c_nThreadCount = cds::OS::topology::processor_count();
-        }
-
-#   include "map2/map_defs.h"
-        CDSUNIT_DECLARE_MichaelMap
-        CDSUNIT_DECLARE_MichaelMap_nogc
-        CDSUNIT_DECLARE_SplitList
-        CDSUNIT_DECLARE_SplitList_nogc
-        CDSUNIT_DECLARE_SkipListMap
-        CDSUNIT_DECLARE_SkipListMap_nogc
-        CDSUNIT_DECLARE_EllenBinTreeMap
-        CDSUNIT_DECLARE_BronsonAVLTreeMap
-        CDSUNIT_DECLARE_StripedMap
-        CDSUNIT_DECLARE_RefinableMap
-        CDSUNIT_DECLARE_CuckooMap
-        CDSUNIT_DECLARE_StdMap
-
-        CPPUNIT_TEST_SUITE( Map_InsFind_int )
-            CDSUNIT_TEST_MichaelMap
-            CDSUNIT_TEST_MichaelMap_nogc
-            CDSUNIT_TEST_SplitList
-            CDSUNIT_TEST_SplitList_nogc
-            CDSUNIT_TEST_SkipListMap
-            CDSUNIT_TEST_SkipListMap_nogc
-            CDSUNIT_TEST_EllenBinTreeMap
-            CDSUNIT_TEST_BronsonAVLTreeMap
-            CDSUNIT_TEST_StripedMap
-            CDSUNIT_TEST_RefinableMap
-            CDSUNIT_TEST_CuckooMap
-            CDSUNIT_TEST_StdMap
-        CPPUNIT_TEST_SUITE_END()
-
-    };
+        setUpParams( m_Cfg.get( "Map_InsFind_int" ));
+
+        run_MichaelMap(in_name, invert);
+        run_SplitList(in_name, invert);
+        run_SkipListMap(in_name, invert);
+        run_EllenBinTreeMap(in_name, invert);
+        run_BronsonAVLTreeMap(in_name, invert);
+        run_StripedMap(in_name, invert);
+        run_RefinableMap(in_name, invert);
+        run_CuckooMap(in_name, invert);
+        run_StdMap(in_name, invert);
+
+        endTestCase();
+    }
 
-    CPPUNIT_TEST_SUITE_REGISTRATION( Map_InsFind_int );
+    /*
+    CPPUNIT_TEST_SUITE( Map_InsFind_int )
+        CDSUNIT_TEST_MichaelMap
+        CDSUNIT_TEST_MichaelMap_nogc
+        CDSUNIT_TEST_SplitList
+        CDSUNIT_TEST_SplitList_nogc
+        CDSUNIT_TEST_SkipListMap
+        CDSUNIT_TEST_SkipListMap_nogc
+        CDSUNIT_TEST_EllenBinTreeMap
+        CDSUNIT_TEST_BronsonAVLTreeMap
+        CDSUNIT_TEST_StripedMap
+        CDSUNIT_TEST_RefinableMap
+        CDSUNIT_TEST_CuckooMap
+        CDSUNIT_TEST_StdMap
+    CPPUNIT_TEST_SUITE_END()
+    */
 } // namespace map2
diff --git a/tests/unit/map2/map_insfind_int.h b/tests/unit/map2/map_insfind_int.h
new file mode 100644 (file)
index 0000000..2003896
--- /dev/null
@@ -0,0 +1,218 @@
+//$$CDS-header$$
+
+#include "map2/map_types.h"
+#include "cppunit/thread.h"
+
+#include <cds/os/topology.h>
+#include <vector>
+#include <algorithm> // random_shuffle
+
+namespace map2 {
+
+#   define TEST_MAP(X)         void X() { test<MapTypes<key_type, value_type>::X >()    ; }
+#   define TEST_MAP_NOLF(X)    void X() { test_nolf<MapTypes<key_type, value_type>::X >()    ; }
+#   define TEST_MAP_EXTRACT(X)  TEST_MAP(X)
+#   define TEST_MAP_NOLF_EXTRACT(X) TEST_MAP_NOLF(X)
+
+    class Map_InsFind_int: public CppUnitMini::TestCase
+    {
+        static size_t  c_nMapSize;       // map size
+        static size_t  c_nThreadCount;   // count of insertion thread
+        static size_t  c_nMaxLoadFactor; // maximum load factor
+        static bool    c_bPrintGCState;
+
+        typedef CppUnitMini::TestCase Base;
+        typedef size_t  key_type;
+        typedef size_t  value_type;
+
+        template <typename Iterator, typename Map>
+        static bool check_result( Iterator const& it, Map const& map )
+        {
+            return it != map.end();
+        }
+        template <typename Map>
+        static bool check_result( bool b, Map const& )
+        {
+            return b;
+        }
+
+        template <class Map>
+        class Inserter: public CppUnitMini::TestThread
+        {
+            Map&     m_Map;
+            std::vector<size_t> m_arrVal;
+
+            virtual Inserter *    clone()
+            {
+                return new Inserter( *this );
+            }
+
+            void make_array()
+            {
+                size_t const nSize = c_nMapSize / c_nThreadCount + 1;
+                m_arrVal.resize( nSize );
+                size_t nItem = m_nThreadNo;
+                for ( size_t i = 0; i < nSize; nItem += c_nThreadCount, ++i )
+                    m_arrVal[i] = nItem;
+                std::random_shuffle( m_arrVal.begin(), m_arrVal.end() );
+            }
+        public:
+            size_t  m_nInsertSuccess;
+            size_t  m_nInsertFailed;
+            size_t  m_nFindSuccess;
+            size_t  m_nFindFail;
+
+        public:
+            Inserter( CppUnitMini::ThreadPool& pool, Map& rMap )
+                : CppUnitMini::TestThread( pool )
+                , m_Map( rMap )
+            {}
+            Inserter( Inserter& src )
+                : CppUnitMini::TestThread( src )
+                , m_Map( src.m_Map )
+            {}
+
+            Map_InsFind_int&  getTest()
+            {
+                return reinterpret_cast<Map_InsFind_int&>( m_Pool.m_Test );
+            }
+
+            virtual void init()
+            {
+                cds::threading::Manager::attachThread();
+                make_array();
+            }
+            virtual void fini() { cds::threading::Manager::detachThread()   ; }
+
+            virtual void test()
+            {
+                Map& rMap = m_Map;
+
+                m_nInsertSuccess =
+                    m_nInsertFailed =
+                    m_nFindSuccess =
+                    m_nFindFail = 0;
+
+                size_t const nArrSize = m_arrVal.size();
+                for ( size_t i = 0; i < nArrSize; ++i ) {
+                    size_t const nItem = m_arrVal[i];
+                    if ( check_result( rMap.insert( nItem, nItem * 8 ), rMap ))
+                        ++m_nInsertSuccess;
+                    else
+                        ++m_nInsertFailed;
+
+                    for ( size_t k = 0; k <= i; ++k ) {
+                        if ( check_result( rMap.find( m_arrVal[k] ), rMap ))
+                            ++m_nFindSuccess;
+                        else
+                            ++m_nFindFail;
+                    }
+                }
+            }
+        };
+
+    protected:
+
+        template <class Map>
+        void do_test( Map& testMap )
+        {
+            typedef Inserter<Map>       InserterThread;
+            cds::OS::Timer    timer;
+
+            CppUnitMini::ThreadPool pool( *this );
+            pool.add( new InserterThread( pool, testMap ), c_nThreadCount );
+            pool.run();
+            CPPUNIT_MSG( "   Duration=" << pool.avgDuration() );
+
+            size_t nInsertSuccess = 0;
+            size_t nInsertFailed = 0;
+            size_t nFindSuccess = 0;
+            size_t nFindFailed = 0;
+            for ( CppUnitMini::ThreadPool::iterator it = pool.begin(); it != pool.end(); ++it ) {
+                InserterThread * pThread = static_cast<InserterThread *>( *it );
+
+                nInsertSuccess += pThread->m_nInsertSuccess;
+                nInsertFailed += pThread->m_nInsertFailed;
+                nFindSuccess += pThread->m_nFindSuccess;
+                nFindFailed += pThread->m_nFindFail;
+            }
+
+            CPPUNIT_MSG( "    Totals: Ins succ=" << nInsertSuccess << " fail=" << nInsertFailed << "\n"
+                      << "           Find succ=" << nFindSuccess << " fail=" << nFindFailed
+            );
+
+            CPPUNIT_CHECK( nInsertFailed == 0 );
+            CPPUNIT_CHECK( nFindFailed == 0 );
+
+            check_before_cleanup( testMap );
+
+            testMap.clear();
+            additional_check( testMap );
+            print_stat( testMap );
+            additional_cleanup( testMap );
+        }
+
+        template <class Map>
+        void test()
+        {
+            static_assert( (!std::is_same< typename Map::item_counter, cds::atomicity::empty_item_counter >::value),
+                "Empty item counter is not suitable for this test");
+
+            CPPUNIT_MSG( "Thread count: " << c_nThreadCount
+                << " map size=" << c_nMapSize
+                );
+
+            for ( size_t nLoadFactor = 1; nLoadFactor <= c_nMaxLoadFactor; nLoadFactor *= 2 ) {
+                CPPUNIT_MSG( "Load factor=" << nLoadFactor );
+                Map  testMap( c_nMapSize, nLoadFactor );
+                do_test( testMap );
+                if ( c_bPrintGCState )
+                    print_gc_state();
+            }
+        }
+
+        template <class Map>
+        void test_nolf()
+        {
+            static_assert( (!std::is_same< typename Map::item_counter, cds::atomicity::empty_item_counter >::value),
+                "Empty item counter is not suitable for this test");
+
+            CPPUNIT_MSG( "Thread count: " << c_nThreadCount
+                << " map size=" << c_nMapSize
+                );
+
+            Map testMap;
+            do_test( testMap );
+            if ( c_bPrintGCState )
+                print_gc_state();
+        }
+
+        void setUpParams( const CppUnitMini::TestCfg& cfg );
+
+        void run_MichaelMap(const char *in_name, bool invert = false);
+        void run_SplitList(const char *in_name, bool invert = false);
+        void run_StripedMap(const char *in_name, bool invert = false);
+        void run_RefinableMap(const char *in_name, bool invert = false);
+        void run_CuckooMap(const char *in_name, bool invert = false);
+        void run_SkipListMap(const char *in_name, bool invert = false);
+        void run_EllenBinTreeMap(const char *in_name, bool invert = false);
+        void run_BronsonAVLTreeMap(const char *in_name, bool invert = false);
+        void run_StdMap(const char *in_name, bool invert = false);
+
+        virtual void myRun(const char *in_name, bool invert = false);
+
+#   include "map2/map_defs.h"
+        CDSUNIT_DECLARE_MichaelMap
+        CDSUNIT_DECLARE_MichaelMap_nogc
+        CDSUNIT_DECLARE_SplitList
+        CDSUNIT_DECLARE_SplitList_nogc
+        CDSUNIT_DECLARE_SkipListMap
+        CDSUNIT_DECLARE_SkipListMap_nogc
+        CDSUNIT_DECLARE_EllenBinTreeMap
+        CDSUNIT_DECLARE_BronsonAVLTreeMap
+        CDSUNIT_DECLARE_StripedMap
+        CDSUNIT_DECLARE_RefinableMap
+        CDSUNIT_DECLARE_CuckooMap
+        CDSUNIT_DECLARE_StdMap
+    };
+} // namespace map2
diff --git a/tests/unit/map2/map_insfind_int_bronsonavltree.cpp b/tests/unit/map2/map_insfind_int_bronsonavltree.cpp
new file mode 100644 (file)
index 0000000..520b785
--- /dev/null
@@ -0,0 +1,9 @@
+//$$CDS-header$$
+
+#include "map2/map_insfind_int.h"
+
+namespace map2 {
+    CPPUNIT_TEST_SUITE_PART( Map_InsFind_int, run_BronsonAVLTreeMap )
+        CDSUNIT_TEST_BronsonAVLTreeMap
+    CPPUNIT_TEST_SUITE_END_PART()
+} // namespace map2
diff --git a/tests/unit/map2/map_insfind_int_cuckoo.cpp b/tests/unit/map2/map_insfind_int_cuckoo.cpp
new file mode 100644 (file)
index 0000000..b1fa855
--- /dev/null
@@ -0,0 +1,9 @@
+//$$CDS-header$$
+
+#include "map2/map_insfind_int.h"
+
+namespace map2 {
+    CPPUNIT_TEST_SUITE_PART( Map_InsFind_int, run_CuckooMap )
+        CDSUNIT_TEST_CuckooMap
+    CPPUNIT_TEST_SUITE_END_PART()
+} // namespace map2
diff --git a/tests/unit/map2/map_insfind_int_ellentree.cpp b/tests/unit/map2/map_insfind_int_ellentree.cpp
new file mode 100644 (file)
index 0000000..17b5d0e
--- /dev/null
@@ -0,0 +1,9 @@
+//$$CDS-header$$
+
+#include "map2/map_insfind_int.h"
+
+namespace map2 {
+    CPPUNIT_TEST_SUITE_PART( Map_InsFind_int, run_EllenBinTreeMap )
+        CDSUNIT_TEST_EllenBinTreeMap
+    CPPUNIT_TEST_SUITE_END_PART()
+} // namespace map2
diff --git a/tests/unit/map2/map_insfind_int_michael.cpp b/tests/unit/map2/map_insfind_int_michael.cpp
new file mode 100644 (file)
index 0000000..8703e06
--- /dev/null
@@ -0,0 +1,10 @@
+//$$CDS-header$$
+
+#include "map2/map_insfind_int.h"
+
+namespace map2 {
+    CPPUNIT_TEST_SUITE_PART( Map_InsFind_int, run_MichaelMap )
+        CDSUNIT_TEST_MichaelMap
+        CDSUNIT_TEST_MichaelMap_nogc
+    CPPUNIT_TEST_SUITE_END_PART()
+} // namespace map2
diff --git a/tests/unit/map2/map_insfind_int_refinable.cpp b/tests/unit/map2/map_insfind_int_refinable.cpp
new file mode 100644 (file)
index 0000000..8926de2
--- /dev/null
@@ -0,0 +1,9 @@
+//$$CDS-header$$
+
+#include "map2/map_insfind_int.h"
+
+namespace map2 {
+    CPPUNIT_TEST_SUITE_PART( Map_InsFind_int, run_RefinableMap )
+        CDSUNIT_TEST_RefinableMap
+    CPPUNIT_TEST_SUITE_END_PART()
+} // namespace map2
diff --git a/tests/unit/map2/map_insfind_int_skip.cpp b/tests/unit/map2/map_insfind_int_skip.cpp
new file mode 100644 (file)
index 0000000..930ccf1
--- /dev/null
@@ -0,0 +1,10 @@
+//$$CDS-header$$
+
+#include "map2/map_insfind_int.h"
+
+namespace map2 {
+    CPPUNIT_TEST_SUITE_PART( Map_InsFind_int, run_SkipListMap )
+        CDSUNIT_TEST_SkipListMap
+        CDSUNIT_TEST_SkipListMap_nogc
+    CPPUNIT_TEST_SUITE_END_PART()
+} // namespace map2
diff --git a/tests/unit/map2/map_insfind_int_split.cpp b/tests/unit/map2/map_insfind_int_split.cpp
new file mode 100644 (file)
index 0000000..4af7722
--- /dev/null
@@ -0,0 +1,10 @@
+//$$CDS-header$$
+
+#include "map2/map_insfind_int.h"
+
+namespace map2 {
+    CPPUNIT_TEST_SUITE_PART( Map_InsFind_int, run_SplitList )
+        CDSUNIT_TEST_SplitList
+        CDSUNIT_TEST_SplitList_nogc
+    CPPUNIT_TEST_SUITE_END_PART()
+} // namespace map2
diff --git a/tests/unit/map2/map_insfind_int_std.cpp b/tests/unit/map2/map_insfind_int_std.cpp
new file mode 100644 (file)
index 0000000..473fb74
--- /dev/null
@@ -0,0 +1,9 @@
+//$$CDS-header$$
+
+#include "map2/map_insfind_int.h"
+
+namespace map2 {
+    CPPUNIT_TEST_SUITE_PART( Map_InsFind_int, run_StdMap )
+        CDSUNIT_TEST_StdMap
+    CPPUNIT_TEST_SUITE_END_PART()
+} // namespace map2
diff --git a/tests/unit/map2/map_insfind_int_striped.cpp b/tests/unit/map2/map_insfind_int_striped.cpp
new file mode 100644 (file)
index 0000000..392ca36
--- /dev/null
@@ -0,0 +1,9 @@
+//$$CDS-header$$
+
+#include "map2/map_insfind_int.h"
+
+namespace map2 {
+    CPPUNIT_TEST_SUITE_PART( Map_InsFind_int, run_StripedMap )
+        CDSUNIT_TEST_StripedMap
+    CPPUNIT_TEST_SUITE_END_PART()
+} // namespace map2
index 4417b02827da5cd9ca537311c1904dfd5a4f8616..e898f82cb0c5230a7172552e3cb4a9f06ec3b5c7 100644 (file)
@@ -1938,10 +1938,11 @@ namespace map2 {
     static inline void check_before_cleanup( cc::BronsonAVLTreeMap<GC, Key, T, Traits>& m )
     {
         CPPUNIT_MSG( "  Check internal consistency (single-threaded)..." );
-        m.check_consistency([]( size_t nLevel, size_t hLeft, size_t hRight )
+        bool bOk = m.check_consistency([]( size_t nLevel, size_t hLeft, size_t hRight )
             { 
                 CPPUNIT_MSG( "Tree violation on level=" << nLevel << ": hLeft=" << hLeft << ", hRight=" << hRight ) 
             });
+        CPPUNIT_CHECK_CURRENT_EX( bOk, "check_consistency failed");
     }
 
     template <typename K, typename V, typename Traits>
index dc2b56adfa523c123c2c91a1fcc93da265a4794f..ca0333310932795f589e5cdd925a8fcaf9b51834 100644 (file)
 //$$CDS-header$$
 
-#include "cppunit/thread.h"
-#include "set2/set_types.h"
-#include <algorithm> // random_shuffle
+#include "set2/set_delodd.h"
 
 namespace set2 {
+    CPPUNIT_TEST_SUITE_REGISTRATION( Set_DelOdd );
 
-#    define TEST_SET(X)         void X() { test<SetTypes<key_type, value_type>::X >()    ; }
-#    define TEST_SET_EXTRACT(X) void X() { test_extract<SetTypes<key_type, value_type>::X >()    ; }
-#    define TEST_SET_NOLF(X)    void X() { test_nolf<SetTypes<key_type, value_type>::X >()    ; }
-#    define TEST_SET_NOLF_EXTRACT(X)    void X() { test_nolf_extract<SetTypes<key_type, value_type>::X >()    ; }
-
-    namespace {
-        static size_t  c_nSetSize = 1000000         ;  // max set size
-        static size_t  c_nInsThreadCount = 4        ;  // insert thread count
-        static size_t  c_nDelThreadCount = 4        ;  // delete thread count
-        static size_t  c_nExtractThreadCount = 4    ;  // extract thread count
-        static size_t  c_nMaxLoadFactor = 8         ;  // maximum load factor
-        static bool    c_bPrintGCState = true;
-    }
-
-    namespace {
-        struct key_thread
-        {
-            size_t  nKey;
-            size_t  nThread;
-
-            key_thread( size_t key, size_t threadNo )
-                : nKey( key )
-                , nThread( threadNo )
-            {}
-
-            key_thread()
-            {}
-        };
-
-        typedef SetTypes<key_thread, size_t>::key_val     key_value_pair;
-    }
-
-    template <>
-    struct cmp<key_thread> {
-        int operator ()(key_thread const& k1, key_thread const& k2) const
-        {
-            if ( k1.nKey < k2.nKey )
-                return -1;
-            if ( k1.nKey > k2.nKey )
-                return 1;
-            if ( k1.nThread < k2.nThread )
-                return -1;
-            if ( k1.nThread > k2.nThread )
-                return 1;
-            return 0;
-        }
-        int operator ()(key_thread const& k1, size_t k2) const
-        {
-            if ( k1.nKey < k2 )
-                return -1;
-            if ( k1.nKey > k2 )
-                return 1;
-            return 0;
-        }
-        int operator ()(size_t k1, key_thread const& k2) const
-        {
-            if ( k1 < k2.nKey )
-                return -1;
-            if ( k1 > k2.nKey )
-                return 1;
-            return 0;
-        }
-    };
-
-} // namespace set2
-
-namespace std {
-    template <>
-    struct less<set2::key_thread>
-    {
-        bool operator()(set2::key_thread const& k1, set2::key_thread const& k2) const
-        {
-            if ( k1.nKey <= k2.nKey )
-                return k1.nKey < k2.nKey || k1.nThread < k2.nThread;
-            return false;
-        }
-    };
-
-    template <>
-    struct hash<set2::key_thread>
-    {
-        typedef size_t              result_type;
-        typedef set2::key_thread    argument_type;
-
-        size_t operator()( set2::key_thread const& k ) const
-        {
-            return std::hash<size_t>()(k.nKey);
-        }
-        size_t operator()( size_t k ) const
-        {
-            return std::hash<size_t>()(k);
-        }
-    };
-
-} // namespace std
+    size_t Set_DelOdd::c_nSetSize = 1000000;
+    size_t Set_DelOdd::c_nInsThreadCount;
+    size_t Set_DelOdd::c_nDelThreadCount;
+    size_t Set_DelOdd::c_nExtractThreadCount;
+    size_t Set_DelOdd::c_nMaxLoadFactor;
+    bool   Set_DelOdd::c_bPrintGCState;
 
-namespace boost {
-    inline size_t hash_value( set2::key_thread const& k )
+    void Set_DelOdd::setUpParams( const CppUnitMini::TestCfg& cfg )
     {
-        return std::hash<size_t>()( k.nKey );
+        c_nSetSize = cfg.getSizeT("MapSize", c_nSetSize );
+        c_nInsThreadCount = cfg.getSizeT("InsThreadCount", c_nInsThreadCount);
+        c_nDelThreadCount = cfg.getSizeT("DelThreadCount", c_nDelThreadCount);
+        c_nExtractThreadCount = cfg.getSizeT("ExtractThreadCount", c_nExtractThreadCount);
+        c_nMaxLoadFactor = cfg.getSizeT("MaxLoadFactor", c_nMaxLoadFactor);
+        c_bPrintGCState = cfg.getBool("PrintGCStateFlag", true );
+
+        if ( c_nInsThreadCount == 0 )
+            c_nInsThreadCount = cds::OS::topology::processor_count();
+        if ( c_nDelThreadCount == 0 && c_nExtractThreadCount == 0 ) {
+            c_nExtractThreadCount = cds::OS::topology::processor_count() / 2;
+            c_nDelThreadCount = cds::OS::topology::processor_count() - c_nExtractThreadCount;
+        }
+
+        m_arrData.resize( c_nSetSize );
+        for ( size_t i = 0; i < c_nSetSize; ++i )
+            m_arrData[i] = i;
+        std::random_shuffle( m_arrData.begin(), m_arrData.end() );
     }
 
-    template <>
-    struct hash<set2::key_thread>
+    void Set_DelOdd::myRun(const char *in_name, bool invert /*= false*/)
     {
-        typedef size_t              result_type;
-        typedef set2::key_thread    argument_type;
+        setUpParams( m_Cfg.get( "Map_DelOdd" ));
 
-        size_t operator()(set2::key_thread const& k) const
-        {
-            return boost::hash<size_t>()( k.nKey );
-        }
-        size_t operator()(size_t k) const
-        {
-            return boost::hash<size_t>()( k );
-        }
-    };
-} // namespace boost
-
-namespace set2 {
+        run_MichaelSet(in_name, invert);
+        run_SplitList(in_name, invert);
+        run_SkipListSet(in_name, invert);
+        run_EllenBinTreeSet(in_name, invert);
+        run_CuckooSet(in_name, invert);
 
-    template <typename Set>
-    static inline void check_before_clear( Set& /*s*/ )
-    {}
-
-    template <typename GC, typename Key, typename T, typename Traits>
-    static inline void check_before_clear( cds::container::EllenBinTreeSet<GC, Key, T, Traits>& s )
-    {
-        CPPUNIT_CHECK_CURRENT( s.check_consistency() );
+        endTestCase();
     }
-
-    class Set_DelOdd: public CppUnitMini::TestCase
-    {
-        std::vector<size_t>     m_arrData;
-
-    protected:
-        typedef key_thread  key_type;
-        typedef size_t      value_type;
-
-        atomics::atomic<size_t>      m_nInsThreadCount;
-
-        // Inserts keys from [0..N)
-        template <class Set>
-        class InsertThread: public CppUnitMini::TestThread
-        {
-            Set&     m_Set;
-
-            virtual InsertThread *    clone()
-            {
-                return new InsertThread( *this );
-            }
-
-            struct ensure_func
-            {
-                template <typename Q>
-                void operator()( bool /*bNew*/, key_value_pair const&, Q const& )
-                {}
-            };
-        public:
-            size_t  m_nInsertSuccess;
-            size_t  m_nInsertFailed;
-
-        public:
-            InsertThread( CppUnitMini::ThreadPool& pool, Set& rMap )
-                : CppUnitMini::TestThread( pool )
-                , m_Set( rMap )
-            {}
-            InsertThread( InsertThread& src )
-                : CppUnitMini::TestThread( src )
-                , m_Set( src.m_Set )
-            {}
-
-            Set_DelOdd&  getTest()
-            {
-                return reinterpret_cast<Set_DelOdd&>( m_Pool.m_Test );
-            }
-
-            virtual void init() { cds::threading::Manager::attachThread()   ; }
-            virtual void fini() { cds::threading::Manager::detachThread()   ; }
-
-            virtual void test()
-            {
-                Set& rSet = m_Set;
-
-                m_nInsertSuccess =
-                    m_nInsertFailed = 0;
-
-                std::vector<size_t>& arrData = getTest().m_arrData;
-                for ( size_t i = 0; i < arrData.size(); ++i ) {
-                    if ( rSet.insert( key_type( arrData[i], m_nThreadNo )))
-                        ++m_nInsertSuccess;
-                    else
-                        ++m_nInsertFailed;
-                }
-
-                ensure_func f;
-                for ( size_t i = arrData.size() - 1; i > 0; --i ) {
-                    if ( arrData[i] & 1 ) {
-                        rSet.ensure( key_type( arrData[i], m_nThreadNo ), f );
-                    }
-                }
-
-                getTest().m_nInsThreadCount.fetch_sub( 1, atomics::memory_order_release );
-            }
-        };
-
-        struct key_equal {
-            bool operator()( key_type const& k1, key_type const& k2 ) const
-            {
-                return k1.nKey == k2.nKey;
-            }
-            bool operator()( size_t k1, key_type const& k2 ) const
-            {
-                return k1 == k2.nKey;
-            }
-            bool operator()( key_type const& k1, size_t k2 ) const
-            {
-                return k1.nKey == k2;
-            }
-            bool operator ()( key_value_pair const& k1, key_value_pair const& k2 ) const
-            {
-                return operator()( k1.key, k2.key );
-            }
-            bool operator ()( key_value_pair const& k1, key_type const& k2 ) const
-            {
-                return operator()( k1.key, k2 );
-            }
-            bool operator ()( key_type const& k1, key_value_pair const& k2 ) const
-            {
-                return operator()( k1, k2.key );
-            }
-            bool operator ()( key_value_pair const& k1, size_t k2 ) const
-            {
-                return operator()( k1.key, k2 );
-            }
-            bool operator ()( size_t k1, key_value_pair const& k2 ) const
-            {
-                return operator()( k1, k2.key );
-            }
-        };
-
-        struct key_less {
-            bool operator()( key_type const& k1, key_type const& k2 ) const
-            {
-                return k1.nKey < k2.nKey;
-            }
-            bool operator()( size_t k1, key_type const& k2 ) const
-            {
-                return k1 < k2.nKey;
-            }
-            bool operator()( key_type const& k1, size_t k2 ) const
-            {
-                return k1.nKey < k2;
-            }
-            bool operator ()( key_value_pair const& k1, key_value_pair const& k2 ) const
-            {
-                return operator()( k1.key, k2.key );
-            }
-            bool operator ()( key_value_pair const& k1, key_type const& k2 ) const
-            {
-                return operator()( k1.key, k2 );
-            }
-            bool operator ()( key_type const& k1, key_value_pair const& k2 ) const
-            {
-                return operator()( k1, k2.key );
-            }
-            bool operator ()( key_value_pair const& k1, size_t k2 ) const
-            {
-                return operator()( k1.key, k2 );
-            }
-            bool operator ()( size_t k1, key_value_pair const& k2 ) const
-            {
-                return operator()( k1, k2.key );
-            }
-
-            typedef key_equal   equal_to;
-        };
-
-        // Deletes odd keys from [0..N)
-        template <class Set>
-        class DeleteThread: public CppUnitMini::TestThread
-        {
-            Set&     m_Set;
-
-            virtual DeleteThread *    clone()
-            {
-                return new DeleteThread( *this );
-            }
-        public:
-            size_t  m_nDeleteSuccess;
-            size_t  m_nDeleteFailed;
-
-        public:
-            DeleteThread( CppUnitMini::ThreadPool& pool, Set& rMap )
-                : CppUnitMini::TestThread( pool )
-                , m_Set( rMap )
-            {}
-            DeleteThread( DeleteThread& src )
-                : CppUnitMini::TestThread( src )
-                , m_Set( src.m_Set )
-            {}
-
-            Set_DelOdd&  getTest()
-            {
-                return reinterpret_cast<Set_DelOdd&>( m_Pool.m_Test );
-            }
-
-            virtual void init() { cds::threading::Manager::attachThread()   ; }
-            virtual void fini() { cds::threading::Manager::detachThread()   ; }
-
-            virtual void test()
-            {
-                Set& rSet = m_Set;
-
-                m_nDeleteSuccess =
-                    m_nDeleteFailed = 0;
-
-                std::vector<size_t>& arrData = getTest().m_arrData;
-                if ( m_nThreadNo & 1 ) {
-                    for ( size_t k = 0; k < c_nInsThreadCount; ++k ) {
-                        for ( size_t i = 0; i < arrData.size(); ++i ) {
-                            if ( arrData[i] & 1 ) {
-                                if ( rSet.erase_with( arrData[i], key_less() ))
-                                    ++m_nDeleteSuccess;
-                                else
-                                    ++m_nDeleteFailed;
-                            }
-                        }
-                        if ( getTest().m_nInsThreadCount.load( atomics::memory_order_acquire ) == 0 )
-                            break;
-                    }
-                }
-                else {
-                    for ( size_t k = 0; k < c_nInsThreadCount; ++k ) {
-                        for ( size_t i = arrData.size() - 1; i > 0; --i ) {
-                            if ( arrData[i] & 1 ) {
-                                if ( rSet.erase_with( arrData[i], key_less() ))
-                                    ++m_nDeleteSuccess;
-                                else
-                                    ++m_nDeleteFailed;
-                            }
-                        }
-                        if ( getTest().m_nInsThreadCount.load( atomics::memory_order_acquire ) == 0 )
-                            break;
-                    }
-                }
-            }
-        };
-
-        // Extracts odd keys from [0..N)
-        template <typename GC, class Set>
-        class ExtractThread: public CppUnitMini::TestThread
-        {
-            Set&     m_Set;
-
-            virtual ExtractThread *    clone()
-            {
-                return new ExtractThread( *this );
-            }
-        public:
-            size_t  m_nExtractSuccess;
-            size_t  m_nExtractFailed;
-
-        public:
-            ExtractThread( CppUnitMini::ThreadPool& pool, Set& rMap )
-                : CppUnitMini::TestThread( pool )
-                , m_Set( rMap )
-            {}
-            ExtractThread( ExtractThread& src )
-                : CppUnitMini::TestThread( src )
-                , m_Set( src.m_Set )
-            {}
-
-            Set_DelOdd&  getTest()
-            {
-                return reinterpret_cast<Set_DelOdd&>( m_Pool.m_Test );
-            }
-
-            virtual void init() { cds::threading::Manager::attachThread()   ; }
-            virtual void fini() { cds::threading::Manager::detachThread()   ; }
-
-            virtual void test()
-            {
-                Set& rSet = m_Set;
-
-                m_nExtractSuccess =
-                    m_nExtractFailed = 0;
-
-                typename Set::guarded_ptr gp;
-
-                std::vector<size_t>& arrData = getTest().m_arrData;
-                if ( m_nThreadNo & 1 ) {
-                    for ( size_t k = 0; k < c_nInsThreadCount; ++k ) {
-                        for ( size_t i = 0; i < arrData.size(); ++i ) {
-                            if ( arrData[i] & 1 ) {
-                                gp = rSet.extract_with( arrData[i], key_less());
-                                if ( gp )
-                                    ++m_nExtractSuccess;
-                                else
-                                    ++m_nExtractFailed;
-                                gp.release();
-                            }
-                        }
-                        if ( getTest().m_nInsThreadCount.load( atomics::memory_order_acquire ) == 0 )
-                            break;
-                    }
-                }
-                else {
-                    for ( size_t k = 0; k < c_nInsThreadCount; ++k ) {
-                        for ( size_t i = arrData.size() - 1; i > 0; --i ) {
-                            if ( arrData[i] & 1 ) {
-                                gp = rSet.extract_with( arrData[i], key_less());
-                                if ( gp )
-                                    ++m_nExtractSuccess;
-                                else
-                                    ++m_nExtractFailed;
-                                gp.release();
-                            }
-                        }
-                        if ( getTest().m_nInsThreadCount.load( atomics::memory_order_acquire ) == 0 )
-                            break;
-                    }
-                }
-            }
-        };
-
-        template <typename RCU, class Set>
-        class ExtractThread< cds::urcu::gc<RCU>, Set >: public CppUnitMini::TestThread
-        {
-            Set&     m_Set;
-
-            virtual ExtractThread *    clone()
-            {
-                return new ExtractThread( *this );
-            }
-        public:
-            size_t  m_nExtractSuccess;
-            size_t  m_nExtractFailed;
-
-        public:
-            ExtractThread( CppUnitMini::ThreadPool& pool, Set& rMap )
-                : CppUnitMini::TestThread( pool )
-                , m_Set( rMap )
-            {}
-            ExtractThread( ExtractThread& src )
-                : CppUnitMini::TestThread( src )
-                , m_Set( src.m_Set )
-            {}
-
-            Set_DelOdd&  getTest()
-            {
-                return reinterpret_cast<Set_DelOdd&>( m_Pool.m_Test );
-            }
-
-            virtual void init() { cds::threading::Manager::attachThread()   ; }
-            virtual void fini() { cds::threading::Manager::detachThread()   ; }
-
-            virtual void test()
-            {
-                Set& rSet = m_Set;
-
-                m_nExtractSuccess =
-                    m_nExtractFailed = 0;
-
-                typename Set::exempt_ptr xp;
-
-                std::vector<size_t>& arrData = getTest().m_arrData;
-                if ( m_nThreadNo & 1 ) {
-                    for ( size_t k = 0; k < c_nInsThreadCount; ++k ) {
-                        for ( size_t i = 0; i < arrData.size(); ++i ) {
-                            if ( arrData[i] & 1 ) {
-                                if ( Set::c_bExtractLockExternal ) {
-                                    typename Set::rcu_lock l;
-                                    xp = rSet.extract_with( arrData[i], key_less() );
-                                    if ( xp )
-                                        ++m_nExtractSuccess;
-                                    else
-                                        ++m_nExtractFailed;
-                                }
-                                else {
-                                    xp = rSet.extract_with( arrData[i], key_less() );
-                                    if ( xp )
-                                        ++m_nExtractSuccess;
-                                    else
-                                        ++m_nExtractFailed;
-                                }
-                                xp.release();
-                            }
-                        }
-                        if ( getTest().m_nInsThreadCount.load( atomics::memory_order_acquire ) == 0 )
-                            break;
-                    }
-                }
-                else {
-                    for ( size_t k = 0; k < c_nInsThreadCount; ++k ) {
-                        for ( size_t i = arrData.size() - 1; i > 0; --i ) {
-                            if ( arrData[i] & 1 ) {
-                                if ( Set::c_bExtractLockExternal ) {
-                                    typename Set::rcu_lock l;
-                                    xp = rSet.extract_with( arrData[i], key_less() );
-                                    if ( xp )
-                                        ++m_nExtractSuccess;
-                                    else
-                                        ++m_nExtractFailed;
-                                }
-                                else {
-                                    xp = rSet.extract_with( arrData[i], key_less() );
-                                    if ( xp )
-                                        ++m_nExtractSuccess;
-                                    else
-                                        ++m_nExtractFailed;
-                                }
-                                xp.release();
-                            }
-                        }
-                        if ( getTest().m_nInsThreadCount.load( atomics::memory_order_acquire ) == 0 )
-                            break;
-                    }
-                }
-            }
-        };
-
-    protected:
-        template <class Set>
-        void do_test( size_t nLoadFactor )
-        {
-            Set  testSet( c_nSetSize, nLoadFactor );
-            do_test_with( testSet );
-            analyze( testSet );
-        }
-
-        template <class Set>
-        void do_test_extract( size_t nLoadFactor )
-        {
-            Set  testSet( c_nSetSize, nLoadFactor );
-            do_test_extract_with( testSet );
-            analyze( testSet );
-        }
-
-        template <class Set>
-        void do_test_with( Set& testSet )
-        {
-            typedef InsertThread<Set> insert_thread;
-            typedef DeleteThread<Set> delete_thread;
-
-            m_nInsThreadCount.store( c_nInsThreadCount, atomics::memory_order_release );
-
-            CppUnitMini::ThreadPool pool( *this );
-            pool.add( new insert_thread( pool, testSet ), c_nInsThreadCount );
-            pool.add( new delete_thread( pool, testSet ), c_nDelThreadCount ? c_nDelThreadCount : cds::OS::topology::processor_count());
-            pool.run();
-            CPPUNIT_MSG( "   Duration=" << pool.avgDuration() );
-
-            size_t nInsertSuccess = 0;
-            size_t nInsertFailed = 0;
-            size_t nDeleteSuccess = 0;
-            size_t nDeleteFailed = 0;
-            for ( CppUnitMini::ThreadPool::iterator it = pool.begin(); it != pool.end(); ++it ) {
-                insert_thread * pThread = dynamic_cast<insert_thread *>( *it );
-                if ( pThread ) {
-                    nInsertSuccess += pThread->m_nInsertSuccess;
-                    nInsertFailed += pThread->m_nInsertFailed;
-                }
-                else {
-                    delete_thread * p = static_cast<delete_thread *>( *it );
-                    nDeleteSuccess += p->m_nDeleteSuccess;
-                    nDeleteFailed += p->m_nDeleteFailed;
-                }
-            }
-
-            CPPUNIT_CHECK( nInsertSuccess == c_nSetSize * c_nInsThreadCount );
-            CPPUNIT_CHECK( nInsertFailed == 0 );
-
-            CPPUNIT_MSG( "  Totals (success/failed): \n\t"
-                      << "      Insert=" << nInsertSuccess << '/' << nInsertFailed << "\n\t"
-                      << "      Delete=" << nDeleteSuccess << '/' << nDeleteFailed << "\n\t"
-            );
-        }
-
-        template <class Set>
-        void do_test_extract_with( Set& testSet )
-        {
-            typedef InsertThread<Set> insert_thread;
-            typedef DeleteThread<Set> delete_thread;
-            typedef ExtractThread< typename Set::gc, Set > extract_thread;
-
-            m_nInsThreadCount.store( c_nInsThreadCount, atomics::memory_order_release );
-
-            CppUnitMini::ThreadPool pool( *this );
-            pool.add( new insert_thread( pool, testSet ), c_nInsThreadCount );
-            if ( c_nDelThreadCount )
-                pool.add( new delete_thread( pool, testSet ), c_nDelThreadCount );
-            if ( c_nExtractThreadCount )
-                pool.add( new extract_thread( pool, testSet ), c_nExtractThreadCount );
-            pool.run();
-            CPPUNIT_MSG( "   Duration=" << pool.avgDuration() );
-
-            size_t nInsertSuccess = 0;
-            size_t nInsertFailed = 0;
-            size_t nDeleteSuccess = 0;
-            size_t nDeleteFailed = 0;
-            size_t nExtractSuccess = 0;
-            size_t nExtractFailed = 0;
-            for ( CppUnitMini::ThreadPool::iterator it = pool.begin(); it != pool.end(); ++it ) {
-                insert_thread * pThread = dynamic_cast<insert_thread *>( *it );
-                if ( pThread ) {
-                    nInsertSuccess += pThread->m_nInsertSuccess;
-                    nInsertFailed += pThread->m_nInsertFailed;
-                }
-                else {
-                    delete_thread * p = dynamic_cast<delete_thread *>( *it );
-                    if ( p ) {
-                        nDeleteSuccess += p->m_nDeleteSuccess;
-                        nDeleteFailed += p->m_nDeleteFailed;
-                    }
-                    else {
-                        extract_thread * pExt = dynamic_cast<extract_thread *>( *it );
-                        assert( pExt );
-                        nExtractSuccess += pExt->m_nExtractSuccess;
-                        nExtractFailed += pExt->m_nExtractFailed;
-                    }
-                }
-            }
-
-            CPPUNIT_CHECK( nInsertSuccess == c_nSetSize * c_nInsThreadCount );
-            CPPUNIT_CHECK( nInsertFailed == 0 );
-
-            CPPUNIT_MSG( "  Totals (success/failed): \n\t"
-                << "      Insert=" << nInsertSuccess << '/' << nInsertFailed << "\n\t"
-                << "      Delete=" << nDeleteSuccess << '/' << nDeleteFailed << "\n\t"
-                << "      Extract=" << nExtractSuccess << '/' << nExtractFailed << "\n\t"
-                );
-        }
-
-        template <typename Set>
-        void analyze( Set& testSet )
-        {
-            // All even keys must be in the set
-            {
-                CPPUNIT_MSG( "  Check even keys..." );
-                size_t nErrorCount = 0;
-                for ( size_t n = 0; n < c_nSetSize; n +=2 ) {
-                    for ( size_t i = 0; i < c_nInsThreadCount; ++i ) {
-                        if ( !testSet.find( key_type(n, i) ) ) {
-                            if ( ++nErrorCount < 10 ) {
-                                CPPUNIT_MSG( "key " << n << "-" << i << " is not found!");
-                            }
-                        }
-                    }
-                }
-                CPPUNIT_CHECK_EX( nErrorCount == 0, "Totals: " << nErrorCount << " keys is not found");
-            }
-
-            check_before_clear( testSet );
-
-            CPPUNIT_MSG( "  Clear map (single-threaded)..." );
-            cds::OS::Timer    timer;
-            testSet.clear();
-            CPPUNIT_MSG( "   Duration=" << timer.duration() );
-            CPPUNIT_CHECK_EX( testSet.empty(), ((long long) testSet.size()) );
-
-            additional_check( testSet );
-            print_stat( testSet );
-            additional_cleanup( testSet );
-        }
-
-        template <class Set>
-        void test()
-        {
-            CPPUNIT_MSG( "Insert thread count=" << c_nInsThreadCount
-                << " delete thread count=" << c_nDelThreadCount
-                << " set size=" << c_nSetSize
-                );
-
-            for ( size_t nLoadFactor = 1; nLoadFactor <= c_nMaxLoadFactor; nLoadFactor *= 2 ) {
-                CPPUNIT_MSG( "Load factor=" << nLoadFactor );
-                do_test<Set>( nLoadFactor );
-                if ( c_bPrintGCState )
-                    print_gc_state();
-            }
-        }
-
-        template <class Set>
-        void test_extract()
-        {
-            CPPUNIT_MSG( "Insert thread count=" << c_nInsThreadCount
-                << " delete thread count=" << c_nDelThreadCount
-                << " extract thread count=" << c_nExtractThreadCount
-                << " set size=" << c_nSetSize
-                );
-
-            for ( size_t nLoadFactor = 1; nLoadFactor <= c_nMaxLoadFactor; nLoadFactor *= 2 ) {
-                CPPUNIT_MSG( "Load factor=" << nLoadFactor );
-                do_test_extract<Set>( nLoadFactor );
-                if ( c_bPrintGCState )
-                    print_gc_state();
-            }
-        }
-
-        template <class Set>
-        void test_nolf()
-        {
-            CPPUNIT_MSG( "Insert thread count=" << c_nInsThreadCount
-                << " delete thread count=" << c_nDelThreadCount
-                << " set size=" << c_nSetSize
-                );
-
-            {
-                Set s;
-                do_test_with( s );
-                analyze( s );
-            }
-
-            if ( c_bPrintGCState )
-                print_gc_state();
-        }
-
-        template <class Set>
-        void test_nolf_extract()
-        {
-            CPPUNIT_MSG( "Insert thread count=" << c_nInsThreadCount
-                << " delete thread count=" << c_nDelThreadCount
-                << " extract thread count=" << c_nExtractThreadCount
-                << " set size=" << c_nSetSize
-                );
-
-            {
-                Set s;
-                do_test_extract_with( s );
-                analyze( s );
-            }
-
-            if ( c_bPrintGCState )
-                print_gc_state();
-        }
-
-        void setUpParams( const CppUnitMini::TestCfg& cfg ) {
-            c_nSetSize = cfg.getULong("MapSize", static_cast<unsigned long>(c_nSetSize) );
-            c_nInsThreadCount = cfg.getULong("InsThreadCount", static_cast<unsigned long>(c_nInsThreadCount) );
-            c_nDelThreadCount = cfg.getULong("DelThreadCount", static_cast<unsigned long>(c_nDelThreadCount) );
-            c_nExtractThreadCount = cfg.getULong("ExtractThreadCount", static_cast<unsigned long>(c_nExtractThreadCount) );
-            c_nMaxLoadFactor = cfg.getULong("MaxLoadFactor", static_cast<unsigned long>(c_nMaxLoadFactor) );
-            c_bPrintGCState = cfg.getBool("PrintGCStateFlag", true );
-
-            if ( c_nInsThreadCount == 0 )
-                c_nInsThreadCount = cds::OS::topology::processor_count();
-            if ( c_nDelThreadCount == 0 && c_nExtractThreadCount == 0 ) {
-                c_nExtractThreadCount = cds::OS::topology::processor_count() / 2;
-                c_nDelThreadCount = cds::OS::topology::processor_count() - c_nExtractThreadCount;
-            }
-
-            m_arrData.resize( c_nSetSize );
-            for ( size_t i = 0; i < c_nSetSize; ++i )
-                m_arrData[i] = i;
-            std::random_shuffle( m_arrData.begin(), m_arrData.end() );
-        }
-
-#   include "set2/set_defs.h"
-        CDSUNIT_DECLARE_MichaelSet
-        CDSUNIT_DECLARE_SplitList
-        //CDSUNIT_DECLARE_StripedSet
-        //CDSUNIT_DECLARE_RefinableSet
-        CDSUNIT_DECLARE_CuckooSet
-        CDSUNIT_DECLARE_SkipListSet
-        CDSUNIT_DECLARE_EllenBinTreeSet
-        //CDSUNIT_DECLARE_StdSet
-
-        CPPUNIT_TEST_SUITE_( Set_DelOdd, "Map_DelOdd" )
-            CDSUNIT_TEST_MichaelSet
-            CDSUNIT_TEST_SplitList
-            CDSUNIT_TEST_SkipListSet
-            CDSUNIT_TEST_EllenBinTreeSet
-            //CDSUNIT_TEST_StripedSet
-            //CDSUNIT_TEST_RefinableSet
-            CDSUNIT_TEST_CuckooSet
-            //CDSUNIT_TEST_StdSet
-        CPPUNIT_TEST_SUITE_END()
-    };
-
-    CPPUNIT_TEST_SUITE_REGISTRATION( Set_DelOdd );
 } // namespace set2
diff --git a/tests/unit/set2/set_delodd.h b/tests/unit/set2/set_delodd.h
new file mode 100644 (file)
index 0000000..f06102c
--- /dev/null
@@ -0,0 +1,752 @@
+//$$CDS-header$$
+
+#include "cppunit/thread.h"
+#include "set2/set_types.h"
+#include <algorithm> // random_shuffle
+
+namespace set2 {
+
+#    define TEST_SET(X)         void X() { test<SetTypes<key_type, value_type>::X >()    ; }
+#    define TEST_SET_EXTRACT(X) void X() { test_extract<SetTypes<key_type, value_type>::X >()    ; }
+#    define TEST_SET_NOLF(X)    void X() { test_nolf<SetTypes<key_type, value_type>::X >()    ; }
+#    define TEST_SET_NOLF_EXTRACT(X)    void X() { test_nolf_extract<SetTypes<key_type, value_type>::X >()    ; }
+
+    namespace {
+        struct key_thread
+        {
+            size_t  nKey;
+            size_t  nThread;
+
+            key_thread( size_t key, size_t threadNo )
+                : nKey( key )
+                , nThread( threadNo )
+            {}
+
+            key_thread()
+            {}
+        };
+
+        typedef SetTypes<key_thread, size_t>::key_val     key_value_pair;
+    }
+
+    template <>
+    struct cmp<key_thread> {
+        int operator ()(key_thread const& k1, key_thread const& k2) const
+        {
+            if ( k1.nKey < k2.nKey )
+                return -1;
+            if ( k1.nKey > k2.nKey )
+                return 1;
+            if ( k1.nThread < k2.nThread )
+                return -1;
+            if ( k1.nThread > k2.nThread )
+                return 1;
+            return 0;
+        }
+        int operator ()(key_thread const& k1, size_t k2) const
+        {
+            if ( k1.nKey < k2 )
+                return -1;
+            if ( k1.nKey > k2 )
+                return 1;
+            return 0;
+        }
+        int operator ()(size_t k1, key_thread const& k2) const
+        {
+            if ( k1 < k2.nKey )
+                return -1;
+            if ( k1 > k2.nKey )
+                return 1;
+            return 0;
+        }
+    };
+
+} // namespace set2
+
+namespace std {
+    template <>
+    struct less<set2::key_thread>
+    {
+        bool operator()(set2::key_thread const& k1, set2::key_thread const& k2) const
+        {
+            if ( k1.nKey <= k2.nKey )
+                return k1.nKey < k2.nKey || k1.nThread < k2.nThread;
+            return false;
+        }
+    };
+
+    template <>
+    struct hash<set2::key_thread>
+    {
+        typedef size_t              result_type;
+        typedef set2::key_thread    argument_type;
+
+        size_t operator()( set2::key_thread const& k ) const
+        {
+            return std::hash<size_t>()(k.nKey);
+        }
+        size_t operator()( size_t k ) const
+        {
+            return std::hash<size_t>()(k);
+        }
+    };
+
+} // namespace std
+
+namespace boost {
+    inline size_t hash_value( set2::key_thread const& k )
+    {
+        return std::hash<size_t>()( k.nKey );
+    }
+
+    template <>
+    struct hash<set2::key_thread>
+    {
+        typedef size_t              result_type;
+        typedef set2::key_thread    argument_type;
+
+        size_t operator()(set2::key_thread const& k) const
+        {
+            return boost::hash<size_t>()( k.nKey );
+        }
+        size_t operator()(size_t k) const
+        {
+            return boost::hash<size_t>()( k );
+        }
+    };
+} // namespace boost
+
+namespace set2 {
+
+    class Set_DelOdd: public CppUnitMini::TestCase
+    {
+        static size_t  c_nSetSize;          // max set size
+        static size_t  c_nInsThreadCount;   // insert thread count
+        static size_t  c_nDelThreadCount;   // delete thread count
+        static size_t  c_nExtractThreadCount;  // extract thread count
+        static size_t  c_nMaxLoadFactor;    // maximum load factor
+        static bool    c_bPrintGCState;
+
+        std::vector<size_t>     m_arrData;
+
+    protected:
+        typedef CppUnitMini::TestCase Base;
+        typedef key_thread  key_type;
+        typedef size_t      value_type;
+
+        atomics::atomic<size_t>      m_nInsThreadCount;
+
+        // Inserts keys from [0..N)
+        template <class Set>
+        class InsertThread: public CppUnitMini::TestThread
+        {
+            Set&     m_Set;
+
+            virtual InsertThread *    clone()
+            {
+                return new InsertThread( *this );
+            }
+
+            struct ensure_func
+            {
+                template <typename Q>
+                void operator()( bool /*bNew*/, key_value_pair const&, Q const& )
+                {}
+            };
+        public:
+            size_t  m_nInsertSuccess;
+            size_t  m_nInsertFailed;
+
+        public:
+            InsertThread( CppUnitMini::ThreadPool& pool, Set& rMap )
+                : CppUnitMini::TestThread( pool )
+                , m_Set( rMap )
+            {}
+            InsertThread( InsertThread& src )
+                : CppUnitMini::TestThread( src )
+                , m_Set( src.m_Set )
+            {}
+
+            Set_DelOdd&  getTest()
+            {
+                return reinterpret_cast<Set_DelOdd&>( m_Pool.m_Test );
+            }
+
+            virtual void init() { cds::threading::Manager::attachThread()   ; }
+            virtual void fini() { cds::threading::Manager::detachThread()   ; }
+
+            virtual void test()
+            {
+                Set& rSet = m_Set;
+
+                m_nInsertSuccess =
+                    m_nInsertFailed = 0;
+
+                std::vector<size_t>& arrData = getTest().m_arrData;
+                for ( size_t i = 0; i < arrData.size(); ++i ) {
+                    if ( rSet.insert( key_type( arrData[i], m_nThreadNo )))
+                        ++m_nInsertSuccess;
+                    else
+                        ++m_nInsertFailed;
+                }
+
+                ensure_func f;
+                for ( size_t i = arrData.size() - 1; i > 0; --i ) {
+                    if ( arrData[i] & 1 ) {
+                        rSet.ensure( key_type( arrData[i], m_nThreadNo ), f );
+                    }
+                }
+
+                getTest().m_nInsThreadCount.fetch_sub( 1, atomics::memory_order_release );
+            }
+        };
+
+        struct key_equal {
+            bool operator()( key_type const& k1, key_type const& k2 ) const
+            {
+                return k1.nKey == k2.nKey;
+            }
+            bool operator()( size_t k1, key_type const& k2 ) const
+            {
+                return k1 == k2.nKey;
+            }
+            bool operator()( key_type const& k1, size_t k2 ) const
+            {
+                return k1.nKey == k2;
+            }
+            bool operator ()( key_value_pair const& k1, key_value_pair const& k2 ) const
+            {
+                return operator()( k1.key, k2.key );
+            }
+            bool operator ()( key_value_pair const& k1, key_type const& k2 ) const
+            {
+                return operator()( k1.key, k2 );
+            }
+            bool operator ()( key_type const& k1, key_value_pair const& k2 ) const
+            {
+                return operator()( k1, k2.key );
+            }
+            bool operator ()( key_value_pair const& k1, size_t k2 ) const
+            {
+                return operator()( k1.key, k2 );
+            }
+            bool operator ()( size_t k1, key_value_pair const& k2 ) const
+            {
+                return operator()( k1, k2.key );
+            }
+        };
+
+        struct key_less {
+            bool operator()( key_type const& k1, key_type const& k2 ) const
+            {
+                return k1.nKey < k2.nKey;
+            }
+            bool operator()( size_t k1, key_type const& k2 ) const
+            {
+                return k1 < k2.nKey;
+            }
+            bool operator()( key_type const& k1, size_t k2 ) const
+            {
+                return k1.nKey < k2;
+            }
+            bool operator ()( key_value_pair const& k1, key_value_pair const& k2 ) const
+            {
+                return operator()( k1.key, k2.key );
+            }
+            bool operator ()( key_value_pair const& k1, key_type const& k2 ) const
+            {
+                return operator()( k1.key, k2 );
+            }
+            bool operator ()( key_type const& k1, key_value_pair const& k2 ) const
+            {
+                return operator()( k1, k2.key );
+            }
+            bool operator ()( key_value_pair const& k1, size_t k2 ) const
+            {
+                return operator()( k1.key, k2 );
+            }
+            bool operator ()( size_t k1, key_value_pair const& k2 ) const
+            {
+                return operator()( k1, k2.key );
+            }
+
+            typedef key_equal   equal_to;
+        };
+
+        // Deletes odd keys from [0..N)
+        template <class Set>
+        class DeleteThread: public CppUnitMini::TestThread
+        {
+            Set&     m_Set;
+
+            virtual DeleteThread *    clone()
+            {
+                return new DeleteThread( *this );
+            }
+        public:
+            size_t  m_nDeleteSuccess;
+            size_t  m_nDeleteFailed;
+
+        public:
+            DeleteThread( CppUnitMini::ThreadPool& pool, Set& rMap )
+                : CppUnitMini::TestThread( pool )
+                , m_Set( rMap )
+            {}
+            DeleteThread( DeleteThread& src )
+                : CppUnitMini::TestThread( src )
+                , m_Set( src.m_Set )
+            {}
+
+            Set_DelOdd&  getTest()
+            {
+                return reinterpret_cast<Set_DelOdd&>( m_Pool.m_Test );
+            }
+
+            virtual void init() { cds::threading::Manager::attachThread()   ; }
+            virtual void fini() { cds::threading::Manager::detachThread()   ; }
+
+            virtual void test()
+            {
+                Set& rSet = m_Set;
+
+                m_nDeleteSuccess =
+                    m_nDeleteFailed = 0;
+
+                std::vector<size_t>& arrData = getTest().m_arrData;
+                if ( m_nThreadNo & 1 ) {
+                    for ( size_t k = 0; k < c_nInsThreadCount; ++k ) {
+                        for ( size_t i = 0; i < arrData.size(); ++i ) {
+                            if ( arrData[i] & 1 ) {
+                                if ( rSet.erase_with( arrData[i], key_less() ))
+                                    ++m_nDeleteSuccess;
+                                else
+                                    ++m_nDeleteFailed;
+                            }
+                        }
+                        if ( getTest().m_nInsThreadCount.load( atomics::memory_order_acquire ) == 0 )
+                            break;
+                    }
+                }
+                else {
+                    for ( size_t k = 0; k < c_nInsThreadCount; ++k ) {
+                        for ( size_t i = arrData.size() - 1; i > 0; --i ) {
+                            if ( arrData[i] & 1 ) {
+                                if ( rSet.erase_with( arrData[i], key_less() ))
+                                    ++m_nDeleteSuccess;
+                                else
+                                    ++m_nDeleteFailed;
+                            }
+                        }
+                        if ( getTest().m_nInsThreadCount.load( atomics::memory_order_acquire ) == 0 )
+                            break;
+                    }
+                }
+            }
+        };
+
+        // Extracts odd keys from [0..N)
+        template <typename GC, class Set>
+        class ExtractThread: public CppUnitMini::TestThread
+        {
+            Set&     m_Set;
+
+            virtual ExtractThread *    clone()
+            {
+                return new ExtractThread( *this );
+            }
+        public:
+            size_t  m_nExtractSuccess;
+            size_t  m_nExtractFailed;
+
+        public:
+            ExtractThread( CppUnitMini::ThreadPool& pool, Set& rMap )
+                : CppUnitMini::TestThread( pool )
+                , m_Set( rMap )
+            {}
+            ExtractThread( ExtractThread& src )
+                : CppUnitMini::TestThread( src )
+                , m_Set( src.m_Set )
+            {}
+
+            Set_DelOdd&  getTest()
+            {
+                return reinterpret_cast<Set_DelOdd&>( m_Pool.m_Test );
+            }
+
+            virtual void init() { cds::threading::Manager::attachThread()   ; }
+            virtual void fini() { cds::threading::Manager::detachThread()   ; }
+
+            virtual void test()
+            {
+                Set& rSet = m_Set;
+
+                m_nExtractSuccess =
+                    m_nExtractFailed = 0;
+
+                typename Set::guarded_ptr gp;
+
+                std::vector<size_t>& arrData = getTest().m_arrData;
+                if ( m_nThreadNo & 1 ) {
+                    for ( size_t k = 0; k < c_nInsThreadCount; ++k ) {
+                        for ( size_t i = 0; i < arrData.size(); ++i ) {
+                            if ( arrData[i] & 1 ) {
+                                gp = rSet.extract_with( arrData[i], key_less());
+                                if ( gp )
+                                    ++m_nExtractSuccess;
+                                else
+                                    ++m_nExtractFailed;
+                                gp.release();
+                            }
+                        }
+                        if ( getTest().m_nInsThreadCount.load( atomics::memory_order_acquire ) == 0 )
+                            break;
+                    }
+                }
+                else {
+                    for ( size_t k = 0; k < c_nInsThreadCount; ++k ) {
+                        for ( size_t i = arrData.size() - 1; i > 0; --i ) {
+                            if ( arrData[i] & 1 ) {
+                                gp = rSet.extract_with( arrData[i], key_less());
+                                if ( gp )
+                                    ++m_nExtractSuccess;
+                                else
+                                    ++m_nExtractFailed;
+                                gp.release();
+                            }
+                        }
+                        if ( getTest().m_nInsThreadCount.load( atomics::memory_order_acquire ) == 0 )
+                            break;
+                    }
+                }
+            }
+        };
+
+        template <typename RCU, class Set>
+        class ExtractThread< cds::urcu::gc<RCU>, Set >: public CppUnitMini::TestThread
+        {
+            Set&     m_Set;
+
+            virtual ExtractThread *    clone()
+            {
+                return new ExtractThread( *this );
+            }
+        public:
+            size_t  m_nExtractSuccess;
+            size_t  m_nExtractFailed;
+
+        public:
+            ExtractThread( CppUnitMini::ThreadPool& pool, Set& rMap )
+                : CppUnitMini::TestThread( pool )
+                , m_Set( rMap )
+            {}
+            ExtractThread( ExtractThread& src )
+                : CppUnitMini::TestThread( src )
+                , m_Set( src.m_Set )
+            {}
+
+            Set_DelOdd&  getTest()
+            {
+                return reinterpret_cast<Set_DelOdd&>( m_Pool.m_Test );
+            }
+
+            virtual void init() { cds::threading::Manager::attachThread()   ; }
+            virtual void fini() { cds::threading::Manager::detachThread()   ; }
+
+            virtual void test()
+            {
+                Set& rSet = m_Set;
+
+                m_nExtractSuccess =
+                    m_nExtractFailed = 0;
+
+                typename Set::exempt_ptr xp;
+
+                std::vector<size_t>& arrData = getTest().m_arrData;
+                if ( m_nThreadNo & 1 ) {
+                    for ( size_t k = 0; k < c_nInsThreadCount; ++k ) {
+                        for ( size_t i = 0; i < arrData.size(); ++i ) {
+                            if ( arrData[i] & 1 ) {
+                                if ( Set::c_bExtractLockExternal ) {
+                                    typename Set::rcu_lock l;
+                                    xp = rSet.extract_with( arrData[i], key_less() );
+                                    if ( xp )
+                                        ++m_nExtractSuccess;
+                                    else
+                                        ++m_nExtractFailed;
+                                }
+                                else {
+                                    xp = rSet.extract_with( arrData[i], key_less() );
+                                    if ( xp )
+                                        ++m_nExtractSuccess;
+                                    else
+                                        ++m_nExtractFailed;
+                                }
+                                xp.release();
+                            }
+                        }
+                        if ( getTest().m_nInsThreadCount.load( atomics::memory_order_acquire ) == 0 )
+                            break;
+                    }
+                }
+                else {
+                    for ( size_t k = 0; k < c_nInsThreadCount; ++k ) {
+                        for ( size_t i = arrData.size() - 1; i > 0; --i ) {
+                            if ( arrData[i] & 1 ) {
+                                if ( Set::c_bExtractLockExternal ) {
+                                    typename Set::rcu_lock l;
+                                    xp = rSet.extract_with( arrData[i], key_less() );
+                                    if ( xp )
+                                        ++m_nExtractSuccess;
+                                    else
+                                        ++m_nExtractFailed;
+                                }
+                                else {
+                                    xp = rSet.extract_with( arrData[i], key_less() );
+                                    if ( xp )
+                                        ++m_nExtractSuccess;
+                                    else
+                                        ++m_nExtractFailed;
+                                }
+                                xp.release();
+                            }
+                        }
+                        if ( getTest().m_nInsThreadCount.load( atomics::memory_order_acquire ) == 0 )
+                            break;
+                    }
+                }
+            }
+        };
+
+    protected:
+        template <class Set>
+        void do_test( size_t nLoadFactor )
+        {
+            Set  testSet( c_nSetSize, nLoadFactor );
+            do_test_with( testSet );
+            analyze( testSet );
+        }
+
+        template <class Set>
+        void do_test_extract( size_t nLoadFactor )
+        {
+            Set  testSet( c_nSetSize, nLoadFactor );
+            do_test_extract_with( testSet );
+            analyze( testSet );
+        }
+
+        template <class Set>
+        void do_test_with( Set& testSet )
+        {
+            typedef InsertThread<Set> insert_thread;
+            typedef DeleteThread<Set> delete_thread;
+
+            m_nInsThreadCount.store( c_nInsThreadCount, atomics::memory_order_release );
+
+            CppUnitMini::ThreadPool pool( *this );
+            pool.add( new insert_thread( pool, testSet ), c_nInsThreadCount );
+            pool.add( new delete_thread( pool, testSet ), c_nDelThreadCount ? c_nDelThreadCount : cds::OS::topology::processor_count());
+            pool.run();
+            CPPUNIT_MSG( "   Duration=" << pool.avgDuration() );
+
+            size_t nInsertSuccess = 0;
+            size_t nInsertFailed = 0;
+            size_t nDeleteSuccess = 0;
+            size_t nDeleteFailed = 0;
+            for ( CppUnitMini::ThreadPool::iterator it = pool.begin(); it != pool.end(); ++it ) {
+                insert_thread * pThread = dynamic_cast<insert_thread *>( *it );
+                if ( pThread ) {
+                    nInsertSuccess += pThread->m_nInsertSuccess;
+                    nInsertFailed += pThread->m_nInsertFailed;
+                }
+                else {
+                    delete_thread * p = static_cast<delete_thread *>( *it );
+                    nDeleteSuccess += p->m_nDeleteSuccess;
+                    nDeleteFailed += p->m_nDeleteFailed;
+                }
+            }
+
+            CPPUNIT_CHECK( nInsertSuccess == c_nSetSize * c_nInsThreadCount );
+            CPPUNIT_CHECK( nInsertFailed == 0 );
+
+            CPPUNIT_MSG( "  Totals (success/failed): \n\t"
+                      << "      Insert=" << nInsertSuccess << '/' << nInsertFailed << "\n\t"
+                      << "      Delete=" << nDeleteSuccess << '/' << nDeleteFailed << "\n\t"
+            );
+        }
+
+        template <class Set>
+        void do_test_extract_with( Set& testSet )
+        {
+            typedef InsertThread<Set> insert_thread;
+            typedef DeleteThread<Set> delete_thread;
+            typedef ExtractThread< typename Set::gc, Set > extract_thread;
+
+            m_nInsThreadCount.store( c_nInsThreadCount, atomics::memory_order_release );
+
+            CppUnitMini::ThreadPool pool( *this );
+            pool.add( new insert_thread( pool, testSet ), c_nInsThreadCount );
+            if ( c_nDelThreadCount )
+                pool.add( new delete_thread( pool, testSet ), c_nDelThreadCount );
+            if ( c_nExtractThreadCount )
+                pool.add( new extract_thread( pool, testSet ), c_nExtractThreadCount );
+            pool.run();
+            CPPUNIT_MSG( "   Duration=" << pool.avgDuration() );
+
+            size_t nInsertSuccess = 0;
+            size_t nInsertFailed = 0;
+            size_t nDeleteSuccess = 0;
+            size_t nDeleteFailed = 0;
+            size_t nExtractSuccess = 0;
+            size_t nExtractFailed = 0;
+            for ( CppUnitMini::ThreadPool::iterator it = pool.begin(); it != pool.end(); ++it ) {
+                insert_thread * pThread = dynamic_cast<insert_thread *>( *it );
+                if ( pThread ) {
+                    nInsertSuccess += pThread->m_nInsertSuccess;
+                    nInsertFailed += pThread->m_nInsertFailed;
+                }
+                else {
+                    delete_thread * p = dynamic_cast<delete_thread *>( *it );
+                    if ( p ) {
+                        nDeleteSuccess += p->m_nDeleteSuccess;
+                        nDeleteFailed += p->m_nDeleteFailed;
+                    }
+                    else {
+                        extract_thread * pExt = dynamic_cast<extract_thread *>( *it );
+                        assert( pExt );
+                        nExtractSuccess += pExt->m_nExtractSuccess;
+                        nExtractFailed += pExt->m_nExtractFailed;
+                    }
+                }
+            }
+
+            CPPUNIT_CHECK( nInsertSuccess == c_nSetSize * c_nInsThreadCount );
+            CPPUNIT_CHECK( nInsertFailed == 0 );
+
+            CPPUNIT_MSG( "  Totals (success/failed): \n\t"
+                << "      Insert=" << nInsertSuccess << '/' << nInsertFailed << "\n\t"
+                << "      Delete=" << nDeleteSuccess << '/' << nDeleteFailed << "\n\t"
+                << "      Extract=" << nExtractSuccess << '/' << nExtractFailed << "\n\t"
+                );
+        }
+
+        template <typename Set>
+        void analyze( Set& testSet )
+        {
+            // All even keys must be in the set
+            {
+                CPPUNIT_MSG( "  Check even keys..." );
+                size_t nErrorCount = 0;
+                for ( size_t n = 0; n < c_nSetSize; n +=2 ) {
+                    for ( size_t i = 0; i < c_nInsThreadCount; ++i ) {
+                        if ( !testSet.find( key_type(n, i) ) ) {
+                            if ( ++nErrorCount < 10 ) {
+                                CPPUNIT_MSG( "key " << n << "-" << i << " is not found!");
+                            }
+                        }
+                    }
+                }
+                CPPUNIT_CHECK_EX( nErrorCount == 0, "Totals: " << nErrorCount << " keys is not found");
+            }
+
+            check_before_clear( testSet );
+
+            CPPUNIT_MSG( "  Clear map (single-threaded)..." );
+            cds::OS::Timer    timer;
+            testSet.clear();
+            CPPUNIT_MSG( "   Duration=" << timer.duration() );
+            CPPUNIT_CHECK_EX( testSet.empty(), ((long long) testSet.size()) );
+
+            additional_check( testSet );
+            print_stat( testSet );
+            additional_cleanup( testSet );
+        }
+
+        template <class Set>
+        void test()
+        {
+            CPPUNIT_MSG( "Insert thread count=" << c_nInsThreadCount
+                << " delete thread count=" << c_nDelThreadCount
+                << " set size=" << c_nSetSize
+                );
+
+            for ( size_t nLoadFactor = 1; nLoadFactor <= c_nMaxLoadFactor; nLoadFactor *= 2 ) {
+                CPPUNIT_MSG( "Load factor=" << nLoadFactor );
+                do_test<Set>( nLoadFactor );
+                if ( c_bPrintGCState )
+                    print_gc_state();
+            }
+        }
+
+        template <class Set>
+        void test_extract()
+        {
+            CPPUNIT_MSG( "Insert thread count=" << c_nInsThreadCount
+                << " delete thread count=" << c_nDelThreadCount
+                << " extract thread count=" << c_nExtractThreadCount
+                << " set size=" << c_nSetSize
+                );
+
+            for ( size_t nLoadFactor = 1; nLoadFactor <= c_nMaxLoadFactor; nLoadFactor *= 2 ) {
+                CPPUNIT_MSG( "Load factor=" << nLoadFactor );
+                do_test_extract<Set>( nLoadFactor );
+                if ( c_bPrintGCState )
+                    print_gc_state();
+            }
+        }
+
+        template <class Set>
+        void test_nolf()
+        {
+            CPPUNIT_MSG( "Insert thread count=" << c_nInsThreadCount
+                << " delete thread count=" << c_nDelThreadCount
+                << " set size=" << c_nSetSize
+                );
+
+            {
+                Set s;
+                do_test_with( s );
+                analyze( s );
+            }
+
+            if ( c_bPrintGCState )
+                print_gc_state();
+        }
+
+        template <class Set>
+        void test_nolf_extract()
+        {
+            CPPUNIT_MSG( "Insert thread count=" << c_nInsThreadCount
+                << " delete thread count=" << c_nDelThreadCount
+                << " extract thread count=" << c_nExtractThreadCount
+                << " set size=" << c_nSetSize
+                );
+
+            {
+                Set s;
+                do_test_extract_with( s );
+                analyze( s );
+            }
+
+            if ( c_bPrintGCState )
+                print_gc_state();
+        }
+
+        void setUpParams( const CppUnitMini::TestCfg& cfg );
+
+        void run_MichaelSet(const char *in_name, bool invert = false);
+        void run_SplitList(const char *in_name, bool invert = false);
+        void run_CuckooSet(const char *in_name, bool invert = false);
+        void run_SkipListSet(const char *in_name, bool invert = false);
+        void run_EllenBinTreeSet(const char *in_name, bool invert = false);
+
+        virtual void myRun(const char *in_name, bool invert = false);
+
+
+#   include "set2/set_defs.h"
+        CDSUNIT_DECLARE_MichaelSet
+        CDSUNIT_DECLARE_SplitList
+        CDSUNIT_DECLARE_CuckooSet
+        CDSUNIT_DECLARE_SkipListSet
+        CDSUNIT_DECLARE_EllenBinTreeSet
+    };
+} // namespace set2
diff --git a/tests/unit/set2/set_delodd_cuckoo.cpp b/tests/unit/set2/set_delodd_cuckoo.cpp
new file mode 100644 (file)
index 0000000..80ca8d5
--- /dev/null
@@ -0,0 +1,10 @@
+//$$CDS-header$$
+
+#include "set2/set_delodd.h"
+
+namespace set2 {
+    CPPUNIT_TEST_SUITE_PART( Set_DelOdd, run_CuckooSet )
+        CDSUNIT_TEST_CuckooSet
+    CPPUNIT_TEST_SUITE_END_PART()
+
+} // namespace set2
diff --git a/tests/unit/set2/set_delodd_ellentree.cpp b/tests/unit/set2/set_delodd_ellentree.cpp
new file mode 100644 (file)
index 0000000..6bd29b4
--- /dev/null
@@ -0,0 +1,10 @@
+//$$CDS-header$$
+
+#include "set2/set_delodd.h"
+
+namespace set2 {
+    CPPUNIT_TEST_SUITE_PART( Set_DelOdd, run_EllenBinTreeSet )
+        CDSUNIT_TEST_EllenBinTreeSet
+    CPPUNIT_TEST_SUITE_END_PART()
+
+} // namespace set2
diff --git a/tests/unit/set2/set_delodd_michael.cpp b/tests/unit/set2/set_delodd_michael.cpp
new file mode 100644 (file)
index 0000000..a988472
--- /dev/null
@@ -0,0 +1,10 @@
+//$$CDS-header$$
+
+#include "set2/set_delodd.h"
+
+namespace set2 {
+    CPPUNIT_TEST_SUITE_PART( Set_DelOdd, run_MichaelSet )
+        CDSUNIT_TEST_MichaelSet
+    CPPUNIT_TEST_SUITE_END_PART()
+
+} // namespace set2
diff --git a/tests/unit/set2/set_delodd_skip.cpp b/tests/unit/set2/set_delodd_skip.cpp
new file mode 100644 (file)
index 0000000..2a07299
--- /dev/null
@@ -0,0 +1,10 @@
+//$$CDS-header$$
+
+#include "set2/set_delodd.h"
+
+namespace set2 {
+    CPPUNIT_TEST_SUITE_PART( Set_DelOdd, run_SkipListSet )
+        CDSUNIT_TEST_SkipListSet
+    CPPUNIT_TEST_SUITE_END_PART()
+
+} // namespace set2
diff --git a/tests/unit/set2/set_delodd_split.cpp b/tests/unit/set2/set_delodd_split.cpp
new file mode 100644 (file)
index 0000000..85e8ba0
--- /dev/null
@@ -0,0 +1,10 @@
+//$$CDS-header$$
+
+#include "set2/set_delodd.h"
+
+namespace set2 {
+    CPPUNIT_TEST_SUITE_PART( Set_DelOdd, run_SplitList )
+        CDSUNIT_TEST_SplitList
+    CPPUNIT_TEST_SUITE_END_PART()
+
+} // namespace set2
diff --git a/tests/unit/set2/set_insdel_func2.cpp b/tests/unit/set2/set_insdel_func2.cpp
deleted file mode 100644 (file)
index fc77c6e..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-//$$CDS-header$$
-
-#include "set2/set_insdel_func.h"
-
-namespace set2 {
-    CPPUNIT_TEST_SUITE_PART( Set_InsDel_func, run_SplitList )
-        CDSUNIT_TEST_SplitList
-    CPPUNIT_TEST_SUITE_END_PART()
-
-} // namespace set2
diff --git a/tests/unit/set2/set_insdel_func3.cpp b/tests/unit/set2/set_insdel_func3.cpp
deleted file mode 100644 (file)
index 3a2765a..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-//$$CDS-header$$
-
-#include "set2/set_insdel_func.h"
-
-namespace set2 {
-    CPPUNIT_TEST_SUITE_PART( Set_InsDel_func, run_SkipListSet )
-        CDSUNIT_TEST_SkipListSet
-    CPPUNIT_TEST_SUITE_END_PART()
-
-} // namespace set2
diff --git a/tests/unit/set2/set_insdel_func4.cpp b/tests/unit/set2/set_insdel_func4.cpp
deleted file mode 100644 (file)
index f1951ab..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-//$$CDS-header$$
-
-#include "set2/set_insdel_func.h"
-
-namespace set2 {
-
-    CPPUNIT_TEST_SUITE_PART( Set_InsDel_func, run_StripedSet )
-        CDSUNIT_TEST_StripedSet
-    CPPUNIT_TEST_SUITE_END_PART()
-
-} // namespace set2
diff --git a/tests/unit/set2/set_insdel_func5.cpp b/tests/unit/set2/set_insdel_func5.cpp
deleted file mode 100644 (file)
index ac6ef50..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-//$$CDS-header$$
-
-#include "set2/set_insdel_func.h"
-
-namespace set2 {
-    CPPUNIT_TEST_SUITE_PART( Set_InsDel_func, run_RefinableSet )
-        CDSUNIT_TEST_RefinableSet
-    CPPUNIT_TEST_SUITE_END_PART()
-
-} // namespace set2
diff --git a/tests/unit/set2/set_insdel_func6.cpp b/tests/unit/set2/set_insdel_func6.cpp
deleted file mode 100644 (file)
index 5db7020..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-//$$CDS-header$$
-
-#include "set2/set_insdel_func.h"
-
-namespace set2 {
-    CPPUNIT_TEST_SUITE_PART( Set_InsDel_func, run_CuckooSet )
-        CDSUNIT_TEST_CuckooSet
-    CPPUNIT_TEST_SUITE_END_PART()
-
-} // namespace set2
diff --git a/tests/unit/set2/set_insdel_func7.cpp b/tests/unit/set2/set_insdel_func7.cpp
deleted file mode 100644 (file)
index d711857..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-//$$CDS-header$$
-
-#include "set2/set_insdel_func.h"
-
-namespace set2 {
-    CPPUNIT_TEST_SUITE_PART( Set_InsDel_func, run_EllenBinTreeSet )
-        CDSUNIT_TEST_EllenBinTreeSet
-    CPPUNIT_TEST_SUITE_END_PART()
-
-} // namespace set2
diff --git a/tests/unit/set2/set_insdel_func_cuckoo.cpp b/tests/unit/set2/set_insdel_func_cuckoo.cpp
new file mode 100644 (file)
index 0000000..5db7020
--- /dev/null
@@ -0,0 +1,10 @@
+//$$CDS-header$$
+
+#include "set2/set_insdel_func.h"
+
+namespace set2 {
+    CPPUNIT_TEST_SUITE_PART( Set_InsDel_func, run_CuckooSet )
+        CDSUNIT_TEST_CuckooSet
+    CPPUNIT_TEST_SUITE_END_PART()
+
+} // namespace set2
diff --git a/tests/unit/set2/set_insdel_func_ellentree.cpp b/tests/unit/set2/set_insdel_func_ellentree.cpp
new file mode 100644 (file)
index 0000000..d711857
--- /dev/null
@@ -0,0 +1,10 @@
+//$$CDS-header$$
+
+#include "set2/set_insdel_func.h"
+
+namespace set2 {
+    CPPUNIT_TEST_SUITE_PART( Set_InsDel_func, run_EllenBinTreeSet )
+        CDSUNIT_TEST_EllenBinTreeSet
+    CPPUNIT_TEST_SUITE_END_PART()
+
+} // namespace set2
diff --git a/tests/unit/set2/set_insdel_func_refinable.cpp b/tests/unit/set2/set_insdel_func_refinable.cpp
new file mode 100644 (file)
index 0000000..ac6ef50
--- /dev/null
@@ -0,0 +1,10 @@
+//$$CDS-header$$
+
+#include "set2/set_insdel_func.h"
+
+namespace set2 {
+    CPPUNIT_TEST_SUITE_PART( Set_InsDel_func, run_RefinableSet )
+        CDSUNIT_TEST_RefinableSet
+    CPPUNIT_TEST_SUITE_END_PART()
+
+} // namespace set2
diff --git a/tests/unit/set2/set_insdel_func_skip.cpp b/tests/unit/set2/set_insdel_func_skip.cpp
new file mode 100644 (file)
index 0000000..3a2765a
--- /dev/null
@@ -0,0 +1,10 @@
+//$$CDS-header$$
+
+#include "set2/set_insdel_func.h"
+
+namespace set2 {
+    CPPUNIT_TEST_SUITE_PART( Set_InsDel_func, run_SkipListSet )
+        CDSUNIT_TEST_SkipListSet
+    CPPUNIT_TEST_SUITE_END_PART()
+
+} // namespace set2
diff --git a/tests/unit/set2/set_insdel_func_split.cpp b/tests/unit/set2/set_insdel_func_split.cpp
new file mode 100644 (file)
index 0000000..fc77c6e
--- /dev/null
@@ -0,0 +1,10 @@
+//$$CDS-header$$
+
+#include "set2/set_insdel_func.h"
+
+namespace set2 {
+    CPPUNIT_TEST_SUITE_PART( Set_InsDel_func, run_SplitList )
+        CDSUNIT_TEST_SplitList
+    CPPUNIT_TEST_SUITE_END_PART()
+
+} // namespace set2
diff --git a/tests/unit/set2/set_insdel_func_striped.cpp b/tests/unit/set2/set_insdel_func_striped.cpp
new file mode 100644 (file)
index 0000000..f1951ab
--- /dev/null
@@ -0,0 +1,11 @@
+//$$CDS-header$$
+
+#include "set2/set_insdel_func.h"
+
+namespace set2 {
+
+    CPPUNIT_TEST_SUITE_PART( Set_InsDel_func, run_StripedSet )
+        CDSUNIT_TEST_StripedSet
+    CPPUNIT_TEST_SUITE_END_PART()
+
+} // namespace set2
index f025071ea38907c9d05dd03684cccc5fb18ce368..a0a2a669b4ad77108a833f2b4fa5220aafab8f24 100644 (file)
 //$$CDS-header$$
 
-#include "set2/set_types.h"
-#include "cppunit/thread.h"
-
-#include <vector>
+#include "set2/set_insdel_string.h"
 
 namespace set2 {
+    CPPUNIT_TEST_SUITE_REGISTRATION( Set_InsDel_string );
 
-#   define TEST_SET(X)          void X() { test<SetTypes<key_type, value_type>::X >(); }
-#   define TEST_SET_EXTRACT(X)  void X() { test_extract<SetTypes<key_type, value_type>::X >(); }
-#   define TEST_SET_NOLF(X)     void X() { test_nolf<SetTypes<key_type, value_type>::X >(); }
-#   define TEST_SET_NOLF_EXTRACT(X) void X() { test_nolf_extract<SetTypes<key_type, value_type>::X >(); }
+    size_t Set_InsDel_string::c_nMapSize = 1000000;
+    size_t Set_InsDel_string::c_nInsertThreadCount = 4;
+    size_t Set_InsDel_string::c_nDeleteThreadCount = 4;
+    size_t Set_InsDel_string::c_nThreadPassCount = 4;
+    size_t Set_InsDel_string::c_nMaxLoadFactor = 8;
+    bool   Set_InsDel_string::c_bPrintGCState = true;
 
-    namespace {
-        static size_t  c_nMapSize = 1000000    ;  // set size
-        static size_t  c_nInsertThreadCount = 4;  // count of insertion thread
-        static size_t  c_nDeleteThreadCount = 4;  // count of deletion thread
-        static size_t  c_nThreadPassCount = 4  ;  // pass count for each thread
-        static size_t  c_nMaxLoadFactor = 8    ;  // maximum load factor
-        static bool    c_bPrintGCState = true;
+    void Set_InsDel_string::setUpParams( const CppUnitMini::TestCfg& cfg )
+    {
+        c_nInsertThreadCount = cfg.getSizeT("InsertThreadCount", c_nInsertThreadCount );
+        c_nDeleteThreadCount = cfg.getSizeT("DeleteThreadCount", c_nDeleteThreadCount );
+        c_nThreadPassCount = cfg.getSizeT("ThreadPassCount", c_nThreadPassCount );
+        c_nMapSize = cfg.getSizeT("MapSize", c_nMapSize );
+        c_nMaxLoadFactor = cfg.getSizeT("MaxLoadFactor", c_nMaxLoadFactor );
+        c_bPrintGCState = cfg.getBool("PrintGCStateFlag", true );
     }
 
-    class Set_InsDel_string: public CppUnitMini::TestCase
+    void Set_InsDel_string::myRun(const char *in_name, bool invert /*= false*/)
     {
-        typedef std::string key_type;
-        typedef size_t      value_type;
-
-        const std::vector<std::string> *  m_parrString;
-
-        template <class Set>
-        class Inserter: public CppUnitMini::TestThread
-        {
-            Set&     m_Set;
-            typedef typename Set::value_type    keyval_type;
-
-            virtual Inserter *    clone()
-            {
-                return new Inserter( *this );
-            }
-        public:
-            size_t  m_nInsertSuccess;
-            size_t  m_nInsertFailed;
-
-        public:
-            Inserter( CppUnitMini::ThreadPool& pool, Set& rSet )
-                : CppUnitMini::TestThread( pool )
-                , m_Set( rSet )
-            {}
-            Inserter( Inserter& src )
-                : CppUnitMini::TestThread( src )
-                , m_Set( src.m_Set )
-            {}
-
-            Set_InsDel_string&  getTest()
-            {
-                return reinterpret_cast<Set_InsDel_string&>( m_Pool.m_Test );
-            }
-
-            virtual void init() { cds::threading::Manager::attachThread()   ; }
-            virtual void fini() { cds::threading::Manager::detachThread()   ; }
-
-            virtual void test()
-            {
-                Set& rSet = m_Set;
-
-                m_nInsertSuccess =
-                    m_nInsertFailed = 0;
-
-                const std::vector<std::string>& arrString = *getTest().m_parrString;
-                size_t nArrSize = arrString.size();
-
-                if ( m_nThreadNo & 1 ) {
-                    for ( size_t nPass = 0; nPass < c_nThreadPassCount; ++nPass ) {
-                        for ( size_t nItem = 0; nItem < c_nMapSize; ++nItem ) {
-                            if ( rSet.insert( keyval_type(arrString[nItem % nArrSize], nItem * 8) ) )
-                                ++m_nInsertSuccess;
-                            else
-                                ++m_nInsertFailed;
-                        }
-                    }
-                }
-                else {
-                    for ( size_t nPass = 0; nPass < c_nThreadPassCount; ++nPass ) {
-                        for ( size_t nItem = c_nMapSize; nItem > 0; --nItem ) {
-                            if ( rSet.insert( keyval_type( arrString[nItem % nArrSize], nItem * 8) ) )
-                                ++m_nInsertSuccess;
-                            else
-                                ++m_nInsertFailed;
-                        }
-                    }
-                }
-            }
-        };
-
-        template <class Set>
-        class Deleter: public CppUnitMini::TestThread
-        {
-            Set&     m_Set;
-
-            virtual Deleter *    clone()
-            {
-                return new Deleter( *this );
-            }
-        public:
-            size_t  m_nDeleteSuccess;
-            size_t  m_nDeleteFailed;
-
-        public:
-            Deleter( CppUnitMini::ThreadPool& pool, Set& rSet )
-                : CppUnitMini::TestThread( pool )
-                , m_Set( rSet )
-            {}
-            Deleter( Deleter& src )
-                : CppUnitMini::TestThread( src )
-                , m_Set( src.m_Set )
-            {}
-
-            Set_InsDel_string&  getTest()
-            {
-                return reinterpret_cast<Set_InsDel_string&>( m_Pool.m_Test );
-            }
-
-            virtual void init() { cds::threading::Manager::attachThread()   ; }
-            virtual void fini() { cds::threading::Manager::detachThread()   ; }
-
-            virtual void test()
-            {
-                Set& rSet = m_Set;
-
-                m_nDeleteSuccess =
-                    m_nDeleteFailed = 0;
-
-                const std::vector<std::string>& arrString = *getTest().m_parrString;
-                size_t nArrSize = arrString.size();
-
-                if ( m_nThreadNo & 1 ) {
-                    for ( size_t nPass = 0; nPass < c_nThreadPassCount; ++nPass ) {
-                        for ( size_t nItem = 0; nItem < c_nMapSize; ++nItem ) {
-                            if ( rSet.erase( arrString[nItem % nArrSize] ) )
-                                ++m_nDeleteSuccess;
-                            else
-                                ++m_nDeleteFailed;
-                        }
-                    }
-                }
-                else {
-                    for ( size_t nPass = 0; nPass < c_nThreadPassCount; ++nPass ) {
-                        for ( size_t nItem = c_nMapSize; nItem > 0; --nItem ) {
-                            if ( rSet.erase( arrString[nItem % nArrSize] ) )
-                                ++m_nDeleteSuccess;
-                            else
-                                ++m_nDeleteFailed;
-                        }
-                    }
-                }
-            }
-        };
-
-        template <typename GC, class Set>
-        class Extractor: public CppUnitMini::TestThread
-        {
-            Set&     m_Set;
-
-            virtual Extractor *    clone()
-            {
-                return new Extractor( *this );
-            }
-        public:
-            size_t  m_nDeleteSuccess;
-            size_t  m_nDeleteFailed;
-
-        public:
-            Extractor( CppUnitMini::ThreadPool& pool, Set& rSet )
-                : CppUnitMini::TestThread( pool )
-                , m_Set( rSet )
-            {}
-            Extractor( Extractor& src )
-                : CppUnitMini::TestThread( src )
-                , m_Set( src.m_Set )
-            {}
-
-            Set_InsDel_string&  getTest()
-            {
-                return reinterpret_cast<Set_InsDel_string&>( m_Pool.m_Test );
-            }
-
-            virtual void init() { cds::threading::Manager::attachThread()   ; }
-            virtual void fini() { cds::threading::Manager::detachThread()   ; }
-
-            virtual void test()
-            {
-                Set& rSet = m_Set;
-
-                m_nDeleteSuccess =
-                    m_nDeleteFailed = 0;
-
-                typename Set::guarded_ptr gp;
-
-                const std::vector<std::string>& arrString = *getTest().m_parrString;
-                size_t nArrSize = arrString.size();
-
-                if ( m_nThreadNo & 1 ) {
-                    for ( size_t nPass = 0; nPass < c_nThreadPassCount; ++nPass ) {
-                        for ( size_t nItem = 0; nItem < c_nMapSize; ++nItem ) {
-                            gp = rSet.extract( arrString[nItem % nArrSize]);
-                            if (  gp )
-                                ++m_nDeleteSuccess;
-                            else
-                                ++m_nDeleteFailed;
-                            gp.release();
-                        }
-                    }
-                }
-                else {
-                    for ( size_t nPass = 0; nPass < c_nThreadPassCount; ++nPass ) {
-                        for ( size_t nItem = c_nMapSize; nItem > 0; --nItem ) {
-                            gp = rSet.extract( arrString[nItem % nArrSize]);
-                            if ( gp )
-                                ++m_nDeleteSuccess;
-                            else
-                                ++m_nDeleteFailed;
-                            gp.release();
-                        }
-                    }
-                }
-            }
-        };
-
-        template <typename RCU, class Set>
-        class Extractor<cds::urcu::gc<RCU>, Set >: public CppUnitMini::TestThread
-        {
-            Set&     m_Set;
-
-            virtual Extractor *    clone()
-            {
-                return new Extractor( *this );
-            }
-        public:
-            size_t  m_nDeleteSuccess;
-            size_t  m_nDeleteFailed;
-
-        public:
-            Extractor( CppUnitMini::ThreadPool& pool, Set& rSet )
-                : CppUnitMini::TestThread( pool )
-                , m_Set( rSet )
-            {}
-            Extractor( Extractor& src )
-                : CppUnitMini::TestThread( src )
-                , m_Set( src.m_Set )
-            {}
-
-            Set_InsDel_string&  getTest()
-            {
-                return reinterpret_cast<Set_InsDel_string&>( m_Pool.m_Test );
-            }
-
-            virtual void init() { cds::threading::Manager::attachThread()   ; }
-            virtual void fini() { cds::threading::Manager::detachThread()   ; }
-
-            virtual void test()
-            {
-                Set& rSet = m_Set;
-
-                m_nDeleteSuccess =
-                    m_nDeleteFailed = 0;
-
-                typename Set::exempt_ptr xp;
-
-                const std::vector<std::string>& arrString = *getTest().m_parrString;
-                size_t nArrSize = arrString.size();
-
-                if ( m_nThreadNo & 1 ) {
-                    for ( size_t nPass = 0; nPass < c_nThreadPassCount; ++nPass ) {
-                        for ( size_t nItem = 0; nItem < c_nMapSize; ++nItem ) {
-                            if ( Set::c_bExtractLockExternal ) {
-                                {
-                                    typename Set::rcu_lock l;
-                                    xp = rSet.extract( arrString[nItem % nArrSize] );
-                                    if ( xp )
-                                        ++m_nDeleteSuccess;
-                                    else
-                                        ++m_nDeleteFailed;
-                                }
-                            }
-                            else {
-                                xp = rSet.extract( arrString[nItem % nArrSize] );
-                                if ( xp )
-                                    ++m_nDeleteSuccess;
-                                else
-                                    ++m_nDeleteFailed;
-                            }
-                            xp.release();
-                        }
-                    }
-                }
-                else {
-                    for ( size_t nPass = 0; nPass < c_nThreadPassCount; ++nPass ) {
-                        for ( size_t nItem = c_nMapSize; nItem > 0; --nItem ) {
-                            if ( Set::c_bExtractLockExternal ) {
-                                {
-                                    typename Set::rcu_lock l;
-                                    xp = rSet.extract( arrString[nItem % nArrSize] );
-                                    if ( xp )
-                                        ++m_nDeleteSuccess;
-                                    else
-                                        ++m_nDeleteFailed;
-                                }
-                            }
-                            else {
-                                xp = rSet.extract( arrString[nItem % nArrSize] );
-                                if ( xp )
-                                    ++m_nDeleteSuccess;
-                                else
-                                    ++m_nDeleteFailed;
-                            }
-                            xp.release();
-                        }
-                    }
-                }
-            }
-        };
-
-    protected:
-
-        template <class Set>
-        void do_test( size_t nLoadFactor )
-        {
-            CPPUNIT_MSG( "Load factor=" << nLoadFactor );
-
-            Set  testSet( c_nMapSize, nLoadFactor );
-            do_test_with( testSet );
-        }
-
-        template <class Set>
-        void do_test_extract( size_t nLoadFactor )
-        {
-            CPPUNIT_MSG( "Load factor=" << nLoadFactor );
-
-            Set  testSet( c_nMapSize, nLoadFactor );
-            do_test_extract_with( testSet );
-        }
-
-        template <class Set>
-        void do_test_with( Set& testSet )
-        {
-            typedef Inserter<Set>       InserterThread;
-            typedef Deleter<Set>        DeleterThread;
-            cds::OS::Timer    timer;
-
-            CppUnitMini::ThreadPool pool( *this );
-            pool.add( new InserterThread( pool, testSet ), c_nInsertThreadCount );
-            pool.add( new DeleterThread( pool, testSet ), c_nDeleteThreadCount );
-            pool.run();
-            CPPUNIT_MSG( "   Duration=" << pool.avgDuration() );
-
-            size_t nInsertSuccess = 0;
-            size_t nInsertFailed = 0;
-            size_t nDeleteSuccess = 0;
-            size_t nDeleteFailed = 0;
-            for ( CppUnitMini::ThreadPool::iterator it = pool.begin(); it != pool.end(); ++it ) {
-                InserterThread * pThread = dynamic_cast<InserterThread *>( *it );
-                if ( pThread ) {
-                    nInsertSuccess += pThread->m_nInsertSuccess;
-                    nInsertFailed += pThread->m_nInsertFailed;
-                }
-                else {
-                    DeleterThread * p = static_cast<DeleterThread *>( *it );
-                    nDeleteSuccess += p->m_nDeleteSuccess;
-                    nDeleteFailed += p->m_nDeleteFailed;
-                }
-            }
-
-            CPPUNIT_MSG( "    Totals: Ins succ=" << nInsertSuccess
-                << " Del succ=" << nDeleteSuccess << "\n"
-                      << "          : Ins fail=" << nInsertFailed
-                << " Del fail=" << nDeleteFailed
-                << " Set size=" << testSet.size()
-                );
-
-
-            CPPUNIT_MSG( "  Clear set (single-threaded)..." );
-            timer.reset();
-            for ( size_t i = 0; i < m_parrString->size(); ++i )
-                testSet.erase( (*m_parrString)[i] );
-            CPPUNIT_MSG( "   Duration=" << timer.duration() );
-            CPPUNIT_ASSERT( testSet.empty() );
-
-            additional_check( testSet );
-            print_stat(  testSet  );
-            additional_cleanup( testSet );
-        }
-
-        template <class Set>
-        void do_test_extract_with( Set& testSet )
-        {
-            typedef Inserter<Set>       InserterThread;
-            typedef Deleter<Set>        DeleterThread;
-            typedef Extractor<typename Set::gc, Set> ExtractThread;
-
-            size_t nDelThreadCount = c_nDeleteThreadCount / 2;
-
-            CppUnitMini::ThreadPool pool( *this );
-            pool.add( new InserterThread( pool, testSet ), c_nInsertThreadCount );
-            pool.add( new DeleterThread( pool, testSet ), nDelThreadCount );
-            pool.add( new ExtractThread( pool, testSet ), c_nDeleteThreadCount - nDelThreadCount );
-            pool.run();
-            CPPUNIT_MSG( "   Duration=" << pool.avgDuration() );
-
-            size_t nInsertSuccess = 0;
-            size_t nInsertFailed = 0;
-            size_t nDeleteSuccess = 0;
-            size_t nDeleteFailed = 0;
-            size_t nExtractSuccess = 0;
-            size_t nExtractFailed = 0;
-            for ( CppUnitMini::ThreadPool::iterator it = pool.begin(); it != pool.end(); ++it ) {
-                InserterThread * pThread = dynamic_cast<InserterThread *>( *it );
-                if ( pThread ) {
-                    nInsertSuccess += pThread->m_nInsertSuccess;
-                    nInsertFailed += pThread->m_nInsertFailed;
-                }
-                else {
-                    DeleterThread * p = dynamic_cast<DeleterThread *>( *it );
-                    if ( p ) {
-                        nDeleteSuccess += p->m_nDeleteSuccess;
-                        nDeleteFailed += p->m_nDeleteFailed;
-                    }
-                    else {
-                        ExtractThread * pExtract = dynamic_cast<ExtractThread *>( *it );
-                        assert( pExtract );
-                        nExtractSuccess += pExtract->m_nDeleteSuccess;
-                        nExtractFailed += pExtract->m_nDeleteFailed;
-                    }
-                }
-            }
-
-            CPPUNIT_MSG( "    Totals: Ins succ=" << nInsertSuccess
-                << " Del succ=" << nDeleteSuccess
-                << " Extract succ= " << nExtractSuccess << "\n"
-                << "          : Ins fail=" << nInsertFailed
-                << " Del fail=" << nDeleteFailed
-                << " Extract fail=" << nExtractFailed
-                << " Set size=" << testSet.size()
-                );
-
-
-            CPPUNIT_MSG( "  Clear set (single-threaded)..." );
-            cds::OS::Timer    timer;
-            for ( size_t i = 0; i < m_parrString->size(); ++i )
-                testSet.erase( (*m_parrString)[i] );
-            CPPUNIT_MSG( "   Duration=" << timer.duration() );
-            CPPUNIT_ASSERT( testSet.empty() );
-
-            additional_check( testSet );
-            print_stat(  testSet  );
-            additional_cleanup( testSet );
-        }
-
-        template <class Set>
-        void test()
-        {
-            m_parrString = &CppUnitMini::TestCase::getTestStrings();
-
-            CPPUNIT_MSG( "Thread count: insert=" << c_nInsertThreadCount
-                << " delete=" << c_nDeleteThreadCount
-                << " pass count=" << c_nThreadPassCount
-                << " set size=" << c_nMapSize
-                );
-
-            for ( size_t nLoadFactor = 1; nLoadFactor <= c_nMaxLoadFactor; nLoadFactor *= 2 ) {
-                do_test<Set>( nLoadFactor );
-                if ( c_bPrintGCState )
-                    print_gc_state();
-            }
-        }
-
-        template <class Set>
-        void test_extract()
-        {
-            m_parrString = &CppUnitMini::TestCase::getTestStrings();
-
-            CPPUNIT_MSG( "Thread count: insert=" << c_nInsertThreadCount
-                << " delete=" << c_nDeleteThreadCount
-                << " pass count=" << c_nThreadPassCount
-                << " set size=" << c_nMapSize
-                );
-
-            for ( size_t nLoadFactor = 1; nLoadFactor <= c_nMaxLoadFactor; nLoadFactor *= 2 ) {
-                do_test_extract<Set>( nLoadFactor );
-                if ( c_bPrintGCState )
-                    print_gc_state();
-            }
-        }
-
-        template <class Set>
-        void test_nolf()
-        {
-            m_parrString = &CppUnitMini::TestCase::getTestStrings();
-
-            CPPUNIT_MSG( "Thread count: insert=" << c_nInsertThreadCount
-                << " delete=" << c_nDeleteThreadCount
-                << " pass count=" << c_nThreadPassCount
-                << " set size=" << c_nMapSize
-                );
-
-            Set s;
-            do_test_with( s );
-            if ( c_bPrintGCState )
-                print_gc_state();
-        }
-
-        template <class Set>
-        void test_nolf_extract()
-        {
-            m_parrString = &CppUnitMini::TestCase::getTestStrings();
-
-            CPPUNIT_MSG( "Thread count: insert=" << c_nInsertThreadCount
-                << " delete=" << c_nDeleteThreadCount
-                << " pass count=" << c_nThreadPassCount
-                << " set size=" << c_nMapSize
-                );
-
-            Set s;
-            do_test_extract_with( s );
-            if ( c_bPrintGCState )
-                print_gc_state();
-        }
-
-        void setUpParams( const CppUnitMini::TestCfg& cfg ) {
-            c_nInsertThreadCount = cfg.getULong("InsertThreadCount", 4 );
-            c_nDeleteThreadCount = cfg.getULong("DeleteThreadCount", 4 );
-            c_nThreadPassCount = cfg.getULong("ThreadPassCount", 4 );
-            c_nMapSize = cfg.getULong("MapSize", 1000000 );
-            c_nMaxLoadFactor = cfg.getULong("MaxLoadFactor", 8 );
-            c_bPrintGCState = cfg.getBool("PrintGCStateFlag", true );
-        }
-
-#   include "set2/set_defs.h"
-        CDSUNIT_DECLARE_MichaelSet
-        CDSUNIT_DECLARE_SplitList
-        CDSUNIT_DECLARE_StripedSet
-        CDSUNIT_DECLARE_RefinableSet
-        CDSUNIT_DECLARE_CuckooSet
-        CDSUNIT_DECLARE_SkipListSet
-        CDSUNIT_DECLARE_EllenBinTreeSet
-        CDSUNIT_DECLARE_StdSet
-
-        CPPUNIT_TEST_SUITE_( Set_InsDel_string, "Map_InsDel_string" )
-            CDSUNIT_TEST_MichaelSet
-            CDSUNIT_TEST_SplitList
-            CDSUNIT_TEST_SkipListSet
-            CDSUNIT_TEST_EllenBinTreeSet
-            CDSUNIT_TEST_StripedSet
-            CDSUNIT_TEST_RefinableSet
-            CDSUNIT_TEST_CuckooSet
-            CDSUNIT_TEST_StdSet
-        CPPUNIT_TEST_SUITE_END()
-
-    };
-
-    CPPUNIT_TEST_SUITE_REGISTRATION( Set_InsDel_string );
+        setUpParams( m_Cfg.get( "Map_InsDel_string" ));
+
+        run_MichaelSet(in_name, invert);
+        run_SplitList(in_name, invert);
+        run_SkipListSet(in_name, invert);
+        run_EllenBinTreeSet(in_name, invert);
+        run_StripedSet(in_name, invert);
+        run_RefinableSet(in_name, invert);
+        run_CuckooSet(in_name, invert);
+        run_StdSet(in_name, invert);
+
+        endTestCase();
+    }
 } // namespace set2
diff --git a/tests/unit/set2/set_insdel_string.h b/tests/unit/set2/set_insdel_string.h
new file mode 100644 (file)
index 0000000..359368f
--- /dev/null
@@ -0,0 +1,551 @@
+//$$CDS-header$$
+
+#include "set2/set_types.h"
+#include "cppunit/thread.h"
+
+#include <vector>
+
+namespace set2 {
+
+#   define TEST_SET(X)          void X() { test<SetTypes<key_type, value_type>::X >(); }
+#   define TEST_SET_EXTRACT(X)  void X() { test_extract<SetTypes<key_type, value_type>::X >(); }
+#   define TEST_SET_NOLF(X)     void X() { test_nolf<SetTypes<key_type, value_type>::X >(); }
+#   define TEST_SET_NOLF_EXTRACT(X) void X() { test_nolf_extract<SetTypes<key_type, value_type>::X >(); }
+
+    class Set_InsDel_string: public CppUnitMini::TestCase
+    {
+        static size_t  c_nMapSize;            // set size
+        static size_t  c_nInsertThreadCount;  // count of insertion thread
+        static size_t  c_nDeleteThreadCount;  // count of deletion thread
+        static size_t  c_nThreadPassCount;    // pass count for each thread
+        static size_t  c_nMaxLoadFactor;      // maximum load factor
+        static bool    c_bPrintGCState;
+
+        typedef CppUnitMini::TestCase Base;
+        typedef std::string key_type;
+        typedef size_t      value_type;
+
+        const std::vector<std::string> *  m_parrString;
+
+        template <class Set>
+        class Inserter: public CppUnitMini::TestThread
+        {
+            Set&     m_Set;
+            typedef typename Set::value_type    keyval_type;
+
+            virtual Inserter *    clone()
+            {
+                return new Inserter( *this );
+            }
+        public:
+            size_t  m_nInsertSuccess;
+            size_t  m_nInsertFailed;
+
+        public:
+            Inserter( CppUnitMini::ThreadPool& pool, Set& rSet )
+                : CppUnitMini::TestThread( pool )
+                , m_Set( rSet )
+            {}
+            Inserter( Inserter& src )
+                : CppUnitMini::TestThread( src )
+                , m_Set( src.m_Set )
+            {}
+
+            Set_InsDel_string&  getTest()
+            {
+                return reinterpret_cast<Set_InsDel_string&>( m_Pool.m_Test );
+            }
+
+            virtual void init() { cds::threading::Manager::attachThread()   ; }
+            virtual void fini() { cds::threading::Manager::detachThread()   ; }
+
+            virtual void test()
+            {
+                Set& rSet = m_Set;
+
+                m_nInsertSuccess =
+                    m_nInsertFailed = 0;
+
+                const std::vector<std::string>& arrString = *getTest().m_parrString;
+                size_t nArrSize = arrString.size();
+
+                if ( m_nThreadNo & 1 ) {
+                    for ( size_t nPass = 0; nPass < c_nThreadPassCount; ++nPass ) {
+                        for ( size_t nItem = 0; nItem < c_nMapSize; ++nItem ) {
+                            if ( rSet.insert( keyval_type(arrString[nItem % nArrSize], nItem * 8) ) )
+                                ++m_nInsertSuccess;
+                            else
+                                ++m_nInsertFailed;
+                        }
+                    }
+                }
+                else {
+                    for ( size_t nPass = 0; nPass < c_nThreadPassCount; ++nPass ) {
+                        for ( size_t nItem = c_nMapSize; nItem > 0; --nItem ) {
+                            if ( rSet.insert( keyval_type( arrString[nItem % nArrSize], nItem * 8) ) )
+                                ++m_nInsertSuccess;
+                            else
+                                ++m_nInsertFailed;
+                        }
+                    }
+                }
+            }
+        };
+
+        template <class Set>
+        class Deleter: public CppUnitMini::TestThread
+        {
+            Set&     m_Set;
+
+            virtual Deleter *    clone()
+            {
+                return new Deleter( *this );
+            }
+        public:
+            size_t  m_nDeleteSuccess;
+            size_t  m_nDeleteFailed;
+
+        public:
+            Deleter( CppUnitMini::ThreadPool& pool, Set& rSet )
+                : CppUnitMini::TestThread( pool )
+                , m_Set( rSet )
+            {}
+            Deleter( Deleter& src )
+                : CppUnitMini::TestThread( src )
+                , m_Set( src.m_Set )
+            {}
+
+            Set_InsDel_string&  getTest()
+            {
+                return reinterpret_cast<Set_InsDel_string&>( m_Pool.m_Test );
+            }
+
+            virtual void init() { cds::threading::Manager::attachThread()   ; }
+            virtual void fini() { cds::threading::Manager::detachThread()   ; }
+
+            virtual void test()
+            {
+                Set& rSet = m_Set;
+
+                m_nDeleteSuccess =
+                    m_nDeleteFailed = 0;
+
+                const std::vector<std::string>& arrString = *getTest().m_parrString;
+                size_t nArrSize = arrString.size();
+
+                if ( m_nThreadNo & 1 ) {
+                    for ( size_t nPass = 0; nPass < c_nThreadPassCount; ++nPass ) {
+                        for ( size_t nItem = 0; nItem < c_nMapSize; ++nItem ) {
+                            if ( rSet.erase( arrString[nItem % nArrSize] ) )
+                                ++m_nDeleteSuccess;
+                            else
+                                ++m_nDeleteFailed;
+                        }
+                    }
+                }
+                else {
+                    for ( size_t nPass = 0; nPass < c_nThreadPassCount; ++nPass ) {
+                        for ( size_t nItem = c_nMapSize; nItem > 0; --nItem ) {
+                            if ( rSet.erase( arrString[nItem % nArrSize] ) )
+                                ++m_nDeleteSuccess;
+                            else
+                                ++m_nDeleteFailed;
+                        }
+                    }
+                }
+            }
+        };
+
+        template <typename GC, class Set>
+        class Extractor: public CppUnitMini::TestThread
+        {
+            Set&     m_Set;
+
+            virtual Extractor *    clone()
+            {
+                return new Extractor( *this );
+            }
+        public:
+            size_t  m_nDeleteSuccess;
+            size_t  m_nDeleteFailed;
+
+        public:
+            Extractor( CppUnitMini::ThreadPool& pool, Set& rSet )
+                : CppUnitMini::TestThread( pool )
+                , m_Set( rSet )
+            {}
+            Extractor( Extractor& src )
+                : CppUnitMini::TestThread( src )
+                , m_Set( src.m_Set )
+            {}
+
+            Set_InsDel_string&  getTest()
+            {
+                return reinterpret_cast<Set_InsDel_string&>( m_Pool.m_Test );
+            }
+
+            virtual void init() { cds::threading::Manager::attachThread()   ; }
+            virtual void fini() { cds::threading::Manager::detachThread()   ; }
+
+            virtual void test()
+            {
+                Set& rSet = m_Set;
+
+                m_nDeleteSuccess =
+                    m_nDeleteFailed = 0;
+
+                typename Set::guarded_ptr gp;
+
+                const std::vector<std::string>& arrString = *getTest().m_parrString;
+                size_t nArrSize = arrString.size();
+
+                if ( m_nThreadNo & 1 ) {
+                    for ( size_t nPass = 0; nPass < c_nThreadPassCount; ++nPass ) {
+                        for ( size_t nItem = 0; nItem < c_nMapSize; ++nItem ) {
+                            gp = rSet.extract( arrString[nItem % nArrSize]);
+                            if (  gp )
+                                ++m_nDeleteSuccess;
+                            else
+                                ++m_nDeleteFailed;
+                            gp.release();
+                        }
+                    }
+                }
+                else {
+                    for ( size_t nPass = 0; nPass < c_nThreadPassCount; ++nPass ) {
+                        for ( size_t nItem = c_nMapSize; nItem > 0; --nItem ) {
+                            gp = rSet.extract( arrString[nItem % nArrSize]);
+                            if ( gp )
+                                ++m_nDeleteSuccess;
+                            else
+                                ++m_nDeleteFailed;
+                            gp.release();
+                        }
+                    }
+                }
+            }
+        };
+
+        template <typename RCU, class Set>
+        class Extractor<cds::urcu::gc<RCU>, Set >: public CppUnitMini::TestThread
+        {
+            Set&     m_Set;
+
+            virtual Extractor *    clone()
+            {
+                return new Extractor( *this );
+            }
+        public:
+            size_t  m_nDeleteSuccess;
+            size_t  m_nDeleteFailed;
+
+        public:
+            Extractor( CppUnitMini::ThreadPool& pool, Set& rSet )
+                : CppUnitMini::TestThread( pool )
+                , m_Set( rSet )
+            {}
+            Extractor( Extractor& src )
+                : CppUnitMini::TestThread( src )
+                , m_Set( src.m_Set )
+            {}
+
+            Set_InsDel_string&  getTest()
+            {
+                return reinterpret_cast<Set_InsDel_string&>( m_Pool.m_Test );
+            }
+
+            virtual void init() { cds::threading::Manager::attachThread()   ; }
+            virtual void fini() { cds::threading::Manager::detachThread()   ; }
+
+            virtual void test()
+            {
+                Set& rSet = m_Set;
+
+                m_nDeleteSuccess =
+                    m_nDeleteFailed = 0;
+
+                typename Set::exempt_ptr xp;
+
+                const std::vector<std::string>& arrString = *getTest().m_parrString;
+                size_t nArrSize = arrString.size();
+
+                if ( m_nThreadNo & 1 ) {
+                    for ( size_t nPass = 0; nPass < c_nThreadPassCount; ++nPass ) {
+                        for ( size_t nItem = 0; nItem < c_nMapSize; ++nItem ) {
+                            if ( Set::c_bExtractLockExternal ) {
+                                {
+                                    typename Set::rcu_lock l;
+                                    xp = rSet.extract( arrString[nItem % nArrSize] );
+                                    if ( xp )
+                                        ++m_nDeleteSuccess;
+                                    else
+                                        ++m_nDeleteFailed;
+                                }
+                            }
+                            else {
+                                xp = rSet.extract( arrString[nItem % nArrSize] );
+                                if ( xp )
+                                    ++m_nDeleteSuccess;
+                                else
+                                    ++m_nDeleteFailed;
+                            }
+                            xp.release();
+                        }
+                    }
+                }
+                else {
+                    for ( size_t nPass = 0; nPass < c_nThreadPassCount; ++nPass ) {
+                        for ( size_t nItem = c_nMapSize; nItem > 0; --nItem ) {
+                            if ( Set::c_bExtractLockExternal ) {
+                                {
+                                    typename Set::rcu_lock l;
+                                    xp = rSet.extract( arrString[nItem % nArrSize] );
+                                    if ( xp )
+                                        ++m_nDeleteSuccess;
+                                    else
+                                        ++m_nDeleteFailed;
+                                }
+                            }
+                            else {
+                                xp = rSet.extract( arrString[nItem % nArrSize] );
+                                if ( xp )
+                                    ++m_nDeleteSuccess;
+                                else
+                                    ++m_nDeleteFailed;
+                            }
+                            xp.release();
+                        }
+                    }
+                }
+            }
+        };
+
+    protected:
+
+        template <class Set>
+        void do_test( size_t nLoadFactor )
+        {
+            CPPUNIT_MSG( "Load factor=" << nLoadFactor );
+
+            Set  testSet( c_nMapSize, nLoadFactor );
+            do_test_with( testSet );
+        }
+
+        template <class Set>
+        void do_test_extract( size_t nLoadFactor )
+        {
+            CPPUNIT_MSG( "Load factor=" << nLoadFactor );
+
+            Set  testSet( c_nMapSize, nLoadFactor );
+            do_test_extract_with( testSet );
+        }
+
+        template <class Set>
+        void do_test_with( Set& testSet )
+        {
+            typedef Inserter<Set>       InserterThread;
+            typedef Deleter<Set>        DeleterThread;
+            cds::OS::Timer    timer;
+
+            CppUnitMini::ThreadPool pool( *this );
+            pool.add( new InserterThread( pool, testSet ), c_nInsertThreadCount );
+            pool.add( new DeleterThread( pool, testSet ), c_nDeleteThreadCount );
+            pool.run();
+            CPPUNIT_MSG( "   Duration=" << pool.avgDuration() );
+
+            size_t nInsertSuccess = 0;
+            size_t nInsertFailed = 0;
+            size_t nDeleteSuccess = 0;
+            size_t nDeleteFailed = 0;
+            for ( CppUnitMini::ThreadPool::iterator it = pool.begin(); it != pool.end(); ++it ) {
+                InserterThread * pThread = dynamic_cast<InserterThread *>( *it );
+                if ( pThread ) {
+                    nInsertSuccess += pThread->m_nInsertSuccess;
+                    nInsertFailed += pThread->m_nInsertFailed;
+                }
+                else {
+                    DeleterThread * p = static_cast<DeleterThread *>( *it );
+                    nDeleteSuccess += p->m_nDeleteSuccess;
+                    nDeleteFailed += p->m_nDeleteFailed;
+                }
+            }
+
+            CPPUNIT_MSG( "    Totals: Ins succ=" << nInsertSuccess
+                << " Del succ=" << nDeleteSuccess << "\n"
+                      << "          : Ins fail=" << nInsertFailed
+                << " Del fail=" << nDeleteFailed
+                << " Set size=" << testSet.size()
+                );
+
+
+            CPPUNIT_MSG( "  Clear set (single-threaded)..." );
+            timer.reset();
+            for ( size_t i = 0; i < m_parrString->size(); ++i )
+                testSet.erase( (*m_parrString)[i] );
+            CPPUNIT_MSG( "   Duration=" << timer.duration() );
+            CPPUNIT_ASSERT( testSet.empty() );
+
+            additional_check( testSet );
+            print_stat(  testSet  );
+            additional_cleanup( testSet );
+        }
+
+        template <class Set>
+        void do_test_extract_with( Set& testSet )
+        {
+            typedef Inserter<Set>       InserterThread;
+            typedef Deleter<Set>        DeleterThread;
+            typedef Extractor<typename Set::gc, Set> ExtractThread;
+
+            size_t nDelThreadCount = c_nDeleteThreadCount / 2;
+
+            CppUnitMini::ThreadPool pool( *this );
+            pool.add( new InserterThread( pool, testSet ), c_nInsertThreadCount );
+            pool.add( new DeleterThread( pool, testSet ), nDelThreadCount );
+            pool.add( new ExtractThread( pool, testSet ), c_nDeleteThreadCount - nDelThreadCount );
+            pool.run();
+            CPPUNIT_MSG( "   Duration=" << pool.avgDuration() );
+
+            size_t nInsertSuccess = 0;
+            size_t nInsertFailed = 0;
+            size_t nDeleteSuccess = 0;
+            size_t nDeleteFailed = 0;
+            size_t nExtractSuccess = 0;
+            size_t nExtractFailed = 0;
+            for ( CppUnitMini::ThreadPool::iterator it = pool.begin(); it != pool.end(); ++it ) {
+                InserterThread * pThread = dynamic_cast<InserterThread *>( *it );
+                if ( pThread ) {
+                    nInsertSuccess += pThread->m_nInsertSuccess;
+                    nInsertFailed += pThread->m_nInsertFailed;
+                }
+                else {
+                    DeleterThread * p = dynamic_cast<DeleterThread *>( *it );
+                    if ( p ) {
+                        nDeleteSuccess += p->m_nDeleteSuccess;
+                        nDeleteFailed += p->m_nDeleteFailed;
+                    }
+                    else {
+                        ExtractThread * pExtract = dynamic_cast<ExtractThread *>( *it );
+                        assert( pExtract );
+                        nExtractSuccess += pExtract->m_nDeleteSuccess;
+                        nExtractFailed += pExtract->m_nDeleteFailed;
+                    }
+                }
+            }
+
+            CPPUNIT_MSG( "    Totals: Ins succ=" << nInsertSuccess
+                << " Del succ=" << nDeleteSuccess
+                << " Extract succ= " << nExtractSuccess << "\n"
+                << "          : Ins fail=" << nInsertFailed
+                << " Del fail=" << nDeleteFailed
+                << " Extract fail=" << nExtractFailed
+                << " Set size=" << testSet.size()
+                );
+
+
+            CPPUNIT_MSG( "  Clear set (single-threaded)..." );
+            cds::OS::Timer    timer;
+            for ( size_t i = 0; i < m_parrString->size(); ++i )
+                testSet.erase( (*m_parrString)[i] );
+            CPPUNIT_MSG( "   Duration=" << timer.duration() );
+            CPPUNIT_ASSERT( testSet.empty() );
+
+            additional_check( testSet );
+            print_stat(  testSet  );
+            additional_cleanup( testSet );
+        }
+
+        template <class Set>
+        void test()
+        {
+            m_parrString = &CppUnitMini::TestCase::getTestStrings();
+
+            CPPUNIT_MSG( "Thread count: insert=" << c_nInsertThreadCount
+                << " delete=" << c_nDeleteThreadCount
+                << " pass count=" << c_nThreadPassCount
+                << " set size=" << c_nMapSize
+                );
+
+            for ( size_t nLoadFactor = 1; nLoadFactor <= c_nMaxLoadFactor; nLoadFactor *= 2 ) {
+                do_test<Set>( nLoadFactor );
+                if ( c_bPrintGCState )
+                    print_gc_state();
+            }
+        }
+
+        template <class Set>
+        void test_extract()
+        {
+            m_parrString = &CppUnitMini::TestCase::getTestStrings();
+
+            CPPUNIT_MSG( "Thread count: insert=" << c_nInsertThreadCount
+                << " delete=" << c_nDeleteThreadCount
+                << " pass count=" << c_nThreadPassCount
+                << " set size=" << c_nMapSize
+                );
+
+            for ( size_t nLoadFactor = 1; nLoadFactor <= c_nMaxLoadFactor; nLoadFactor *= 2 ) {
+                do_test_extract<Set>( nLoadFactor );
+                if ( c_bPrintGCState )
+                    print_gc_state();
+            }
+        }
+
+        template <class Set>
+        void test_nolf()
+        {
+            m_parrString = &CppUnitMini::TestCase::getTestStrings();
+
+            CPPUNIT_MSG( "Thread count: insert=" << c_nInsertThreadCount
+                << " delete=" << c_nDeleteThreadCount
+                << " pass count=" << c_nThreadPassCount
+                << " set size=" << c_nMapSize
+                );
+
+            Set s;
+            do_test_with( s );
+            if ( c_bPrintGCState )
+                print_gc_state();
+        }
+
+        template <class Set>
+        void test_nolf_extract()
+        {
+            m_parrString = &CppUnitMini::TestCase::getTestStrings();
+
+            CPPUNIT_MSG( "Thread count: insert=" << c_nInsertThreadCount
+                << " delete=" << c_nDeleteThreadCount
+                << " pass count=" << c_nThreadPassCount
+                << " set size=" << c_nMapSize
+                );
+
+            Set s;
+            do_test_extract_with( s );
+            if ( c_bPrintGCState )
+                print_gc_state();
+        }
+
+        void setUpParams( const CppUnitMini::TestCfg& cfg );
+
+        void run_MichaelSet(const char *in_name, bool invert = false);
+        void run_SplitList(const char *in_name, bool invert = false);
+        void run_SkipListSet(const char *in_name, bool invert = false);
+        void run_CuckooSet(const char *in_name, bool invert = false);
+        void run_StripedSet(const char *in_name, bool invert = false);
+        void run_RefinableSet(const char *in_name, bool invert = false);
+        void run_EllenBinTreeSet(const char *in_name, bool invert = false);
+        void run_StdSet(const char *in_name, bool invert = false);
+
+        virtual void myRun(const char *in_name, bool invert = false);
+
+#   include "set2/set_defs.h"
+        CDSUNIT_DECLARE_MichaelSet
+        CDSUNIT_DECLARE_SplitList
+        CDSUNIT_DECLARE_StripedSet
+        CDSUNIT_DECLARE_RefinableSet
+        CDSUNIT_DECLARE_CuckooSet
+        CDSUNIT_DECLARE_SkipListSet
+        CDSUNIT_DECLARE_EllenBinTreeSet
+        CDSUNIT_DECLARE_StdSet
+    };
+} // namespace set2
diff --git a/tests/unit/set2/set_insdel_string_cuckoo.cpp b/tests/unit/set2/set_insdel_string_cuckoo.cpp
new file mode 100644 (file)
index 0000000..0f5e506
--- /dev/null
@@ -0,0 +1,9 @@
+//$$CDS-header$$
+
+#include "set2/set_insdel_string.h"
+
+namespace set2 {
+    CPPUNIT_TEST_SUITE_PART( Set_InsDel_string, run_CuckooSet )
+        CDSUNIT_TEST_CuckooSet
+    CPPUNIT_TEST_SUITE_END_PART()
+} // namespace set2
diff --git a/tests/unit/set2/set_insdel_string_ellentree.cpp b/tests/unit/set2/set_insdel_string_ellentree.cpp
new file mode 100644 (file)
index 0000000..cb6bec8
--- /dev/null
@@ -0,0 +1,9 @@
+//$$CDS-header$$
+
+#include "set2/set_insdel_string.h"
+
+namespace set2 {
+    CPPUNIT_TEST_SUITE_PART( Set_InsDel_string, run_EllenBinTreeSet )
+        CDSUNIT_TEST_EllenBinTreeSet
+    CPPUNIT_TEST_SUITE_END_PART()
+} // namespace set2
diff --git a/tests/unit/set2/set_insdel_string_michael.cpp b/tests/unit/set2/set_insdel_string_michael.cpp
new file mode 100644 (file)
index 0000000..b7be88f
--- /dev/null
@@ -0,0 +1,9 @@
+//$$CDS-header$$
+
+#include "set2/set_insdel_string.h"
+
+namespace set2 {
+    CPPUNIT_TEST_SUITE_PART( Set_InsDel_string, run_MichaelSet )
+        CDSUNIT_TEST_MichaelSet
+    CPPUNIT_TEST_SUITE_END_PART()
+} // namespace set2
diff --git a/tests/unit/set2/set_insdel_string_refinable.cpp b/tests/unit/set2/set_insdel_string_refinable.cpp
new file mode 100644 (file)
index 0000000..fb14006
--- /dev/null
@@ -0,0 +1,9 @@
+//$$CDS-header$$
+
+#include "set2/set_insdel_string.h"
+
+namespace set2 {
+    CPPUNIT_TEST_SUITE_PART( Set_InsDel_string, run_RefinableSet )
+        CDSUNIT_TEST_RefinableSet
+    CPPUNIT_TEST_SUITE_END_PART()
+} // namespace set2
diff --git a/tests/unit/set2/set_insdel_string_skip.cpp b/tests/unit/set2/set_insdel_string_skip.cpp
new file mode 100644 (file)
index 0000000..4c98a6a
--- /dev/null
@@ -0,0 +1,9 @@
+//$$CDS-header$$
+
+#include "set2/set_insdel_string.h"
+
+namespace set2 {
+    CPPUNIT_TEST_SUITE_PART( Set_InsDel_string, run_SkipListSet )
+        CDSUNIT_TEST_SkipListSet
+    CPPUNIT_TEST_SUITE_END_PART()
+} // namespace set2
diff --git a/tests/unit/set2/set_insdel_string_split.cpp b/tests/unit/set2/set_insdel_string_split.cpp
new file mode 100644 (file)
index 0000000..821d0bd
--- /dev/null
@@ -0,0 +1,9 @@
+//$$CDS-header$$
+
+#include "set2/set_insdel_string.h"
+
+namespace set2 {
+    CPPUNIT_TEST_SUITE_PART( Set_InsDel_string, run_SplitList )
+        CDSUNIT_TEST_SplitList
+    CPPUNIT_TEST_SUITE_END_PART()
+} // namespace set2
diff --git a/tests/unit/set2/set_insdel_string_std.cpp b/tests/unit/set2/set_insdel_string_std.cpp
new file mode 100644 (file)
index 0000000..8a8f3cc
--- /dev/null
@@ -0,0 +1,9 @@
+//$$CDS-header$$
+
+#include "set2/set_insdel_string.h"
+
+namespace set2 {
+    CPPUNIT_TEST_SUITE_PART( Set_InsDel_string, run_StdSet )
+        CDSUNIT_TEST_StdSet
+    CPPUNIT_TEST_SUITE_END_PART()
+} // namespace set2
diff --git a/tests/unit/set2/set_insdel_string_striped.cpp b/tests/unit/set2/set_insdel_string_striped.cpp
new file mode 100644 (file)
index 0000000..c823c56
--- /dev/null
@@ -0,0 +1,9 @@
+//$$CDS-header$$
+
+#include "set2/set_insdel_string.h"
+
+namespace set2 {
+    CPPUNIT_TEST_SUITE_PART( Set_InsDel_string, run_StripedSet )
+        CDSUNIT_TEST_StripedSet
+    CPPUNIT_TEST_SUITE_END_PART()
+} // namespace set2
index 0d4d5f45c3785bf32550f21a0890df108b071d8c..82c61d74de53c5291ca283bbd9e7e867baa3a582 100644 (file)
 //$$CDS-header$$
 
-#include "set2/set_types.h"
-#include "cppunit/thread.h"
-#include <algorithm> // random_shuffle
+#include "set2/set_insdelfind.h"
 
 namespace set2 {
+    CPPUNIT_TEST_SUITE_REGISTRATION( Set_InsDelFind );
 
-#   define TEST_SET(X)          void X() { test<SetTypes<key_type, value_type>::X >()    ; }
-#   define TEST_SET_EXTRACT(X)  TEST_SET(X)
-#   define TEST_SET_NOLF(X)    void X() { test_nolf<SetTypes<key_type, value_type>::X >()    ; }
-#   define TEST_SET_NOLF_EXTRACT(X) TEST_SET_NOLF(X)
+    size_t Set_InsDelFind::c_nInitialMapSize = 500000;
+    size_t Set_InsDelFind::c_nThreadCount = 8;
+    size_t Set_InsDelFind::c_nMaxLoadFactor = 8;
+    unsigned int Set_InsDelFind::c_nInsertPercentage = 5;
+    unsigned int Set_InsDelFind::c_nDeletePercentage = 5;
+    unsigned int Set_InsDelFind::c_nDuration = 30;
+    bool Set_InsDelFind::c_bPrintGCState = true;
 
-    namespace {
-        static size_t  c_nInitialMapSize = 500000   ;  // initial map size
-        static size_t  c_nThreadCount = 8           ;  // thread count
-        static size_t  c_nMaxLoadFactor = 8         ;  // maximum load factor
-        static unsigned int c_nInsertPercentage = 5;
-        static unsigned int c_nDeletePercentage = 5;
-        static unsigned int c_nDuration = 30        ;  // test duration, seconds
-        static bool    c_bPrintGCState = true;
+    void Set_InsDelFind::setUpParams( const CppUnitMini::TestCfg& cfg )
+    {
+        c_nInitialMapSize = cfg.getSizeT("InitialMapSize", c_nInitialMapSize );
+        c_nThreadCount = cfg.getSizeT("ThreadCount", c_nThreadCount );
+        c_nMaxLoadFactor = cfg.getSizeT("MaxLoadFactor", c_nMaxLoadFactor );
+        c_nInsertPercentage = cfg.getUInt("InsertPercentage", c_nInsertPercentage );
+        c_nDeletePercentage = cfg.getUInt("DeletePercentage", c_nDeletePercentage );
+        c_nDuration = cfg.getUInt("Duration", c_nDuration );
+        c_bPrintGCState = cfg.getBool("PrintGCStateFlag", c_bPrintGCState );
+
+        if ( c_nThreadCount == 0 )
+            c_nThreadCount = cds::OS::topology::processor_count() * 2;
+
+        CPPUNIT_ASSERT( c_nInsertPercentage + c_nDeletePercentage <= 100 );
+
+        actions * pFirst = m_arrShuffle;
+        actions * pLast = m_arrShuffle + c_nInsertPercentage;
+        std::fill( pFirst, pLast, do_insert );
+        pFirst = pLast;
+        pLast += c_nDeletePercentage;
+        std::fill( pFirst, pLast, do_delete );
+        pFirst = pLast;
+        pLast = m_arrShuffle + sizeof(m_arrShuffle)/sizeof(m_arrShuffle[0]);
+        std::fill( pFirst, pLast, do_find );
+        std::random_shuffle( m_arrShuffle, pLast );
     }
 
-    class Set_InsDelFind: public CppUnitMini::TestCase
+    void Set_InsDelFind::myRun(const char *in_name, bool invert /*= false*/)
     {
-    public:
-        enum actions
-        {
-            do_find,
-            do_insert,
-            do_delete
-        };
-        static const unsigned int c_nShuffleSize = 100;
-        actions m_arrShuffle[c_nShuffleSize];
-
-    protected:
-        typedef size_t  key_type;
-        typedef size_t  value_type;
-
-        template <class Set>
-        class WorkThread: public CppUnitMini::TestThread
-        {
-            Set&     m_Map;
-
-            virtual WorkThread *    clone()
-            {
-                return new WorkThread( *this );
-            }
-        public:
-            size_t  m_nInsertSuccess;
-            size_t  m_nInsertFailed;
-            size_t  m_nDeleteSuccess;
-            size_t  m_nDeleteFailed;
-            size_t  m_nFindSuccess;
-            size_t  m_nFindFailed;
-
-        public:
-            WorkThread( CppUnitMini::ThreadPool& pool, Set& rMap )
-                : CppUnitMini::TestThread( pool )
-                , m_Map( rMap )
-            {}
-            WorkThread( WorkThread& src )
-                : CppUnitMini::TestThread( src )
-                , m_Map( src.m_Map )
-            {}
-
-            Set_InsDelFind&  getTest()
-            {
-                return reinterpret_cast<Set_InsDelFind&>( m_Pool.m_Test );
-            }
-
-            virtual void init() { cds::threading::Manager::attachThread()   ; }
-            virtual void fini() { cds::threading::Manager::detachThread()   ; }
-
-            virtual void test()
-            {
-                Set& rMap = m_Map;
-
-                m_nInsertSuccess =
-                    m_nInsertFailed =
-                    m_nDeleteSuccess =
-                    m_nDeleteFailed =
-                    m_nFindSuccess =
-                    m_nFindFailed = 0;
-
-                actions * pAct = getTest().m_arrShuffle;
-                unsigned int i = 0;
-                size_t const nNormalize = size_t(-1) / (c_nInitialMapSize * 2);
-
-                size_t nRand = 0;
-                while ( !time_elapsed() ) {
-                    nRand = cds::bitop::RandXorShift(nRand);
-                    size_t n = nRand / nNormalize;
-                    switch ( pAct[i] ) {
-                    case do_find:
-                        if ( rMap.find( n ))
-                            ++m_nFindSuccess;
-                        else
-                            ++m_nFindFailed;
-                        break;
-                    case do_insert:
-                        if ( rMap.insert( n ))
-                            ++m_nInsertSuccess;
-                        else
-                            ++m_nInsertFailed;
-                        break;
-                    case do_delete:
-                        if ( rMap.erase( n ))
-                            ++m_nDeleteSuccess;
-                        else
-                            ++m_nDeleteFailed;
-                        break;
-                    }
-
-                    if ( ++i >= c_nShuffleSize )
-                        i = 0;
-                }
-            }
-        };
-
-    protected:
-        template <class Set>
-        void do_test( size_t nLoadFactor )
-        {
-            CPPUNIT_MSG( "Load factor=" << nLoadFactor );
-
-            Set  testSet( c_nInitialMapSize, nLoadFactor );
-            do_test_with( testSet );
-        }
-
-        template <class Set>
-        void do_test_with( Set& testSet )
-        {
-            typedef WorkThread<Set> work_thread;
-
-            // fill map - only odd number
-            {
-                size_t * pInitArr = new size_t[ c_nInitialMapSize ];
-                size_t * pEnd = pInitArr + c_nInitialMapSize;
-                for ( size_t i = 0; i < c_nInitialMapSize; ++i )
-                    pInitArr[i] = i * 2 + 1;
-                std::random_shuffle( pInitArr, pEnd );
-                for ( size_t * p = pInitArr; p < pEnd; ++p )
-                    testSet.insert( typename Set::value_type( *p, *p ) );
-                delete [] pInitArr;
-            }
-
-            cds::OS::Timer    timer;
-
-            CppUnitMini::ThreadPool pool( *this );
-            pool.add( new work_thread( pool, testSet ), c_nThreadCount );
-            pool.run( c_nDuration );
-            CPPUNIT_MSG( "   Duration=" << pool.avgDuration() );
-
-            size_t nInsertSuccess = 0;
-            size_t nInsertFailed = 0;
-            size_t nDeleteSuccess = 0;
-            size_t nDeleteFailed = 0;
-            size_t nFindSuccess = 0;
-            size_t nFindFailed = 0;
-            for ( CppUnitMini::ThreadPool::iterator it = pool.begin(); it != pool.end(); ++it ) {
-                work_thread * pThread = static_cast<work_thread *>( *it );
-                assert( pThread != nullptr );
-                nInsertSuccess += pThread->m_nInsertSuccess;
-                nInsertFailed += pThread->m_nInsertFailed;
-                nDeleteSuccess += pThread->m_nDeleteSuccess;
-                nDeleteFailed += pThread->m_nDeleteFailed;
-                nFindSuccess += pThread->m_nFindSuccess;
-                nFindFailed += pThread->m_nFindFailed;
-            }
-
-            size_t nTotalOps = nInsertSuccess + nInsertFailed + nDeleteSuccess + nDeleteFailed + nFindSuccess + nFindFailed;
-
-            CPPUNIT_MSG( "  Totals (success/failed): \n\t"
-                      << "      Insert=" << nInsertSuccess << '/' << nInsertFailed << "\n\t"
-                      << "      Delete=" << nDeleteSuccess << '/' << nDeleteFailed << "\n\t"
-                      << "        Find=" << nFindSuccess   << '/' << nFindFailed   << "\n\t"
-                      << "       Speed=" << (nFindSuccess + nFindFailed) / c_nDuration << " find/sec\n\t"
-                      << "             " << (nInsertSuccess + nDeleteSuccess) / c_nDuration << " modify/sec\n\t"
-                      << "   Total ops=" << nTotalOps << "\n\t"
-                      << "       speed=" << nTotalOps / c_nDuration << " ops/sec\n\t"
-                      << "      Set size=" << testSet.size()
-                );
-
-
-            CPPUNIT_MSG( "  Clear map (single-threaded)..." );
-            timer.reset();
-            testSet.clear();
-            CPPUNIT_MSG( "   Duration=" << timer.duration() );
-            CPPUNIT_CHECK_EX( testSet.empty(), ((long long) testSet.size()) );
-
-            additional_check( testSet );
-            print_stat( testSet );
-            additional_cleanup( testSet );
-        }
-
-        template <class Set>
-        void test()
-        {
-            CPPUNIT_MSG( "Thread count=" << c_nThreadCount
-                << " initial map size=" << c_nInitialMapSize
-                << " insert=" << c_nInsertPercentage << '%'
-                << " delete=" << c_nDeletePercentage << '%'
-                << " duration=" << c_nDuration << "s"
-                );
-
-            for ( size_t nLoadFactor = 1; nLoadFactor <= c_nMaxLoadFactor; nLoadFactor *= 2 ) {
-                do_test<Set>( nLoadFactor );
-                if ( c_bPrintGCState )
-                    print_gc_state();
-            }
-        }
-
-        template <class Set>
-        void test_nolf()
-        {
-            CPPUNIT_MSG( "Thread count=" << c_nThreadCount
-                << " initial map size=" << c_nInitialMapSize
-                << " insert=" << c_nInsertPercentage << '%'
-                << " delete=" << c_nDeletePercentage << '%'
-                << " duration=" << c_nDuration << "s"
-                );
-
-            Set s;
-            do_test_with( s );
-            //CPPUNIT_MSG( s.statistics() );
-            if ( c_bPrintGCState )
-                print_gc_state();
-        }
-
-        void setUpParams( const CppUnitMini::TestCfg& cfg ) {
-            c_nInitialMapSize = cfg.getULong("InitialMapSize", 500000 );
-            c_nThreadCount = cfg.getULong("ThreadCount", 8 );
-            c_nMaxLoadFactor = cfg.getULong("MaxLoadFactor", 8 );
-            c_nInsertPercentage = cfg.getUInt("InsertPercentage", 5 );
-            c_nDeletePercentage = cfg.getUInt("DeletePercentage", 5 );
-            c_nDuration = cfg.getUInt("Duration", 30 );
-            c_bPrintGCState = cfg.getBool("PrintGCStateFlag", true );
-
-            if ( c_nThreadCount == 0 )
-                c_nThreadCount = cds::OS::topology::processor_count() * 2;
-
-            CPPUNIT_ASSERT( c_nInsertPercentage + c_nDeletePercentage <= 100 );
-
-            actions * pFirst = m_arrShuffle;
-            actions * pLast = m_arrShuffle + c_nInsertPercentage;
-            std::fill( pFirst, pLast, do_insert );
-            pFirst = pLast;
-            pLast += c_nDeletePercentage;
-            std::fill( pFirst, pLast, do_delete );
-            pFirst = pLast;
-            pLast = m_arrShuffle + sizeof(m_arrShuffle)/sizeof(m_arrShuffle[0]);
-            std::fill( pFirst, pLast, do_find );
-            std::random_shuffle( m_arrShuffle, pLast );
-        }
-
-#   include "set2/set_defs.h"
-        CDSUNIT_DECLARE_MichaelSet
-        CDSUNIT_DECLARE_SplitList
-        CDSUNIT_DECLARE_StripedSet
-        CDSUNIT_DECLARE_RefinableSet
-        CDSUNIT_DECLARE_CuckooSet
-        CDSUNIT_DECLARE_SkipListSet
-        CDSUNIT_DECLARE_EllenBinTreeSet
-        CDSUNIT_DECLARE_StdSet
+        setUpParams( m_Cfg.get( "Map_InsDelFind" ));
+
+        run_MichaelSet(in_name, invert);
+        run_SplitList(in_name, invert);
+        run_SkipListSet(in_name, invert);
+        run_EllenBinTreeSet(in_name, invert);
+        run_StripedSet(in_name, invert);
+        run_RefinableSet(in_name, invert);
+        run_CuckooSet(in_name, invert);
+        run_StdSet(in_name, invert);
+
+        endTestCase();
+    }
 
+    /*
         CPPUNIT_TEST_SUITE_( Set_InsDelFind, "Map_InsDelFind" )
             CDSUNIT_TEST_MichaelSet
             CDSUNIT_TEST_SplitList
@@ -274,7 +67,5 @@ namespace set2 {
             CDSUNIT_TEST_CuckooSet
             CDSUNIT_TEST_StdSet
         CPPUNIT_TEST_SUITE_END()
-    };
-
-    CPPUNIT_TEST_SUITE_REGISTRATION( Set_InsDelFind );
+        */
 } // namespace set2
diff --git a/tests/unit/set2/set_insdelfind.h b/tests/unit/set2/set_insdelfind.h
new file mode 100644 (file)
index 0000000..2a128cb
--- /dev/null
@@ -0,0 +1,253 @@
+//$$CDS-header$$
+
+#include "set2/set_types.h"
+#include "cppunit/thread.h"
+#include <algorithm> // random_shuffle
+
+namespace set2 {
+
+#   define TEST_SET(X)          void X() { test<SetTypes<key_type, value_type>::X >()    ; }
+#   define TEST_SET_EXTRACT(X)  TEST_SET(X)
+#   define TEST_SET_NOLF(X)    void X() { test_nolf<SetTypes<key_type, value_type>::X >()    ; }
+#   define TEST_SET_NOLF_EXTRACT(X) TEST_SET_NOLF(X)
+
+    class Set_InsDelFind: public CppUnitMini::TestCase
+    {
+        static size_t c_nInitialMapSize;    // initial map size
+        static size_t c_nThreadCount;       // thread count
+        static size_t c_nMaxLoadFactor;     // maximum load factor
+        static unsigned int c_nInsertPercentage;
+        static unsigned int c_nDeletePercentage;
+        static unsigned int c_nDuration;    // test duration, seconds
+        static bool c_bPrintGCState;
+
+    public:
+        enum actions
+        {
+            do_find,
+            do_insert,
+            do_delete
+        };
+        static const unsigned int c_nShuffleSize = 100;
+        actions m_arrShuffle[c_nShuffleSize];
+
+    protected:
+        typedef CppUnitMini::TestCase Base;
+        typedef size_t  key_type;
+        typedef size_t  value_type;
+
+        template <class Set>
+        class WorkThread: public CppUnitMini::TestThread
+        {
+            Set&     m_Map;
+
+            virtual WorkThread *    clone()
+            {
+                return new WorkThread( *this );
+            }
+        public:
+            size_t  m_nInsertSuccess;
+            size_t  m_nInsertFailed;
+            size_t  m_nDeleteSuccess;
+            size_t  m_nDeleteFailed;
+            size_t  m_nFindSuccess;
+            size_t  m_nFindFailed;
+
+        public:
+            WorkThread( CppUnitMini::ThreadPool& pool, Set& rMap )
+                : CppUnitMini::TestThread( pool )
+                , m_Map( rMap )
+            {}
+            WorkThread( WorkThread& src )
+                : CppUnitMini::TestThread( src )
+                , m_Map( src.m_Map )
+            {}
+
+            Set_InsDelFind&  getTest()
+            {
+                return reinterpret_cast<Set_InsDelFind&>( m_Pool.m_Test );
+            }
+
+            virtual void init() { cds::threading::Manager::attachThread()   ; }
+            virtual void fini() { cds::threading::Manager::detachThread()   ; }
+
+            virtual void test()
+            {
+                Set& rMap = m_Map;
+
+                m_nInsertSuccess =
+                    m_nInsertFailed =
+                    m_nDeleteSuccess =
+                    m_nDeleteFailed =
+                    m_nFindSuccess =
+                    m_nFindFailed = 0;
+
+                actions * pAct = getTest().m_arrShuffle;
+                unsigned int i = 0;
+                size_t const nNormalize = size_t(-1) / (c_nInitialMapSize * 2);
+
+                size_t nRand = 0;
+                while ( !time_elapsed() ) {
+                    nRand = cds::bitop::RandXorShift(nRand);
+                    size_t n = nRand / nNormalize;
+                    switch ( pAct[i] ) {
+                    case do_find:
+                        if ( rMap.find( n ))
+                            ++m_nFindSuccess;
+                        else
+                            ++m_nFindFailed;
+                        break;
+                    case do_insert:
+                        if ( rMap.insert( n ))
+                            ++m_nInsertSuccess;
+                        else
+                            ++m_nInsertFailed;
+                        break;
+                    case do_delete:
+                        if ( rMap.erase( n ))
+                            ++m_nDeleteSuccess;
+                        else
+                            ++m_nDeleteFailed;
+                        break;
+                    }
+
+                    if ( ++i >= c_nShuffleSize )
+                        i = 0;
+                }
+            }
+        };
+
+    protected:
+        template <class Set>
+        void do_test( size_t nLoadFactor )
+        {
+            CPPUNIT_MSG( "Load factor=" << nLoadFactor );
+
+            Set  testSet( c_nInitialMapSize, nLoadFactor );
+            do_test_with( testSet );
+        }
+
+        template <class Set>
+        void do_test_with( Set& testSet )
+        {
+            typedef WorkThread<Set> work_thread;
+
+            // fill map - only odd number
+            {
+                size_t * pInitArr = new size_t[ c_nInitialMapSize ];
+                size_t * pEnd = pInitArr + c_nInitialMapSize;
+                for ( size_t i = 0; i < c_nInitialMapSize; ++i )
+                    pInitArr[i] = i * 2 + 1;
+                std::random_shuffle( pInitArr, pEnd );
+                for ( size_t * p = pInitArr; p < pEnd; ++p )
+                    testSet.insert( typename Set::value_type( *p, *p ) );
+                delete [] pInitArr;
+            }
+
+            cds::OS::Timer    timer;
+
+            CppUnitMini::ThreadPool pool( *this );
+            pool.add( new work_thread( pool, testSet ), c_nThreadCount );
+            pool.run( c_nDuration );
+            CPPUNIT_MSG( "   Duration=" << pool.avgDuration() );
+
+            size_t nInsertSuccess = 0;
+            size_t nInsertFailed = 0;
+            size_t nDeleteSuccess = 0;
+            size_t nDeleteFailed = 0;
+            size_t nFindSuccess = 0;
+            size_t nFindFailed = 0;
+            for ( CppUnitMini::ThreadPool::iterator it = pool.begin(); it != pool.end(); ++it ) {
+                work_thread * pThread = static_cast<work_thread *>( *it );
+                assert( pThread != nullptr );
+                nInsertSuccess += pThread->m_nInsertSuccess;
+                nInsertFailed += pThread->m_nInsertFailed;
+                nDeleteSuccess += pThread->m_nDeleteSuccess;
+                nDeleteFailed += pThread->m_nDeleteFailed;
+                nFindSuccess += pThread->m_nFindSuccess;
+                nFindFailed += pThread->m_nFindFailed;
+            }
+
+            size_t nTotalOps = nInsertSuccess + nInsertFailed + nDeleteSuccess + nDeleteFailed + nFindSuccess + nFindFailed;
+
+            CPPUNIT_MSG( "  Totals (success/failed): \n\t"
+                      << "      Insert=" << nInsertSuccess << '/' << nInsertFailed << "\n\t"
+                      << "      Delete=" << nDeleteSuccess << '/' << nDeleteFailed << "\n\t"
+                      << "        Find=" << nFindSuccess   << '/' << nFindFailed   << "\n\t"
+                      << "       Speed=" << (nFindSuccess + nFindFailed) / c_nDuration << " find/sec\n\t"
+                      << "             " << (nInsertSuccess + nDeleteSuccess) / c_nDuration << " modify/sec\n\t"
+                      << "   Total ops=" << nTotalOps << "\n\t"
+                      << "       speed=" << nTotalOps / c_nDuration << " ops/sec\n\t"
+                      << "      Set size=" << testSet.size()
+                );
+
+
+            CPPUNIT_MSG( "  Clear map (single-threaded)..." );
+            timer.reset();
+            testSet.clear();
+            CPPUNIT_MSG( "   Duration=" << timer.duration() );
+            CPPUNIT_CHECK_EX( testSet.empty(), ((long long) testSet.size()) );
+
+            additional_check( testSet );
+            print_stat( testSet );
+            additional_cleanup( testSet );
+        }
+
+        template <class Set>
+        void test()
+        {
+            CPPUNIT_MSG( "Thread count=" << c_nThreadCount
+                << " initial map size=" << c_nInitialMapSize
+                << " insert=" << c_nInsertPercentage << '%'
+                << " delete=" << c_nDeletePercentage << '%'
+                << " duration=" << c_nDuration << "s"
+                );
+
+            for ( size_t nLoadFactor = 1; nLoadFactor <= c_nMaxLoadFactor; nLoadFactor *= 2 ) {
+                do_test<Set>( nLoadFactor );
+                if ( c_bPrintGCState )
+                    print_gc_state();
+            }
+        }
+
+        template <class Set>
+        void test_nolf()
+        {
+            CPPUNIT_MSG( "Thread count=" << c_nThreadCount
+                << " initial map size=" << c_nInitialMapSize
+                << " insert=" << c_nInsertPercentage << '%'
+                << " delete=" << c_nDeletePercentage << '%'
+                << " duration=" << c_nDuration << "s"
+                );
+
+            Set s;
+            do_test_with( s );
+            //CPPUNIT_MSG( s.statistics() );
+            if ( c_bPrintGCState )
+                print_gc_state();
+        }
+
+        void setUpParams( const CppUnitMini::TestCfg& cfg );
+
+        void run_MichaelSet(const char *in_name, bool invert = false);
+        void run_SplitList(const char *in_name, bool invert = false);
+        void run_SkipListSet(const char *in_name, bool invert = false);
+        void run_CuckooSet(const char *in_name, bool invert = false);
+        void run_StripedSet(const char *in_name, bool invert = false);
+        void run_RefinableSet(const char *in_name, bool invert = false);
+        void run_EllenBinTreeSet(const char *in_name, bool invert = false);
+        void run_StdSet(const char *in_name, bool invert = false);
+
+        virtual void myRun(const char *in_name, bool invert = false);
+
+#   include "set2/set_defs.h"
+        CDSUNIT_DECLARE_MichaelSet
+        CDSUNIT_DECLARE_SplitList
+        CDSUNIT_DECLARE_StripedSet
+        CDSUNIT_DECLARE_RefinableSet
+        CDSUNIT_DECLARE_CuckooSet
+        CDSUNIT_DECLARE_SkipListSet
+        CDSUNIT_DECLARE_EllenBinTreeSet
+        CDSUNIT_DECLARE_StdSet
+    };
+} // namespace set2
diff --git a/tests/unit/set2/set_insdelfind_cuckoo.cpp b/tests/unit/set2/set_insdelfind_cuckoo.cpp
new file mode 100644 (file)
index 0000000..f5986ab
--- /dev/null
@@ -0,0 +1,9 @@
+//$$CDS-header$$
+
+#include "set2/set_insdelfind.h"
+
+namespace set2 {
+    CPPUNIT_TEST_SUITE_PART( Set_InsDelFind, run_CuckooSet )
+        CDSUNIT_TEST_CuckooSet
+    CPPUNIT_TEST_SUITE_END_PART()
+} // namespace set2
diff --git a/tests/unit/set2/set_insdelfind_ellentree.cpp b/tests/unit/set2/set_insdelfind_ellentree.cpp
new file mode 100644 (file)
index 0000000..db2a7e3
--- /dev/null
@@ -0,0 +1,9 @@
+//$$CDS-header$$
+
+#include "set2/set_insdelfind.h"
+
+namespace set2 {
+    CPPUNIT_TEST_SUITE_PART( Set_InsDelFind, run_EllenBinTreeSet )
+        CDSUNIT_TEST_EllenBinTreeSet
+    CPPUNIT_TEST_SUITE_END_PART()
+} // namespace set2
diff --git a/tests/unit/set2/set_insdelfind_michael.cpp b/tests/unit/set2/set_insdelfind_michael.cpp
new file mode 100644 (file)
index 0000000..631111f
--- /dev/null
@@ -0,0 +1,9 @@
+//$$CDS-header$$
+
+#include "set2/set_insdelfind.h"
+
+namespace set2 {
+    CPPUNIT_TEST_SUITE_PART( Set_InsDelFind, run_MichaelSet )
+        CDSUNIT_TEST_MichaelSet
+    CPPUNIT_TEST_SUITE_END_PART()
+} // namespace set2
diff --git a/tests/unit/set2/set_insdelfind_refinable.cpp b/tests/unit/set2/set_insdelfind_refinable.cpp
new file mode 100644 (file)
index 0000000..942113e
--- /dev/null
@@ -0,0 +1,9 @@
+//$$CDS-header$$
+
+#include "set2/set_insdelfind.h"
+
+namespace set2 {
+    CPPUNIT_TEST_SUITE_PART( Set_InsDelFind, run_RefinableSet )
+        CDSUNIT_TEST_RefinableSet
+    CPPUNIT_TEST_SUITE_END_PART()
+} // namespace set2
diff --git a/tests/unit/set2/set_insdelfind_skip.cpp b/tests/unit/set2/set_insdelfind_skip.cpp
new file mode 100644 (file)
index 0000000..8e49865
--- /dev/null
@@ -0,0 +1,9 @@
+//$$CDS-header$$
+
+#include "set2/set_insdelfind.h"
+
+namespace set2 {
+    CPPUNIT_TEST_SUITE_PART( Set_InsDelFind, run_SkipListSet )
+        CDSUNIT_TEST_SkipListSet
+    CPPUNIT_TEST_SUITE_END_PART()
+} // namespace set2
diff --git a/tests/unit/set2/set_insdelfind_split.cpp b/tests/unit/set2/set_insdelfind_split.cpp
new file mode 100644 (file)
index 0000000..c16b852
--- /dev/null
@@ -0,0 +1,9 @@
+//$$CDS-header$$
+
+#include "set2/set_insdelfind.h"
+
+namespace set2 {
+    CPPUNIT_TEST_SUITE_PART( Set_InsDelFind, run_SplitList )
+        CDSUNIT_TEST_SplitList
+    CPPUNIT_TEST_SUITE_END_PART()
+} // namespace set2
diff --git a/tests/unit/set2/set_insdelfind_std.cpp b/tests/unit/set2/set_insdelfind_std.cpp
new file mode 100644 (file)
index 0000000..7543b88
--- /dev/null
@@ -0,0 +1,9 @@
+//$$CDS-header$$
+
+#include "set2/set_insdelfind.h"
+
+namespace set2 {
+    CPPUNIT_TEST_SUITE_PART( Set_InsDelFind, run_StdSet )
+        CDSUNIT_TEST_StdSet
+    CPPUNIT_TEST_SUITE_END_PART()
+} // namespace set2
diff --git a/tests/unit/set2/set_insdelfind_striped.cpp b/tests/unit/set2/set_insdelfind_striped.cpp
new file mode 100644 (file)
index 0000000..f98d69f
--- /dev/null
@@ -0,0 +1,9 @@
+//$$CDS-header$$
+
+#include "set2/set_insdelfind.h"
+
+namespace set2 {
+    CPPUNIT_TEST_SUITE_PART( Set_InsDelFind, run_StripedSet )
+        CDSUNIT_TEST_StripedSet
+    CPPUNIT_TEST_SUITE_END_PART()
+} // namespace set2
index a048eb3791122dfe1f4929d0ca62bd79da4bc033..1e163239a33400e6b0787be0d8dbfee6d1236afb 100644 (file)
@@ -1806,6 +1806,20 @@ namespace set2 {
         ellen_bintree_pool::internal_node_counter::reset();
     }
 
+    //*******************************************************
+    // check_before_clear
+    //*******************************************************
+
+    template <typename Set>
+    static inline void check_before_clear( Set& /*s*/ )
+    {}
+
+    template <typename GC, typename Key, typename T, typename Traits>
+    static inline void check_before_clear( cds::container::EllenBinTreeSet<GC, Key, T, Traits>& s )
+    {
+        CPPUNIT_CHECK_CURRENT( s.check_consistency() );
+    }
+
 }   // namespace set2
 
 #endif // ifndef CDSUNIT_SET_TYPES_H