summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--odcsim-core/src/main/kotlin/com/atlarge/odcsim/coroutines/Behavior.kt13
-rw-r--r--odcsim-core/src/main/kotlin/com/atlarge/odcsim/internal/Coroutines.kt23
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.