|
|
|
@ -135,6 +135,11 @@ public class RedissonSemaphore extends RedissonExpirable implements RSemaphore {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void tryAcquireAsync(final AtomicLong time, final int permits, final RFuture<RedissonLockEntry> subscribeFuture, final RPromise<Boolean> result) {
|
|
|
|
|
if (result.isDone()) {
|
|
|
|
|
unsubscribe(subscribeFuture);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
RFuture<Boolean> tryAcquireFuture = tryAcquireAsync(permits);
|
|
|
|
|
tryAcquireFuture.addListener(new FutureListener<Boolean>() {
|
|
|
|
|
@Override
|
|
|
|
@ -144,10 +149,12 @@ public class RedissonSemaphore extends RedissonExpirable implements RSemaphore {
|
|
|
|
|
result.tryFailure(future.cause());
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (future.getNow()) {
|
|
|
|
|
unsubscribe(subscribeFuture);
|
|
|
|
|
result.trySuccess(true);
|
|
|
|
|
if (!result.trySuccess(true)) {
|
|
|
|
|
releaseAsync(permits);
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -170,8 +177,9 @@ public class RedissonSemaphore extends RedissonExpirable implements RSemaphore {
|
|
|
|
|
@Override
|
|
|
|
|
public void run() {
|
|
|
|
|
executed.set(true);
|
|
|
|
|
if (futureRef.get() != null) {
|
|
|
|
|
futureRef.get().cancel();
|
|
|
|
|
if (futureRef.get() != null && !futureRef.get().cancel()) {
|
|
|
|
|
entry.getLatch().release();
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
long elapsed = System.currentTimeMillis() - current;
|
|
|
|
|
time.addAndGet(-elapsed);
|
|
|
|
@ -206,19 +214,26 @@ public class RedissonSemaphore extends RedissonExpirable implements RSemaphore {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void acquireAsync(final int permits, final RFuture<RedissonLockEntry> subscribeFuture, final RPromise<Void> result) {
|
|
|
|
|
if (result.isDone()) {
|
|
|
|
|
unsubscribe(subscribeFuture);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
RFuture<Boolean> tryAcquireFuture = tryAcquireAsync(permits);
|
|
|
|
|
tryAcquireFuture.addListener(new FutureListener<Boolean>() {
|
|
|
|
|
@Override
|
|
|
|
|
public void operationComplete(Future<Boolean> future) throws Exception {
|
|
|
|
|
if (!future.isSuccess()) {
|
|
|
|
|
unsubscribe(subscribeFuture);
|
|
|
|
|
result.setFailure(future.cause());
|
|
|
|
|
result.tryFailure(future.cause());
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (future.getNow()) {
|
|
|
|
|
unsubscribe(subscribeFuture);
|
|
|
|
|
result.setSuccess(null);
|
|
|
|
|
if (!result.trySuccess(null)) {
|
|
|
|
|
releaseAsync(permits);
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -321,12 +336,14 @@ public class RedissonSemaphore extends RedissonExpirable implements RSemaphore {
|
|
|
|
|
@Override
|
|
|
|
|
public void operationComplete(Future<Boolean> future) throws Exception {
|
|
|
|
|
if (!future.isSuccess()) {
|
|
|
|
|
result.setFailure(future.cause());
|
|
|
|
|
result.tryFailure(future.cause());
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (future.getNow()) {
|
|
|
|
|
result.setSuccess(true);
|
|
|
|
|
if (!result.trySuccess(true)) {
|
|
|
|
|
releaseAsync(permits);
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -337,14 +354,14 @@ public class RedissonSemaphore extends RedissonExpirable implements RSemaphore {
|
|
|
|
|
@Override
|
|
|
|
|
public void operationComplete(Future<RedissonLockEntry> future) throws Exception {
|
|
|
|
|
if (!future.isSuccess()) {
|
|
|
|
|
result.setFailure(future.cause());
|
|
|
|
|
result.tryFailure(future.cause());
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (futureRef.get() != null) {
|
|
|
|
|
futureRef.get().cancel();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
long elapsed = System.currentTimeMillis() - current;
|
|
|
|
|
time.addAndGet(-elapsed);
|
|
|
|
|
|
|
|
|
@ -455,5 +472,42 @@ public class RedissonSemaphore extends RedissonExpirable implements RSemaphore {
|
|
|
|
|
+ "end;",
|
|
|
|
|
Arrays.<Object>asList(getName(), getChannelName()), permits);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public boolean trySetPermits(int permits) {
|
|
|
|
|
return get(trySetPermitsAsync(permits));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public RFuture<Boolean> trySetPermitsAsync(int permits) {
|
|
|
|
|
return commandExecutor.evalWriteAsync(getName(), LongCodec.INSTANCE, RedisCommands.EVAL_BOOLEAN,
|
|
|
|
|
"local value = redis.call('get', KEYS[1]); " +
|
|
|
|
|
"if (value == false or value == 0) then "
|
|
|
|
|
+ "redis.call('set', KEYS[1], ARGV[1]); "
|
|
|
|
|
+ "redis.call('publish', KEYS[2], ARGV[1]); "
|
|
|
|
|
+ "return 1;"
|
|
|
|
|
+ "end;"
|
|
|
|
|
+ "return 0;",
|
|
|
|
|
Arrays.<Object>asList(getName(), getChannelName()), permits);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public void reducePermits(int permits) {
|
|
|
|
|
get(reducePermitsAsync(permits));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public RFuture<Void> reducePermitsAsync(int permits) {
|
|
|
|
|
if (permits < 0) {
|
|
|
|
|
throw new IllegalArgumentException();
|
|
|
|
|
}
|
|
|
|
|
return commandExecutor.evalWriteAsync(getName(), LongCodec.INSTANCE, RedisCommands.EVAL_VOID,
|
|
|
|
|
"local value = redis.call('get', KEYS[1]); " +
|
|
|
|
|
"if (value == false) then "
|
|
|
|
|
+ "value = 0;"
|
|
|
|
|
+ "end;"
|
|
|
|
|
+ "redis.call('set', KEYS[1], value - ARGV[1]); ",
|
|
|
|
|
Arrays.<Object>asList(getName(), getChannelName()), permits);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|