@@ -179,7 +179,9 @@ internal actual class UndispatchedCoroutine<in T>actual constructor (
179
179
* // and it also calls saveThreadContext and clearThreadContext
180
180
* }
181
181
*/
182
- private var threadStateToRecover = ThreadLocal <Pair <CoroutineContext , Any ?>>()
182
+ private val threadStateToRecover = ThreadLocal <Pair <CoroutineContext , Any ?>>()
183
+ @Volatile
184
+ private var threadLocalIsSet = false // Better than nullable thread-local for easier debugging
183
185
184
186
init {
185
187
/*
@@ -213,11 +215,12 @@ internal actual class UndispatchedCoroutine<in T>actual constructor (
213
215
}
214
216
215
217
fun saveThreadContext (context : CoroutineContext , oldValue : Any? ) {
218
+ threadLocalIsSet = true // Specify that thread-local is touched at all
216
219
threadStateToRecover.set(context to oldValue)
217
220
}
218
221
219
222
fun clearThreadContext (): Boolean {
220
- if (threadStateToRecover.get() == null ) {
223
+ if (threadLocalIsSet && threadStateToRecover.get() == null ) {
221
224
threadStateToRecover.remove()
222
225
return false
223
226
}
@@ -226,10 +229,12 @@ internal actual class UndispatchedCoroutine<in T>actual constructor (
226
229
}
227
230
228
231
override fun afterResume (state : Any? ) {
229
- threadStateToRecover.get()?.let { (ctx, value) ->
230
- restoreThreadContext(ctx, value)
232
+ if (threadLocalIsSet) {
233
+ threadStateToRecover.get()?.let { (ctx, value) ->
234
+ restoreThreadContext(ctx, value)
235
+ }
236
+ threadStateToRecover.remove()
231
237
}
232
- threadStateToRecover.remove()
233
238
// resume undispatched -- update context but stay on the same dispatcher
234
239
val result = recoverResult(state, uCont)
235
240
withContinuationContext(uCont, null ) {
0 commit comments