@@ -25,7 +25,7 @@ class DelimContScope<R>(val f: suspend DelimitedScope<R>.() -> R) : DelimitedSco
25
25
/* *
26
26
* Variable used for polling the result after suspension happened.
27
27
*/
28
- private val resultVar = atomic<R ?>(null )
28
+ private val resultVar = atomic<Any ?>(EMPTY_VALUE )
29
29
30
30
/* *
31
31
* Variable for the next shift block to (partially) run, if it is empty that usually means we are done.
@@ -61,20 +61,20 @@ class DelimContScope<R>(val f: suspend DelimitedScope<R>.() -> R) : DelimitedSco
61
61
}
62
62
63
63
/* *
64
- * Captures the continuation and set [func ] with the continuation to be executed next by the runloop.
64
+ * Captures the continuation and set [f ] with the continuation to be executed next by the runloop.
65
65
*/
66
- override suspend fun <A > shift (func : suspend DelimitedScope <R >.(DelimitedContinuation <A , R >) -> R ): A =
66
+ override suspend fun <A > shift (f : suspend DelimitedScope <R >.(DelimitedContinuation <A , R >) -> R ): A =
67
67
suspendCoroutine { continueMain ->
68
68
val delCont = SingleShotCont (continueMain, shiftFnContinuations)
69
- assert (nextShift.compareAndSet(null , suspend { this .func (delCont) }))
69
+ assert (nextShift.compareAndSet(null , suspend { this .f (delCont) }))
70
70
}
71
71
72
72
/* *
73
73
* Same as [shift] except we never resume execution because we only continue in [c].
74
74
*/
75
- override suspend fun <A , B > shiftCPS (func : suspend (DelimitedContinuation <A , B >) -> R , c : suspend DelimitedScope <B >.(A ) -> B ): Nothing =
75
+ override suspend fun <A , B > shiftCPS (f : suspend (DelimitedContinuation <A , B >) -> R , c : suspend DelimitedScope <B >.(A ) -> B ): Nothing =
76
76
suspendCoroutine {
77
- assert (nextShift.compareAndSet(null , suspend { func (CPSCont (c)) }))
77
+ assert (nextShift.compareAndSet(null , suspend { f (CPSCont (c)) }))
78
78
}
79
79
80
80
/* *
@@ -83,22 +83,23 @@ class DelimContScope<R>(val f: suspend DelimitedScope<R>.() -> R) : DelimitedSco
83
83
override suspend fun <A > reset (f : suspend DelimitedScope <A >.() -> A ): A =
84
84
DelimContScope (f).invoke()
85
85
86
+ @Suppress(" UNCHECKED_CAST" )
86
87
fun invoke (): R {
87
88
f.startCoroutineUninterceptedOrReturn(this , Continuation (EmptyCoroutineContext ) { result ->
88
89
resultVar.value = result.getOrThrow()
89
90
}).let {
90
91
if (it == COROUTINE_SUSPENDED ) {
91
92
// we have a call to shift so we must start execution the blocks there
92
93
resultVar.loop { mRes ->
93
- if (mRes == null ) {
94
+ if (mRes == = EMPTY_VALUE ) {
94
95
val nextShiftFn = nextShift.getAndSet(null )
95
96
? : throw IllegalStateException (" No further work to do but also no result!" )
96
97
nextShiftFn.startCoroutineUninterceptedOrReturn(Continuation (EmptyCoroutineContext ) { result ->
97
98
resultVar.value = result.getOrThrow()
98
- }).let {
99
+ }).let { nextRes ->
99
100
// If we suspended here we can just continue to loop because we should now have a new function to run
100
101
// If we did not suspend we short-circuited and are thus done with looping
101
- if (it != COROUTINE_SUSPENDED ) resultVar.value = it as R
102
+ if (nextRes != COROUTINE_SUSPENDED ) resultVar.value = nextRes as R
102
103
}
103
104
// Break out of the infinite loop if we have a result
104
105
} else return @let
@@ -107,15 +108,18 @@ class DelimContScope<R>(val f: suspend DelimitedScope<R>.() -> R) : DelimitedSco
107
108
// we can return directly if we never suspended/called shift
108
109
else return @invoke it as R
109
110
}
110
- assert (resultVar.value != null )
111
+ assert (resultVar.value != = EMPTY_VALUE )
111
112
// We need to finish the partially evaluated shift blocks by passing them our result.
112
113
// This will update the result via the continuations that now finish up
113
- for (c in shiftFnContinuations.asReversed()) c.resume(resultVar.value!! )
114
+ for (c in shiftFnContinuations.asReversed()) c.resume(resultVar.value as R )
114
115
// Return the final result
115
- return resultVar.value!!
116
+ return resultVar.value as R
116
117
}
117
118
118
119
companion object {
119
120
fun <R > reset (f : suspend DelimitedScope <R >.() -> R ): R = DelimContScope (f).invoke()
121
+
122
+ @Suppress(" ClassName" )
123
+ private object EMPTY_VALUE
120
124
}
121
125
}
0 commit comments