Created
November 10, 2011 19:01
-
-
Save rschildmeijer/1355775 to your computer and use it in GitHub Desktop.
Deferred
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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