Skip to content

Commit 80c1235

Browse files
committed
Optimization: don't wait on a Deferred already in State.DONE.
When a Callback returned a Deferred already in State.DONE, the current Deferred was paused and immediately resumed, which involved the creation of an unnecessary Continue callback and other objects. We now bypass this entire code path, which helps in the cases where a Callback returns a Deferred built with Deferred.fromResult or Deferred.fromError, or if a real Deferred completes so quickly that we directly see it in State.DONE. Change-Id: I710266e05b5f37d676018f706c923ecafa276ffc
1 parent ce70924 commit 80c1235

File tree

1 file changed

+11
-0
lines changed

1 file changed

+11
-0
lines changed

src/Deferred.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1143,6 +1143,17 @@ private void handleContinuation(final Deferred d, final Callback cb) {
11431143
+ ", the result returned was the same Deferred object. This is illegal"
11441144
+ ", a Deferred can't run itself recursively. Something is wrong.");
11451145
}
1146+
// Optimization: if `d' is already DONE, instead of calling
1147+
// adding a callback on `d' to continue when `d' completes,
1148+
// we atomically read the result off of `d' immediately. To
1149+
// do this safely, we need to change `d's state momentarily.
1150+
if (d.casState(State.DONE, State.RUNNING)) {
1151+
result = d.result; // No one will change `d.result' now.
1152+
d.state = State.DONE;
1153+
runCallbacks();
1154+
return;
1155+
}
1156+
11461157
// Our `state' was either RUNNING or DONE.
11471158
// If it was RUNNING, we have to suspend the callback chain here and
11481159
// resume when the result of that other Deferred is available.

0 commit comments

Comments
 (0)