@@ -215,6 +215,12 @@ private[concurrent] object Promise {
215
215
override final def onComplete [U ](func : Try [T ] => U )(implicit executor : ExecutionContext ): Unit =
216
216
dispatchOrAddCallbacks(get(), new Transformation [T , Unit ](Xform_onComplete , func, executor))
217
217
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
+
218
224
override final def failed : Future [Throwable ] =
219
225
if (! get().isInstanceOf [Success [_]]) super .failed
220
226
else Future .failedFailureFuture // Cached instance in case of already known success
@@ -319,6 +325,15 @@ private[concurrent] object Promise {
319
325
p.dispatchOrAddCallbacks(p.get(), callbacks)
320
326
}
321
327
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
+
322
337
// IMPORTANT: Noop should never be passed in here, neither as left OR as right
323
338
@ tailrec private [this ] final def concatCallbacks (left : Callbacks [T ], right : Callbacks [T ]): Callbacks [T ] =
324
339
if (left.isInstanceOf [Transformation [T ,_]]) new ManyCallbacks [T ](left.asInstanceOf [Transformation [T ,_]], right)
@@ -327,6 +342,20 @@ private[concurrent] object Promise {
327
342
concatCallbacks(m.rest, new ManyCallbacks (m.first, right))
328
343
}
329
344
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
+
330
359
// IMPORTANT: Noop should not be passed in here, `callbacks` cannot be null
331
360
@ tailrec
332
361
private [this ] final def submitWithValue (callbacks : Callbacks [T ], resolved : Try [T ]): Unit =
0 commit comments