summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFabian Mastenbroek <mail.fabianm@gmail.com>2019-05-08 11:42:05 +0200
committerFabian Mastenbroek <mail.fabianm@gmail.com>2019-05-14 12:55:56 +0200
commit1f77d1011577c54e98ad0cbbd898817f98000881 (patch)
tree8ee70617f9fa7234f7b78d5056e59677979adc5e
parent791aa01938aef966ff3c0f2cd31d2aebdccddb6f (diff)
feat: Add support for spawning anonymous children
This change adds support for spawning anonymous children in an ActorContext. This means a name does not have to be specified when spawning an actor.
-rw-r--r--odcsim-core/src/main/kotlin/com/atlarge/odcsim/ActorContext.kt8
-rw-r--r--odcsim-core/src/main/kotlin/com/atlarge/odcsim/coroutines/Behavior.kt2
-rw-r--r--odcsim-core/src/main/kotlin/com/atlarge/odcsim/internal/Coroutines.kt2
-rw-r--r--odcsim-core/src/test/kotlin/com/atlarge/odcsim/CoroutinesTest.kt2
-rw-r--r--odcsim-engine-omega/src/main/kotlin/com/atlarge/odcsim/engine/omega/OmegaActorSystem.kt12
-rw-r--r--odcsim-engine-tests/src/main/kotlin/com/atlarge/odcsim/engine/tests/ActorSystemContract.kt1
-rw-r--r--odcsim-testkit/src/main/kotlin/com/atlarge/odcsim/testkit/internal/ActorContextStub.kt5
7 files changed, 28 insertions, 4 deletions
diff --git a/odcsim-core/src/main/kotlin/com/atlarge/odcsim/ActorContext.kt b/odcsim-core/src/main/kotlin/com/atlarge/odcsim/ActorContext.kt
index 8ea4a09d..499e7df0 100644
--- a/odcsim-core/src/main/kotlin/com/atlarge/odcsim/ActorContext.kt
+++ b/odcsim-core/src/main/kotlin/com/atlarge/odcsim/ActorContext.kt
@@ -76,6 +76,14 @@ interface ActorContext<T : Any> {
fun <U : Any> spawn(behavior: Behavior<U>, name: String): ActorRef<U>
/**
+ * Spawn an anonymous child actor from the given [Behavior].
+ *
+ * @param behavior The behavior of the child actor to spawn.
+ * @return A reference to the child that has/will be spawned.
+ */
+ fun <U : Any> spawnAnonymous(behavior: Behavior<U>): ActorRef<U>
+
+ /**
* Request the specified child actor to be stopped in asynchronous fashion.
*
* @param child The reference to the child actor to stop.
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 b963cdb6..eb26add1 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
@@ -32,8 +32,8 @@ import com.atlarge.odcsim.internal.SuspendingActorContextImpl
import com.atlarge.odcsim.internal.SuspendingBehaviorImpl
import kotlin.coroutines.Continuation
import kotlin.coroutines.CoroutineContext
-import kotlin.coroutines.suspendCoroutine
import kotlin.coroutines.intrinsics.suspendCoroutineUninterceptedOrReturn
+import kotlin.coroutines.suspendCoroutine
/**
* A [Behavior] that allows method calls to suspend execution via Kotlin coroutines.
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 a9e20d0e..13e722fc 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
@@ -105,6 +105,8 @@ internal class SuspendingBehaviorImpl<T : Any>(
override fun <U : Any> spawn(behavior: Behavior<U>, name: String) = actorContext.spawn(behavior, name)
+ override fun <U : Any> spawnAnonymous(behavior: Behavior<U>) = actorContext.spawnAnonymous(behavior)
+
override fun stop(child: ActorRef<*>): Boolean = actorContext.stop(child)
override fun watch(target: ActorRef<*>) = actorContext.watch(target)
diff --git a/odcsim-core/src/test/kotlin/com/atlarge/odcsim/CoroutinesTest.kt b/odcsim-core/src/test/kotlin/com/atlarge/odcsim/CoroutinesTest.kt
index d6bf6a74..98486149 100644
--- a/odcsim-core/src/test/kotlin/com/atlarge/odcsim/CoroutinesTest.kt
+++ b/odcsim-core/src/test/kotlin/com/atlarge/odcsim/CoroutinesTest.kt
@@ -24,8 +24,8 @@
package com.atlarge.odcsim
-import com.atlarge.odcsim.coroutines.suspending
import com.atlarge.odcsim.coroutines.SuspendingBehavior
+import com.atlarge.odcsim.coroutines.suspending
import com.atlarge.odcsim.internal.BehaviorInterpreter
import com.atlarge.odcsim.internal.EmptyBehavior
import com.nhaarman.mockitokotlin2.mock
diff --git a/odcsim-engine-omega/src/main/kotlin/com/atlarge/odcsim/engine/omega/OmegaActorSystem.kt b/odcsim-engine-omega/src/main/kotlin/com/atlarge/odcsim/engine/omega/OmegaActorSystem.kt
index 8930fb96..37b5395f 100644
--- a/odcsim-engine-omega/src/main/kotlin/com/atlarge/odcsim/engine/omega/OmegaActorSystem.kt
+++ b/odcsim-engine-omega/src/main/kotlin/com/atlarge/odcsim/engine/omega/OmegaActorSystem.kt
@@ -38,10 +38,10 @@ import com.atlarge.odcsim.Signal
import com.atlarge.odcsim.Terminated
import com.atlarge.odcsim.internal.BehaviorInterpreter
import com.atlarge.odcsim.internal.logging.LoggerImpl
-import com.sun.xml.internal.messaging.saaj.soap.impl.EnvelopeImpl
import org.slf4j.Logger
import java.util.Collections
import java.util.PriorityQueue
+import java.util.UUID
import java.util.WeakHashMap
import kotlin.math.max
@@ -155,6 +155,16 @@ class OmegaActorSystem<in T : Any>(root: Behavior<T>, override val name: String)
override fun <U : Any> send(ref: ActorRef<U>, msg: U, after: Duration) = schedule(ref, msg, after)
override fun <U : Any> spawn(behavior: Behavior<U>, name: String): ActorRef<U> {
+ require(!name.startsWith("$")) { "Name may not start with $-sign" }
+ return internalSpawn(behavior, name)
+ }
+
+ override fun <U : Any> spawnAnonymous(behavior: Behavior<U>): ActorRef<U> {
+ val name = "$" + UUID.randomUUID()
+ return internalSpawn(behavior, name)
+ }
+
+ private fun <U : Any> internalSpawn(behavior: Behavior<U>, name: String): ActorRef<U> {
val ref = ActorRefImpl<U>(this@OmegaActorSystem, self.path.child(name))
if (ref.path !in registry) {
val actor = Actor(ref, behavior)
diff --git a/odcsim-engine-tests/src/main/kotlin/com/atlarge/odcsim/engine/tests/ActorSystemContract.kt b/odcsim-engine-tests/src/main/kotlin/com/atlarge/odcsim/engine/tests/ActorSystemContract.kt
index 867e7c11..e7639db8 100644
--- a/odcsim-engine-tests/src/main/kotlin/com/atlarge/odcsim/engine/tests/ActorSystemContract.kt
+++ b/odcsim-engine-tests/src/main/kotlin/com/atlarge/odcsim/engine/tests/ActorSystemContract.kt
@@ -29,7 +29,6 @@ import com.atlarge.odcsim.ActorRef
import com.atlarge.odcsim.ActorSystemFactory
import com.atlarge.odcsim.Behavior
import com.atlarge.odcsim.Terminated
-import com.atlarge.odcsim.coroutines.dsl.timeout
import com.atlarge.odcsim.coroutines.suspending
import com.atlarge.odcsim.empty
import com.atlarge.odcsim.ignore
diff --git a/odcsim-testkit/src/main/kotlin/com/atlarge/odcsim/testkit/internal/ActorContextStub.kt b/odcsim-testkit/src/main/kotlin/com/atlarge/odcsim/testkit/internal/ActorContextStub.kt
index 047e4c70..7035b908 100644
--- a/odcsim-testkit/src/main/kotlin/com/atlarge/odcsim/testkit/internal/ActorContextStub.kt
+++ b/odcsim-testkit/src/main/kotlin/com/atlarge/odcsim/testkit/internal/ActorContextStub.kt
@@ -32,6 +32,7 @@ import com.atlarge.odcsim.Duration
import com.atlarge.odcsim.Instant
import com.atlarge.odcsim.internal.logging.LoggerImpl
import org.slf4j.Logger
+import java.util.UUID
/**
* A stubbed [ActorContext] implementation for synchronous behavior testing.
@@ -72,6 +73,10 @@ internal class ActorContextStub<T : Any>(private val owner: BehaviorTestKitImpl<
return btk.ref
}
+ override fun <U : Any> spawnAnonymous(behavior: Behavior<U>): ActorRef<U> {
+ return spawn(behavior, "$" + UUID.randomUUID())
+ }
+
override fun stop(child: ActorRef<*>): Boolean {
if (child.path.parent != self.path) {
// This is not a child of this actor