@@ -88,25 +88,52 @@ internal fun runEventLoop(eventLoop: EventLoop?, isCompleted: () -> Boolean) {
88
88
89
89
// --------------- Kotlin/Native specialization hooks ---------------
90
90
91
+ // just start
91
92
internal actual fun <T , R > startCoroutine (
92
93
start : CoroutineStart ,
93
94
receiver : R ,
94
95
completion : Continuation <T >,
95
96
block : suspend R .() -> T
97
+ ) =
98
+ startCoroutine(start, receiver, completion, block) {}
99
+
100
+ // initParentJob + startCoroutine
101
+ internal actual fun <T , R > startAbstractCoroutine (
102
+ start : CoroutineStart ,
103
+ receiver : R ,
104
+ coroutine : AbstractCoroutine <T >,
105
+ block : suspend R .() -> T
106
+ ) {
107
+ // See https://github.com/Kotlin/kotlinx.coroutines/issues/2064
108
+ // We shall do initParentJob only after freezing the block
109
+ startCoroutine(start, receiver, coroutine, block) {
110
+ coroutine.initParentJob()
111
+ }
112
+ }
113
+
114
+ private fun <T , R > startCoroutine (
115
+ start : CoroutineStart ,
116
+ receiver : R ,
117
+ completion : Continuation <T >,
118
+ block : suspend R .() -> T ,
119
+ initParentJobIfNeeded : () -> Unit
96
120
) {
97
121
val curThread = currentThread()
98
122
val newThread = completion.context[ContinuationInterceptor ].thread()
99
123
if (newThread != curThread) {
100
124
check(start != CoroutineStart .UNDISPATCHED ) {
101
125
" Cannot start an undispatched coroutine in another thread $newThread from current $curThread "
102
126
}
127
+ block.freeze() // freeze the block, safely get FreezingException if it cannot be frozen
128
+ initParentJobIfNeeded() // only initParentJob here if needed
103
129
if (start != CoroutineStart .LAZY ) {
104
130
newThread.execute {
105
131
startCoroutineImpl(start, receiver, completion, block)
106
132
}
107
133
}
108
134
return
109
135
}
136
+ initParentJobIfNeeded()
110
137
startCoroutineImpl(start, receiver, completion, block)
111
138
}
112
139
0 commit comments