aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Buland <eichlan@xagasoft.com>2015-08-16 23:09:59 +0000
committerMike Buland <eichlan@xagasoft.com>2015-08-16 23:09:59 +0000
commit6939ae56531e7c7f066e88c97862c9aa28278edd (patch)
tree7d32ea9bc61864915b70b8663fa7fc2a6681b142
parente7e8164d1f4baccb1c1bfd7c370342456b1a8f29 (diff)
downloadlibbu++-6939ae56531e7c7f066e88c97862c9aa28278edd.tar.gz
libbu++-6939ae56531e7c7f066e88c97862c9aa28278edd.tar.bz2
libbu++-6939ae56531e7c7f066e88c97862c9aa28278edd.tar.xz
libbu++-6939ae56531e7c7f066e88c97862c9aa28278edd.zip
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.
Diffstat (limited to '')
-rw-r--r--src/unstable/cachebase.h53
1 files changed, 30 insertions, 23 deletions
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
518 518
519 void sync() 519 void sync()
520 { 520 {
521 Bu::ReadWriteMutex::WriteLocker wl( mCacheEntry ); 521 {
522 _sync(); 522 Bu::ReadWriteMutex::WriteLocker wl( mCacheEntry );
523 _sync();
524 }
523 syncChanges(); 525 syncChanges();
524 } 526 }
525 527
@@ -601,30 +603,35 @@ namespace Bu
601 603
602 void syncChanges() 604 void syncChanges()
603 { 605 {
604 if( !hChanged.isEmpty() ) 606 Bu::List<keytype> lKeys;
607 mCacheEntry.lockWrite();
608 for( typename CacheKeySet::iterator i = hChanged.begin(); i; i++ )
605 { 609 {
606 for( typename CacheKeySet::iterator i = hChanged.begin(); i; i++ ) 610 lKeys.append( i.getKey() );
611 }
612 hChanged.clear();
613 mCacheEntry.unlockWrite();
614
615 for( typename List<keytype>::iterator i = lKeys.begin(); i; i++ )
616 {
617 Entry *pEnt = NULL;
618 try
619 {
620 pEnt = hCacheEntry.get( *i );
621 }
622 catch( Bu::HashException )
623 {
624 // The entry wasn't there, most likely because it
625 // was deleted. That's ok.
626 }
627 // This isn't inside of the above because we want to be
628 // able to handle these exceptions differently.
629 if( pEnt )
607 { 630 {
608 Entry *pEnt = NULL; 631 Bu::MutexLocker ml( pEnt->getMutex() );
609 try 632 _save( pEnt->getPtr() );
610 { 633 pEnt->getPtr()->changed( false );
611 pEnt = hCacheEntry.get( i.getKey() );
612 }
613 catch( Bu::HashException )
614 {
615 // The entry wasn't there, most likely because it
616 // was deleted. That's ok.
617 }
618 // This isn't inside of the above because we want to be
619 // able to handle these exceptions differently.
620 if( pEnt )
621 {
622 Bu::MutexLocker ml( pEnt->getMutex() );
623 _save( pEnt->getPtr() );
624 pEnt->getPtr()->changed( false );
625 }
626 } 634 }
627 hChanged.clear();
628 } 635 }
629 } 636 }
630 637