summaryrefslogtreecommitdiff
path: root/src/library/scala/concurrent/Promise.scala
diff options
context:
space:
mode:
authorViktor Klang <viktor.klang@gmail.com>2014-12-20 19:51:43 +0100
committerJason Zaugg <jzaugg@gmail.com>2015-02-04 14:04:05 +1000
commitbf20737faa2da5b45ad1ef5e6a43dff307c99788 (patch)
tree235f68bfa6b187f2e7d9ad12a84610bdec41c8f4 /src/library/scala/concurrent/Promise.scala
parentad0ddd4603e6ec134460491333444d505d376883 (diff)
downloadscala-bf20737faa2da5b45ad1ef5e6a43dff307c99788.tar.gz
scala-bf20737faa2da5b45ad1ef5e6a43dff307c99788.tar.bz2
scala-bf20737faa2da5b45ad1ef5e6a43dff307c99788.zip
SI-8689 Avoid internal error in Promise after sequence of completions
Calling `completeWith` when the `DefaultPromise` is already completed, leads to callbacks not being properly executed. This happened because `Future.InternalCallbackExecutor` extends `BatchingExecutor`[1] which assumes `unbatchedExecute` to be async, when in this case it is sync, and if there is an exception thrown by executing the batch, it creates a new batch with the remaining items from the current batch and submits that to `unbatchedExecute` and then rethrows, but if you have a sync `unbatchedExecute`, it will fail since it is not reentrant, as witnessed by the failed `require` as reported in this issue. This commit avoids problem by delegating `completeWith` to `tryComplete`, which has the effect of using `onComplete` + `tryComplete` i.s.o. `complete`, which means that when it fails (because of a benign race condition between completers) it won't throw an exception. It has been tested by the minimized reproducer. [1] Actually, in the 2.10.x branch where this patch is starting out, "The BatchingExecutor trait had to be inlined into InternalCallbackExecutor for binary compatibility.". This comment will be more literally correct in the context of 2.11.x and beyond
Diffstat (limited to 'src/library/scala/concurrent/Promise.scala')
-rw-r--r--src/library/scala/concurrent/Promise.scala7
1 files changed, 2 insertions, 5 deletions
diff --git a/src/library/scala/concurrent/Promise.scala b/src/library/scala/concurrent/Promise.scala
index 8355a73a1f..02253d4bd9 100644
--- a/src/library/scala/concurrent/Promise.scala
+++ b/src/library/scala/concurrent/Promise.scala
@@ -66,11 +66,8 @@ trait Promise[T] {
*
* @return This promise
*/
- final def completeWith(other: Future[T]): this.type = {
- other onComplete { this complete _ }
- this
- }
-
+ final def completeWith(other: Future[T]): this.type = tryCompleteWith(other)
+
/** Attempts to complete this promise with the specified future, once that future is completed.
*
* @return This promise