From 6939ae56531e7c7f066e88c97862c9aa28278edd Mon Sep 17 00:00:00 2001 From: Mike Buland Date: Sun, 16 Aug 2015 23:09:59 +0000 Subject: Fixed a highly essoteric issue. The ReadWriteMutex was locked in write while syncing changes. That was important so that more changes wouldn't be added while we're writing, but it also meant that in a very particular circumstance where one thread was syncing changes, another was marking changes as having happened, and another locked an object that was being written because it had changes they would all deadlock. This should be fixed now. --- src/unstable/cachebase.h | 53 +++++++++++++++++++++++++++--------------------- 1 file changed, 30 insertions(+), 23 deletions(-) (limited to 'src/unstable/cachebase.h') diff --git a/src/unstable/cachebase.h b/src/unstable/cachebase.h index 1f78360..5da4ce9 100644 --- a/src/unstable/cachebase.h +++ b/src/unstable/cachebase.h @@ -518,8 +518,10 @@ namespace Bu void sync() { - Bu::ReadWriteMutex::WriteLocker wl( mCacheEntry ); - _sync(); + { + Bu::ReadWriteMutex::WriteLocker wl( mCacheEntry ); + _sync(); + } syncChanges(); } @@ -601,30 +603,35 @@ namespace Bu void syncChanges() { - if( !hChanged.isEmpty() ) + Bu::List lKeys; + mCacheEntry.lockWrite(); + for( typename CacheKeySet::iterator i = hChanged.begin(); i; i++ ) { - for( typename CacheKeySet::iterator i = hChanged.begin(); i; i++ ) + lKeys.append( i.getKey() ); + } + hChanged.clear(); + mCacheEntry.unlockWrite(); + + for( typename List::iterator i = lKeys.begin(); i; i++ ) + { + Entry *pEnt = NULL; + try + { + pEnt = hCacheEntry.get( *i ); + } + catch( Bu::HashException ) + { + // The entry wasn't there, most likely because it + // was deleted. That's ok. + } + // This isn't inside of the above because we want to be + // able to handle these exceptions differently. + if( pEnt ) { - Entry *pEnt = NULL; - try - { - pEnt = hCacheEntry.get( i.getKey() ); - } - catch( Bu::HashException ) - { - // The entry wasn't there, most likely because it - // was deleted. That's ok. - } - // This isn't inside of the above because we want to be - // able to handle these exceptions differently. - if( pEnt ) - { - Bu::MutexLocker ml( pEnt->getMutex() ); - _save( pEnt->getPtr() ); - pEnt->getPtr()->changed( false ); - } + Bu::MutexLocker ml( pEnt->getMutex() ); + _save( pEnt->getPtr() ); + pEnt->getPtr()->changed( false ); } - hChanged.clear(); } } -- cgit v1.2.3