diff options
author | Mike Buland <eichlan@xagasoft.com> | 2015-08-16 23:09:59 +0000 |
---|---|---|
committer | Mike Buland <eichlan@xagasoft.com> | 2015-08-16 23:09:59 +0000 |
commit | 6939ae56531e7c7f066e88c97862c9aa28278edd (patch) | |
tree | 7d32ea9bc61864915b70b8663fa7fc2a6681b142 /src | |
parent | e7e8164d1f4baccb1c1bfd7c370342456b1a8f29 (diff) | |
download | libbu++-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.h | 53 |
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 | ||