diff options
| -rw-r--r-- | odcsim-core/src/main/kotlin/com/atlarge/odcsim/coroutines/Behavior.kt | 13 | ||||
| -rw-r--r-- | odcsim-core/src/main/kotlin/com/atlarge/odcsim/internal/Coroutines.kt | 23 |
2 files changed, 15 insertions, 21 deletions
diff --git a/odcsim-core/src/main/kotlin/com/atlarge/odcsim/coroutines/Behavior.kt b/odcsim-core/src/main/kotlin/com/atlarge/odcsim/coroutines/Behavior.kt index 4951d619..20aab232 100644 --- a/odcsim-core/src/main/kotlin/com/atlarge/odcsim/coroutines/Behavior.kt +++ b/odcsim-core/src/main/kotlin/com/atlarge/odcsim/coroutines/Behavior.kt @@ -28,9 +28,10 @@ import com.atlarge.odcsim.ActorContext import com.atlarge.odcsim.Behavior import com.atlarge.odcsim.DeferredBehavior import com.atlarge.odcsim.Signal -import com.atlarge.odcsim.internal.SuspendingBehaviorContext +import com.atlarge.odcsim.internal.SuspendingActorContextImpl import com.atlarge.odcsim.internal.SuspendingBehaviorImpl import kotlin.coroutines.Continuation +import kotlin.coroutines.CoroutineContext import kotlin.coroutines.suspendCoroutine /** @@ -65,7 +66,7 @@ fun <T : Any> Behavior.Companion.suspending(block: suspend (SuspendingActorConte * * @param T The shape of the messages the actor accepts. */ -interface SuspendingActorContext<T : Any> : ActorContext<T> { +interface SuspendingActorContext<T : Any> : ActorContext<T>, CoroutineContext.Element { /** * Suspend execution of the active coroutine to wait for a message of type [T] to be received in the actor's * mailbox. During suspension, incoming signals will be marked unhandled. @@ -81,6 +82,12 @@ interface SuspendingActorContext<T : Any> : ActorContext<T> { * @return The [Signal] that has been received. */ suspend fun receiveSignal(): Signal + + /** + * A key to provide access to the untyped [SuspendingActorContext] via [CoroutineContext] for suspending methods + * running inside a [SuspendingBehavior]. + */ + companion object Key : CoroutineContext.Key<SuspendingActorContext<*>> } /** @@ -91,7 +98,7 @@ interface SuspendingActorContext<T : Any> : ActorContext<T> { suspend fun <T : Any, U> suspendWithBehavior(block: (Continuation<U>, () -> Behavior<T>) -> Behavior<T>): U = suspendCoroutine { cont -> @Suppress("UNCHECKED_CAST") - val ctx = cont.context[SuspendingBehaviorContext] as? SuspendingBehaviorContext<T> + val ctx = cont.context[SuspendingActorContext] as? SuspendingActorContextImpl<T> ?: throw UnsupportedOperationException("Coroutine does not run inside SuspendingBehavior") ctx.become(block(cont) { ctx.behavior }) } diff --git a/odcsim-core/src/main/kotlin/com/atlarge/odcsim/internal/Coroutines.kt b/odcsim-core/src/main/kotlin/com/atlarge/odcsim/internal/Coroutines.kt index d8c3e8fc..7f2d39bc 100644 --- a/odcsim-core/src/main/kotlin/com/atlarge/odcsim/internal/Coroutines.kt +++ b/odcsim-core/src/main/kotlin/com/atlarge/odcsim/internal/Coroutines.kt @@ -41,15 +41,10 @@ import kotlin.coroutines.resume import kotlin.coroutines.startCoroutine /** - * The interface that is exposed from the [CoroutineContext] and provides control over the [SuspendingBehavior] - * instance. + * This interface exposes internal functionality provided by [SuspendingBehaviorImpl] on [SuspendingActorContext] to + * control the active behavior of the coroutine. */ -interface SuspendingBehaviorContext<T : Any> : CoroutineContext.Element { - /** - * The [ActorContext] in which the actor currently runs. - */ - val context: SuspendingActorContext<T> - +interface SuspendingActorContextImpl<T : Any> : SuspendingActorContext<T> { /** * The current active behavior */ @@ -61,12 +56,6 @@ interface SuspendingBehaviorContext<T : Any> : CoroutineContext.Element { * @param next The behavior to replace the current behavior with. */ fun become(next: Behavior<T>) - - /** - * This key provides users access to an untyped actor context in case the coroutine runs inside a - * [SuspendingBehavior]. - */ - companion object Key : CoroutineContext.Key<SuspendingBehaviorContext<*>> } /** @@ -75,7 +64,7 @@ interface SuspendingBehaviorContext<T : Any> : CoroutineContext.Element { * This implementation uses the fact that each actor is thread-safe (as it processes its mailbox sequentially). */ internal class SuspendingBehaviorImpl<T : Any>(actorContext: ActorContext<T>, initialBehavior: SuspendingBehavior<T>) : - ReceivingBehavior<T>(), SuspendingActorContext<T>, SuspendingBehaviorContext<T> { + ReceivingBehavior<T>(), SuspendingActorContextImpl<T> { /** * The next behavior to use. */ @@ -128,15 +117,13 @@ internal class SuspendingBehaviorImpl<T : Any>(actorContext: ActorContext<T>, in } } - override val context: SuspendingActorContext<T> get() = this - override val behavior: Behavior<T> get() = interpreter.behavior override fun become(next: Behavior<T>) { interpreter.become(actorContext, next) } - override val key: CoroutineContext.Key<*> = SuspendingBehaviorContext.Key + override val key: CoroutineContext.Key<*> = SuspendingActorContext.Key /** * Start the suspending behavior. |
