@@ -640,6 +640,7 @@ internal open class JobSupport constructor(active: Boolean) : Job, SelectClause0
640640 private fun tryMakeCancelling (expect : Incomplete , list : NodeList , cause : Throwable ? ): Boolean {
641641 val cancelled = Cancelled (this , cause)
642642 if (! _state .compareAndSet(expect, Finishing (list, cancelled, false ))) return false
643+ onFinishingInternal(cancelled)
643644 onCancellationInternal(cancelled)
644645 // Materialize cause
645646 notifyCancellation(list, cancelled.cause)
@@ -678,10 +679,10 @@ internal open class JobSupport constructor(active: Boolean) : Job, SelectClause0
678679 if (state is Finishing && state.completing)
679680 return COMPLETING_ALREADY_COMPLETING
680681 val child: ChildJob ? = firstChild(state) ? : // or else complete immediately w/o children
681- if (tryFinalizeState(state, proposedUpdate, mode)) {
682- return COMPLETING_COMPLETED
683- } else {
684- return @loopOnState // retry
682+ when {
683+ state !is Finishing && hasOnFinishingHandler(proposedUpdate) -> null // unless it has onFinishing handler
684+ tryFinalizeState(state, proposedUpdate, mode) -> return COMPLETING_COMPLETED
685+ else -> return @loopOnState
685686 }
686687 val list = state.list ? : // must promote to list to correctly operate on child lists
687688 when (state) {
@@ -703,6 +704,7 @@ internal open class JobSupport constructor(active: Boolean) : Job, SelectClause0
703704 val completing = Finishing (list, cancelled, true )
704705 if (_state .compareAndSet(state, completing)) {
705706 (state as ? Finishing )?.transferExceptions(completing)
707+ if (state !is Finishing ) onFinishingInternal(proposedUpdate)
706708 if (child != null && tryWaitForChild(child, proposedUpdate))
707709 return COMPLETING_WAITING_CHILDREN
708710 if (tryFinalizeState(completing, proposedUpdate, mode = MODE_ATOMIC_DEFAULT ))
@@ -798,6 +800,17 @@ internal open class JobSupport constructor(active: Boolean) : Job, SelectClause0
798800 // TODO rename to "onCancelling"
799801 }
800802
803+ /* *
804+ * Whether job has [onFinishingInternal] handler for given [update]
805+ * @suppress **This is unstable API and it is subject to change.**
806+ */
807+ internal open fun hasOnFinishingHandler (update : Any? ) = false
808+
809+ /* *
810+ * @suppress **This is unstable API and it is subject to change.**
811+ */
812+ internal open fun onFinishingInternal (update : Any? ) {}
813+
801814 /* *
802815 * Method which is invoked once Job becomes [Cancelled] or [CompletedExceptionally].
803816 * It's guaranteed that at the moment of invocation the job and all its children are complete.
0 commit comments