bool RandomizeMutexOrder( LevelMutexInfo::MutexContainer & mutexes ) { unsigned int count = mutexes.size(); if ( count < 2 ) return false; LevelMutexInfo::MutexContainer randomMutexes; for ( unsigned int ii = 0; ii < count; ++ii ) { volatile LevelMutexInfo * mutex = nullptr; const unsigned int sizeNow = mutexes.size(); if ( 1 < sizeNow ) { unsigned int index = ( ::rand() % sizeNow ); mutex = mutexes[ index ]; if ( index < sizeNow - 1 ) mutexes[ index ] = mutexes[ sizeNow - 1 ]; } else { mutex = mutexes[ 0 ]; } mutexes.pop_back(); randomMutexes.push_back( mutex ); } mutexes = randomMutexes; return true; }
void UnlockThese( SomeThingPool & pool ) { const unsigned int count = pool.size(); assert( 0 != count ); SortByLevel( pool ); volatile SomeThing * thing = pool[ 0 ]; assert( NULL != thing ); unsigned int level = thing->GetLevel(); LevelMutexInfo::MutexContainer mutexes; MutexErrors::Type result = MutexErrors::Success; unsigned int ii = 0; for ( ii = 0; ii < count; ++ii ) { thing = pool[ ii ]; assert( NULL != thing ); if ( level != thing->GetLevel() ) { assert( mutexes.size() != 0 ); result = LevelMutexInfo::MultiUnlock( mutexes ); assert( result == MutexErrors::Success ); mutexes.clear(); level = thing->GetLevel(); } mutexes.push_back( &thing->GetMutex() ); } assert( mutexes.size() != 0 ); result = LevelMutexInfo::MultiUnlock( mutexes ); assert( result == MutexErrors::Success ); for ( ii = 0; ii < count; ++ii ) { thing = pool[ ii ]; assert( NULL != thing ); assert( !thing->GetMutex().IsLockedByCurrentThread() ); } }