@Override public RCountDownLatch getCountDownLatch(K key) { String lockName = getLockName(key, "countdownlatch"); return new RedissonCountDownLatch(commandExecutor, lockName); }
@Override public boolean await(long time, TimeUnit unit) throws InterruptedException { long remainTime = unit.toMillis(time); long current = System.currentTimeMillis(); RFuture<RedissonCountDownLatchEntry> promise = subscribe(); if (!await(promise, time, unit)) { return false; } try { remainTime -= (System.currentTimeMillis() - current); if (remainTime <= 0) { return false; } while (getCount() > 0) { if (remainTime <= 0) { return false; } current = System.currentTimeMillis(); // waiting for open state RedissonCountDownLatchEntry entry = getEntry(); if (entry != null) { entry.getLatch().await(remainTime, TimeUnit.MILLISECONDS); } remainTime -= (System.currentTimeMillis() - current); } return true; } finally { unsubscribe(promise); } }
@Override public void countDown() { get(countDownAsync()); }
@Override public long getCount() { return get(getCountAsync()); }
@Override public boolean trySetCount(long count) { return get(trySetCountAsync(count)); }
@Override public RFuture<Boolean> trySetCountAsync(long count) { return commandExecutor.evalWriteAsync(getName(), LongCodec.INSTANCE, RedisCommands.EVAL_BOOLEAN, "if redis.call('exists', KEYS[1]) == 0 then " + "redis.call('set', KEYS[1], ARGV[2]); " + "redis.call('publish', KEYS[2], ARGV[1]); " + "return 1 " + "else " + "return 0 " + "end", Arrays.<Object>asList(getName(), getChannelName()), newCountMessage, count); }
private RFuture<RedissonCountDownLatchEntry> subscribe() { return PUBSUB.subscribe(getEntryName(), getChannelName(), commandExecutor.getConnectionManager().getSubscribeService()); }
private String getEntryName() { return id + getName(); }
private RedissonCountDownLatchEntry getEntry() { return PUBSUB.getEntry(getEntryName()); }
public void await() throws InterruptedException { RFuture<RedissonCountDownLatchEntry> future = subscribe(); try { commandExecutor.syncSubscription(future); while (getCount() > 0) { // waiting for open state RedissonCountDownLatchEntry entry = getEntry(); if (entry != null) { entry.getLatch().await(); } } } finally { unsubscribe(future); } }
@Override public RFuture<Void> countDownAsync() { return commandExecutor.evalWriteAsync(getName(), LongCodec.INSTANCE, RedisCommands.EVAL_BOOLEAN, "local v = redis.call('decr', KEYS[1]);" + "if v <= 0 then redis.call('del', KEYS[1]) end;" + "if v == 0 then redis.call('publish', KEYS[2], ARGV[1]) end;", Arrays.<Object>asList(getName(), getChannelName()), zeroCountMessage); }
private RFuture<RedissonCountDownLatchEntry> subscribe() { return PUBSUB.subscribe(getEntryName(), getChannelName(), commandExecutor.getConnectionManager().getSubscribeService()); }
@Override public long getCount() { return get(getCountAsync()); }
@Override public boolean trySetCount(long count) { return get(trySetCountAsync(count)); }
private String getChannelName() { return "redisson_countdownlatch__channel__{" + getName() + "}"; }
private RedissonCountDownLatchEntry getEntry() { return PUBSUB.getEntry(getEntryName()); }
public void await() throws InterruptedException { RFuture<RedissonCountDownLatchEntry> future = subscribe(); try { commandExecutor.syncSubscription(future); while (getCount() > 0) { // waiting for open state RedissonCountDownLatchEntry entry = getEntry(); if (entry != null) { entry.getLatch().await(); } } } finally { unsubscribe(future); } }
@Override public RFuture<Boolean> trySetCountAsync(long count) { return commandExecutor.evalWriteAsync(getName(), LongCodec.INSTANCE, RedisCommands.EVAL_BOOLEAN, "if redis.call('exists', KEYS[1]) == 0 then " + "redis.call('set', KEYS[1], ARGV[2]); " + "redis.call('publish', KEYS[2], ARGV[1]); " + "return 1 " + "else " + "return 0 " + "end", Arrays.<Object>asList(getName(), getChannelName()), newCountMessage, count); }
private void unsubscribe(RFuture<RedissonCountDownLatchEntry> future) { PUBSUB.unsubscribe(future.getNow(), getEntryName(), getChannelName(), commandExecutor.getConnectionManager().getSubscribeService()); }
@Override public RCountDownLatch getCountDownLatch(V value) { String lockName = getLockName(value, "countdownlatch"); return new RedissonCountDownLatch(commandExecutor, lockName); }