Is there a java library that implements something that behaves like a ReadWriteLock
but uses listeners or CompletableFuture/CompletionStage instead of blocking?
Ideally I'd like to write:
lock = ...
CompletionStage stage = lock.lockRead();
stage.thenAccept(r -> { doSomething(); r.release(); });
And also important:
CompletionStage stage = lock.tryLockWrite(10, TimeUnit.SECONDS);
stage.handle(callback);
I'm looking to know if something like this exists and if it does how is it called.
I'm not looking to implement this myself, but rather use a library to simplify some framework code.
I think writing it yourself shouldn't be hard enough. Chances are it would take less time than looking for a library. It's pretty simple overall:
static const int STATE_UNLOCKED = 0;
static const int STATE_READING = 1;
static const int STATE_WRITING = 2;
int state = STATE_UNLOCKED;
int readers = 0;
Queue<CompletableFuture<Void>> queueWriters = new LinkedList<CompletableFuture<Void>>();
Queue<CompletableFuture<Void>> queueReaders = new LinkedList<CompletableFuture<Void>>();
public synchronized CompletionStage<Void> lockWriter() {
CompletableFuture<Void> l = new CompletableFuture<Void>();
if (state == STATE_UNLOCKED) {
state = STATE_WRITING;
l.complete(null);
return l;
}
queueWriters.offer(l);
return l;
}
public synchronized CompletionStage<Void> lockReader() {
CompletableFuture<Void> l = new CompletableFuture<Void>();
if (state != STATE_WRITING) {
state = STATE_READING;
readers++;
l.complete(null);
return l;
}
queueReaders.offer(l);
return l;
}
public void unlock() {
CompletableFuture<Void> l = null;
synchronized(this) {
if (state == STATE_READING) {
readers--;
if (readers > 0) {
return;
}
}
l = queueReaders.poll();
if (l != null) {
state = STATE_READING;
readers++;
}
else {
l = queueWriters.poll();
if (l != null) {
state = STATE_WRITING;
}
else {
state = STATE_UNLOCKED;
return;
}
}
}
l.complete(null);
while (true) {
synchronized (this) {
if (state != STATE_READING) {
return;
}
l = queueReaders.poll();
if (l == null) {
return;
}
readers++;
}
l.complete(null);
}
}
Adding timed locking (By using some sort of "expiring queue" or writer-starvation prevention (By preventing additional readers from being executed if queueWriters
is not empty) to the above shouldn't be that much more difficult either.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With