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 );
}
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 );
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 ) {
// 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 );
);
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
{
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();
}
}
else if ( nChildVersion != node_type::unlinked ) {
-
if ( pNode->version( memory_model::memory_order_acquire ) != nVersion ) {
m_stat.onFindRetry();
return find_result::retry;
if ( found != find_result::retry )
return found;
}
+
+ if ( pNode->version( memory_model::memory_order_acquire ) != nVersion ) {
+ m_stat.onFindRetry();
+ return find_result::retry;
+ }
}
}
// 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 );
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;
// 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 );
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;
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;
}
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;
}
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;
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;
}
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;
}
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;
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;
}
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;
}
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;
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 );
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 )))
{
{
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;
}
// 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;
//@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;
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;
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 );
}
{
// 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 ))
}
}
- 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;
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 );
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.
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
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
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
{
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 );
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 );
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 )
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 );
// 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();
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 );
// 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();
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 );
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 );
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 );
// 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 );
</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
</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
--- /dev/null
+<?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
</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
--- /dev/null
+<?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
</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
</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
--- /dev/null
+<?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
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 \
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 \
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
{
std::cerr << "bad_lexical_cast encountered while getting parameter "
<< strParamName << "=" << it->second
<< ": " << ex.what()
- << std::endl
-;
+ << std::endl;
}
return bDefVal;
}
//$$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
--- /dev/null
+//$$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
--- /dev/null
+//$$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
--- /dev/null
+//$$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
--- /dev/null
+//$$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
--- /dev/null
+//$$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
--- /dev/null
+//$$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
--- /dev/null
+//$$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
// 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
--- /dev/null
+//$$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
--- /dev/null
+//$$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
--- /dev/null
+//$$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
--- /dev/null
+//$$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
--- /dev/null
+//$$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
--- /dev/null
+//$$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
--- /dev/null
+//$$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
--- /dev/null
+//$$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
--- /dev/null
+//$$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
--- /dev/null
+//$$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
//$$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
--- /dev/null
+//$$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
--- /dev/null
+//$$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
--- /dev/null
+//$$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
--- /dev/null
+//$$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
--- /dev/null
+//$$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
--- /dev/null
+//$$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
--- /dev/null
+//$$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
--- /dev/null
+//$$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
--- /dev/null
+//$$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
--- /dev/null
+//$$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
endTestCase();
}
-
- CPPUNIT_TEST_SUITE_PART( Map_InsDel_func, run_MichaelMap )
- CDSUNIT_TEST_MichaelMap
- CPPUNIT_TEST_SUITE_END_PART()
} // namespace map2
+++ /dev/null
-//$$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
-
+++ /dev/null
-//$$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
-
+++ /dev/null
-//$$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
-
+++ /dev/null
-//$$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
+++ /dev/null
-//$$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
+++ /dev/null
-//$$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
+++ /dev/null
-//$$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
--- /dev/null
+//$$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
--- /dev/null
+//$$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
--- /dev/null
+//$$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
+
--- /dev/null
+//$$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
--- /dev/null
+//$$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
--- /dev/null
+//$$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
+
--- /dev/null
+//$$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
+
--- /dev/null
+//$$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
//$$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
--- /dev/null
+//$$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
--- /dev/null
+//$$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
--- /dev/null
+//$$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
--- /dev/null
+//$$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
--- /dev/null
+//$$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
--- /dev/null
+//$$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
--- /dev/null
+//$$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
--- /dev/null
+//$$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
--- /dev/null
+//$$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
//$$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
--- /dev/null
+//$$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
--- /dev/null
+//$$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
--- /dev/null
+//$$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
--- /dev/null
+//$$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
--- /dev/null
+//$$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
--- /dev/null
+//$$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
--- /dev/null
+//$$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
--- /dev/null
+//$$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
--- /dev/null
+//$$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
//$$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
--- /dev/null
+//$$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
--- /dev/null
+//$$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
--- /dev/null
+//$$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
--- /dev/null
+//$$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
--- /dev/null
+//$$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
--- /dev/null
+//$$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
--- /dev/null
+//$$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
--- /dev/null
+//$$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
--- /dev/null
+//$$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
//$$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
--- /dev/null
+//$$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
--- /dev/null
+//$$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
--- /dev/null
+//$$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
--- /dev/null
+//$$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
--- /dev/null
+//$$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
--- /dev/null
+//$$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
--- /dev/null
+//$$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
--- /dev/null
+//$$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
--- /dev/null
+//$$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
--- /dev/null
+//$$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
//$$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
--- /dev/null
+//$$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
--- /dev/null
+//$$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
--- /dev/null
+//$$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
--- /dev/null
+//$$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
--- /dev/null
+//$$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
--- /dev/null
+//$$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
--- /dev/null
+//$$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
--- /dev/null
+//$$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
--- /dev/null
+//$$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
--- /dev/null
+//$$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
//$$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
--- /dev/null
+//$$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
--- /dev/null
+//$$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
--- /dev/null
+//$$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
--- /dev/null
+//$$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
--- /dev/null
+//$$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
--- /dev/null
+//$$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
--- /dev/null
+//$$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
--- /dev/null
+//$$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
--- /dev/null
+//$$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
--- /dev/null
+//$$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
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>
//$$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
--- /dev/null
+//$$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
--- /dev/null
+//$$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
--- /dev/null
+//$$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
--- /dev/null
+//$$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
--- /dev/null
+//$$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
--- /dev/null
+//$$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
+++ /dev/null
-//$$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
+++ /dev/null
-//$$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
+++ /dev/null
-//$$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
+++ /dev/null
-//$$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
+++ /dev/null
-//$$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
+++ /dev/null
-//$$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
--- /dev/null
+//$$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
--- /dev/null
+//$$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
--- /dev/null
+//$$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
--- /dev/null
+//$$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
--- /dev/null
+//$$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
--- /dev/null
+//$$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
//$$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
--- /dev/null
+//$$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
--- /dev/null
+//$$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
--- /dev/null
+//$$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
--- /dev/null
+//$$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
--- /dev/null
+//$$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
--- /dev/null
+//$$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
--- /dev/null
+//$$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
--- /dev/null
+//$$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
--- /dev/null
+//$$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
//$$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
CDSUNIT_TEST_CuckooSet
CDSUNIT_TEST_StdSet
CPPUNIT_TEST_SUITE_END()
- };
-
- CPPUNIT_TEST_SUITE_REGISTRATION( Set_InsDelFind );
+ */
} // namespace set2
--- /dev/null
+//$$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
--- /dev/null
+//$$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
--- /dev/null
+//$$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
--- /dev/null
+//$$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
--- /dev/null
+//$$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
--- /dev/null
+//$$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
--- /dev/null
+//$$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
--- /dev/null
+//$$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
--- /dev/null
+//$$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
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