Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Fix refreshAfterWrite racing with a removed entry (fixes #715)
When a read triggers a refresh, it captures the key and value into local variables and performs validation checks. This should have included verifying that the entry is still alive (vs retired, dead). Otherwise, the key may be an internal sentinel and the refresh will fail. This has no harmful effects due to being logged and swallowed.
- Loading branch information
Showing
4 changed files
with
66 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -29,12 +29,13 @@ | |
* @author ben.manes@gmail.com (Ben Manes) | ||
*/ | ||
interface NodeFactory<K, V> { | ||
WeakKeyReference<Object> RETIRED_WEAK_KEY = new WeakKeyReference<>(null, null); | ||
WeakKeyReference<Object> DEAD_WEAK_KEY = new WeakKeyReference<>(null, null); | ||
MethodType FACTORY = MethodType.methodType(void.class); | ||
MethodHandles.Lookup LOOKUP = MethodHandles.lookup(); | ||
Object RETIRED_STRONG_KEY = new Object(); | ||
Object DEAD_STRONG_KEY = new Object(); | ||
|
||
RetiredStrongKey RETIRED_STRONG_KEY = new RetiredStrongKey(); | ||
RetiredWeakKey RETIRED_WEAK_KEY = new RetiredWeakKey(); | ||
DeadStrongKey DEAD_STRONG_KEY = new DeadStrongKey(); | ||
DeadWeakKey DEAD_WEAK_KEY = new DeadWeakKey(); | ||
String ACCESS_TIME = "accessTime"; | ||
String WRITE_TIME = "writeTime"; | ||
String VALUE = "value"; | ||
|
@@ -141,4 +142,13 @@ static <K, V> NodeFactory<K, V> loadFactory(String className) { | |
throw new IllegalStateException(className, t); | ||
} | ||
} | ||
|
||
final class RetiredWeakKey extends WeakKeyReference<Object> { | ||
RetiredWeakKey() { super(/* key */ null, /* referenceQueue */ null); } | ||
} | ||
final class DeadWeakKey extends WeakKeyReference<Object> { | ||
DeadWeakKey() { super(/* key */ null, /* referenceQueue */ null); } | ||
} | ||
final class RetiredStrongKey {} | ||
final class DeadStrongKey {} | ||
This comment has been minimized.
Sorry, something went wrong.
This comment has been minimized.
Sorry, something went wrong.
ben-manes
Author
Owner
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Nice, was thinking similarly to make it more obvious if this kind of thing ever happens again where the objects are coming from. This should probably be considered best practice for singleton objects.