Skip to content

Instantly share code, notes, and snippets.

@rschildmeijer
Created November 10, 2011 19:01
Show Gist options
  • Save rschildmeijer/1355775 to your computer and use it in GitHub Desktop.
Save rschildmeijer/1355775 to your computer and use it in GitHub Desktop.
Deferred
public class Deferred<T> {
private boolean fired = false;
private Object consequence = null;
private final List<AsyncResult<T>> callbacks = Lists.newLinkedList();
public void addCallbacks(AsyncResult<T> callback) {
callbacks.add(callback);
if (fired && callbacks.size() == 1) {
// Fire callback immediately
if (consequence instanceof Exception) {
invokeErrbacks((Exception) consequence);
} else if (consequence instanceof Deferred) {
// TODO
} else
invokeCallbacks((T) consequence);
}
}
public void callback(T result) {
if (fired) {
// Throw AlreadyFiredException
}
fired = true;
invokeCallbacks(result);
}
public void errback(Exception failure) {
if (fired) {
// Throw AlreadyFiredException
}
fired = true;
invokeErrbacks(failure);
}
private void invokeCallbacks(T result) {
consequence = result; // Exception, T or Deferred
Iterator<AsyncResult<T>> iter = callbacks.iterator();
while (iter.hasNext()) {
try {
consequence = iter.next().onSuccess((T) consequence); // returns Exception, T or Deferred
if (consequence instanceof Deferred) {
chain((Deferred) consequence);
break;
} else if (consequence instanceof Exception) {
break;
}
} catch (Exception e) {
consequence = e;
break;
} finally {
iter.remove();
}
}
if (consequence instanceof Exception) {
invokeErrbacks((Exception) consequence);
}
}
private void invokeErrbacks(Exception failure) {
consequence = failure; // Exception, T or Deferred
Iterator<AsyncResult<T>> iter = callbacks.iterator();
while (iter.hasNext()) {
try {
consequence = iter.next().onFailure((Exception) consequence); // returns Exception, T or Deferred
if (consequence instanceof Deferred) {
chain((Deferred) consequence);
break;
} else if (!(consequence instanceof Exception)) {
break;
}
} catch (Exception e) {
consequence = e;
} finally {
iter.remove();
}
}
if (!(consequence instanceof Exception) && !(consequence instanceof Deferred)) {
invokeCallbacks((T) consequence);
}
}
private void chain(Deferred<T> d) {
d.addCallbacks(new AsyncResult<T>() {
@Override
public Object onFailure(Throwable caught) {
invokeErrbacks((Exception) caught);
return caught;
}
@Override
public Object onSuccess(T result) {
invokeCallbacks(result);
return result;
}
});
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment