Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save bonetechnologies/a85bfb4fca7376369d0f7581e3bec0e6 to your computer and use it in GitHub Desktop.
Save bonetechnologies/a85bfb4fca7376369d0f7581e3bec0e6 to your computer and use it in GitHub Desktop.
/**
* <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