@@ -1012,6 +1012,7 @@ internal actual open class JobSupport actual constructor(active: Boolean) : Job,
1012
1012
private fun tryMakeCancelling (expect : Incomplete , list : NodeList , cause : Throwable ? ): Boolean {
1013
1013
val cancelled = Cancelled (this , cause)
1014
1014
if (! _state .compareAndSet(expect, Finishing (list, cancelled, false ))) return false
1015
+ onFinishingInternal(cancelled)
1015
1016
onCancellationInternal(cancelled)
1016
1017
notifyCancellation(list, cause)
1017
1018
return true
@@ -1051,21 +1052,33 @@ internal actual open class JobSupport actual constructor(active: Boolean) : Job,
1051
1052
return COMPLETING_ALREADY_COMPLETING
1052
1053
if (state is Finishing && state.completing)
1053
1054
return COMPLETING_ALREADY_COMPLETING
1054
- val child: Child = firstChild(state) ? : // or else complete immediately w/o children
1055
- if (updateState(state, proposedUpdate, mode)) return COMPLETING_COMPLETED else return @loopOnState
1056
- // must promote to list to correct operate on child lists
1057
- if (state is JobNode <* >) {
1058
- promoteSingleToNodeList(state)
1059
- return @loopOnState // retry
1060
- }
1055
+ val child: Child ? = firstChild(state) ? : // or else complete immediately w/o children
1056
+ when {
1057
+ state !is Finishing && hasOnFinishingHandler(proposedUpdate) -> null // unless it has onFinishing handler
1058
+ updateState(state, proposedUpdate, mode) -> return COMPLETING_COMPLETED
1059
+ else -> return @loopOnState
1060
+ }
1061
+ val list = state.list ? : // must promote to list to correctly operate on child lists
1062
+ when (state) {
1063
+ is Empty -> {
1064
+ promoteEmptyToNodeList(state)
1065
+ return @loopOnState // retry
1066
+ }
1067
+ is JobNode <* > -> {
1068
+ promoteSingleToNodeList(state)
1069
+ return @loopOnState // retry
1070
+ }
1071
+ else -> error(" Unexpected state with an empty list: $state " )
1072
+ }
1061
1073
// cancel all children in list on exceptional completion
1062
1074
if (proposedUpdate is CompletedExceptionally )
1063
- child.cancelChildrenInternal(proposedUpdate.exception)
1075
+ child? .cancelChildrenInternal(proposedUpdate.exception)
1064
1076
// switch to completing state
1065
1077
val cancelled = (state as ? Finishing )?.cancelled ? : (proposedUpdate as ? Cancelled )
1066
- val completing = Finishing (state. list!! , cancelled, true )
1078
+ val completing = Finishing (list, cancelled, true )
1067
1079
if (_state .compareAndSet(state, completing)) {
1068
- if (tryWaitForChild(child, proposedUpdate))
1080
+ if (state !is Finishing ) onFinishingInternal(proposedUpdate)
1081
+ if (child != null && tryWaitForChild(child, proposedUpdate))
1069
1082
return COMPLETING_WAITING_CHILDREN
1070
1083
if (updateState(completing, proposedUpdate, mode = MODE_ATOMIC_DEFAULT ))
1071
1084
return COMPLETING_COMPLETED
@@ -1157,6 +1170,16 @@ internal actual open class JobSupport actual constructor(active: Boolean) : Job,
1157
1170
*/
1158
1171
internal actual open fun onCancellationInternal (exceptionally : CompletedExceptionally ? ) {}
1159
1172
1173
+ /* *
1174
+ * @suppress **This is unstable API and it is subject to change.**
1175
+ */
1176
+ internal actual open fun hasOnFinishingHandler (update : Any? ) = false
1177
+
1178
+ /* *
1179
+ * @suppress **This is unstable API and it is subject to change.**
1180
+ */
1181
+ internal actual open fun onFinishingInternal (update : Any? ) {}
1182
+
1160
1183
/* *
1161
1184
* Override for post-completion actions that need to do something with the state.
1162
1185
* @param mode completion mode.
0 commit comments