Created
December 19, 2017 00:13
-
-
Save bonetechnologies/a85bfb4fca7376369d0f7581e3bec0e6 to your computer and use it in GitHub Desktop.
This file contains hidden or 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
/** | |
* <ul> | |
* <li>{@code keyCreator} creates the key which indexes the value to be saved</li> | |
* <li>{@code reader} reads the value stored with the key provided by {@code keyCreator}</li> | |
* <li>{@code creator} is a function that takes the value read by {@code reader} and returns a new value to be stored</li> | |
* </ul> | |
*/ | |
public <T> void readWriteCompare(Provider<String> keyCreator, Provider<Optional<T>> reader, Function<Optional<T>, T> creator) { | |
// This method protects against concurrent writes of the owner list using the read-write-compare technique | |
// Starvation is hedged against with a random sleep, but is still possible | |
// NOTE: database transactions would be nice :( | |
while (true) { | |
// read | |
Optional<T> existing = reader.get(); | |
T toWrite = creator.apply(existing); | |
// write | |
save(keyCreator.get(), toWrite); | |
// compare | |
Optional<T> observed = reader.get(); | |
if (!observed.isPresent()) { | |
throw new RuntimeException("Just wrote some stuff but can't find any thing"); | |
} | |
boolean equal = toWrite.equals(observed.get()); | |
if (!equal) { | |
try { | |
long delay = randomWriteDelay(); | |
log.info("Delaying next write attempt for " + delay + " milliseconds"); | |
Thread.sleep(delay); | |
} catch (InterruptedException e) { | |
throw Throwables.propagate(e); | |
} | |
} else { | |
break; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment