com.koushikdutta.async.future.Continuation Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of androidasync Show documentation
Show all versions of androidasync Show documentation
Asynchronous socket, http(s) (client+server) and websocket library for android. Based on nio, not threads.
package com.koushikdutta.async.future;
import com.koushikdutta.async.callback.CompletedCallback;
import com.koushikdutta.async.callback.ContinuationCallback;
import java.util.LinkedList;
public class Continuation extends SimpleCancellable implements ContinuationCallback, Runnable, Cancellable {
CompletedCallback callback;
Runnable cancelCallback;
public CompletedCallback getCallback() {
return callback;
}
public void setCallback(CompletedCallback callback) {
this.callback = callback;
}
public Runnable getCancelCallback() {
return cancelCallback;
}
public void setCancelCallback(Runnable cancelCallback) {
this.cancelCallback = cancelCallback;
}
public void setCancelCallback(final Cancellable cancel) {
if (cancel == null) {
this.cancelCallback = null;
return;
}
this.cancelCallback = new Runnable() {
@Override
public void run() {
cancel.cancel();
}
};
}
public Continuation() {
this(null);
}
public Continuation(CompletedCallback callback) {
this(callback, null);
}
public Continuation(CompletedCallback callback, Runnable cancelCallback) {
this.cancelCallback = cancelCallback;
this.callback = callback;
}
private CompletedCallback wrap() {
return new CompletedCallback() {
boolean mThisCompleted;
@Override
public void onCompleted(Exception ex) {
// onCompleted may be called more than once... buggy code.
// only accept the first (timeouts, etc)
if (mThisCompleted)
return;
mThisCompleted = true;
assert waiting;
waiting = false;
if (ex == null) {
next();
return;
}
reportCompleted(ex);
}
};
}
void reportCompleted(Exception ex) {
if (!setComplete())
return;
if (callback != null)
callback.onCompleted(ex);
}
LinkedList mCallbacks = new LinkedList();
private ContinuationCallback hook(ContinuationCallback callback) {
if (callback instanceof DependentCancellable) {
DependentCancellable child = (DependentCancellable)callback;
child.setParent(this);
}
return callback;
}
public Continuation add(ContinuationCallback callback) {
mCallbacks.add(hook(callback));
return this;
}
public Continuation insert(ContinuationCallback callback) {
mCallbacks.add(0, hook(callback));
return this;
}
public void add(final DependentFuture future) {
future.setParent(this);
add(new ContinuationCallback() {
@Override
public void onContinue(Continuation continuation, CompletedCallback next) throws Exception {
future.get();
next.onCompleted(null);
}
});
}
private boolean inNext;
private boolean waiting;
private void next() {
if (inNext)
return;
while (mCallbacks.size() > 0 && !waiting && !isDone() && !isCancelled()) {
ContinuationCallback cb = mCallbacks.remove();
try {
inNext = true;
waiting = true;
cb.onContinue(this, wrap());
}
catch (Exception e) {
reportCompleted(e);
}
finally {
inNext = false;
}
}
if (waiting)
return;
if (isDone())
return;
if (isCancelled())
return;
reportCompleted(null);
}
@Override
public boolean cancel() {
if (!super.cancel())
return false;
if (cancelCallback != null)
cancelCallback.run();
return true;
}
boolean started;
public Continuation start() {
if (started)
throw new IllegalStateException("already started");
started = true;
next();
return this;
}
@Override
public void onContinue(Continuation continuation, CompletedCallback next) throws Exception {
setCallback(next);
start();
}
@Override
public void run() {
start();
}
}