@@ -215,6 +215,12 @@ private[concurrent] object Promise {
215215 override final def onComplete [U ](func : Try [T ] => U )(implicit executor : ExecutionContext ): Unit =
216216 dispatchOrAddCallbacks(get(), new Transformation [T , Unit ](Xform_onComplete , func, executor))
217217
218+ override private [concurrent] final def onCompleteWithUnregister [U ](func : Try [T ] => U )(implicit executor : ExecutionContext ): () => Unit = {
219+ val t = new Transformation [T , Unit ](Xform_onComplete , func, executor)
220+ dispatchOrAddCallbacks(get(), t)
221+ () => unregisterCallback(t)
222+ }
223+
218224 override final def failed : Future [Throwable ] =
219225 if (! get().isInstanceOf [Success [_]]) super .failed
220226 else Future .failedFailureFuture // Cached instance in case of already known success
@@ -319,6 +325,15 @@ private[concurrent] object Promise {
319325 p.dispatchOrAddCallbacks(p.get(), callbacks)
320326 }
321327
328+ @ tailrec private def unregisterCallback (t : Transformation [_, _]): Unit = {
329+ val state = get()
330+ if (state eq t) {
331+ if (! compareAndSet(state, Noop )) unregisterCallback(t)
332+ } else if (state.isInstanceOf [ManyCallbacks [_]]) {
333+ if (! compareAndSet(state, removeCallback(state.asInstanceOf [ManyCallbacks [T ]], t))) unregisterCallback(t)
334+ }
335+ }
336+
322337 // IMPORTANT: Noop should never be passed in here, neither as left OR as right
323338 @ tailrec private [this ] final def concatCallbacks (left : Callbacks [T ], right : Callbacks [T ]): Callbacks [T ] =
324339 if (left.isInstanceOf [Transformation [T ,_]]) new ManyCallbacks [T ](left.asInstanceOf [Transformation [T ,_]], right)
@@ -327,6 +342,20 @@ private[concurrent] object Promise {
327342 concatCallbacks(m.rest, new ManyCallbacks (m.first, right))
328343 }
329344
345+ @ tailrec private [this ] final def removeCallback (cs : Callbacks [T ], t : Transformation [_, _], result : Callbacks [T ] = null ): AnyRef =
346+ if (cs eq t) {
347+ if (result == null ) Noop
348+ else result
349+ }
350+ else if (cs.isInstanceOf [ManyCallbacks [_]]) {
351+ val m = cs.asInstanceOf [ManyCallbacks [T ]]
352+ if (m.first eq t) {
353+ if (result == null ) m.rest
354+ else concatCallbacks(m.rest, result)
355+ }
356+ else removeCallback(m.rest, t, if (result == null ) m.first else new ManyCallbacks (m.first, result))
357+ } else cs
358+
330359 // IMPORTANT: Noop should not be passed in here, `callbacks` cannot be null
331360 @ tailrec
332361 private [this ] final def submitWithValue (callbacks : Callbacks [T ], resolved : Try [T ]): Unit =
0 commit comments