IoFuture<Connection> connect(FutureResult<Connection> orig) { AtomicReference<FutureResult<Connection>> futureConnectionRef = this.futureConnectionRef; FutureResult<Connection> oldVal; oldVal = futureConnectionRef.get(); if (oldVal != orig) { return oldVal.getIoFuture(); } final FutureResult<Connection> futureResult = new FutureResult<>(); while (!futureConnectionRef.compareAndSet(oldVal, futureResult)) { oldVal = futureConnectionRef.get(); if (oldVal != orig) { // discard our new one return oldVal.getIoFuture(); } } IoFuture<Connection> realFuture; try { realFuture = endpoint.connect(uri); } catch (IOException e) { realFuture = new FailedIoFuture<>(e); } splice(futureResult, realFuture); final IoFuture<Connection> ioFuture = futureResult.getIoFuture(); ioFuture.addNotifier(HANDLER, this); return ioFuture; }
void splice(FutureResult<Connection> futureResult, IoFuture<Connection> realFuture) { // always add in this order futureResult.addCancelHandler(realFuture); realFuture.addNotifier(IoUtils.resultNotifier(), futureResult); }