summaryrefslogtreecommitdiff
path: root/opendc-simulator
diff options
context:
space:
mode:
Diffstat (limited to 'opendc-simulator')
-rw-r--r--opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/impl/SimResourceInterpreterImpl.kt66
1 files changed, 43 insertions, 23 deletions
diff --git a/opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/impl/SimResourceInterpreterImpl.kt b/opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/impl/SimResourceInterpreterImpl.kt
index cb0d6160..6dd02ae5 100644
--- a/opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/impl/SimResourceInterpreterImpl.kt
+++ b/opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/impl/SimResourceInterpreterImpl.kt
@@ -48,12 +48,12 @@ internal class SimResourceInterpreterImpl(private val context: CoroutineContext,
/**
* The queue of resource updates that are scheduled for immediate execution.
*/
- private val queue = ArrayDeque<Update>()
+ private val queue = ArrayDeque<SimResourceContextImpl>()
/**
* A priority queue containing the resource updates to be scheduled in the future.
*/
- private val futureQueue = PriorityQueue<Update>()
+ private val futureQueue = PriorityQueue<Update>(compareBy { it.timestamp })
/**
* The stack of interpreter invocations to occur in the future.
@@ -83,7 +83,7 @@ internal class SimResourceInterpreterImpl(private val context: CoroutineContext,
* re-computed. In case no interpreter is currently active, the interpreter will be started.
*/
fun scheduleImmediate(ctx: SimResourceContextImpl) {
- queue.add(Update(ctx, Long.MIN_VALUE))
+ queue.add(ctx)
// In-case the interpreter is already running in the call-stack, return immediately. The changes will be picked
// up by the active interpreter.
@@ -137,7 +137,7 @@ internal class SimResourceInterpreterImpl(private val context: CoroutineContext,
require(timestamp >= now) { "Timestamp must be in the future" }
- val update = Update(ctx, timestamp)
+ val update = allocUpdate(ctx, timestamp)
futureQueue.add(update)
// Optimization: Check if we need to push the interruption forward. Note that we check by timer reference.
@@ -193,9 +193,16 @@ internal class SimResourceInterpreterImpl(private val context: CoroutineContext,
futureQueue.poll()
- if (update(now) && visited.add(update.ctx)) {
- collectAncestors(update.ctx, visited)
+ val shouldExecute = !update.isCancelled && update.ctx.requiresUpdate(now)
+ if (shouldExecute) {
+ update.ctx.doUpdate(now)
+
+ if (visited.add(update.ctx)) {
+ collectAncestors(update.ctx, visited)
+ }
}
+
+ updatePool.add(update)
}
// Repeat execution of all immediate updates until the system has converged to a steady-state
@@ -203,9 +210,15 @@ internal class SimResourceInterpreterImpl(private val context: CoroutineContext,
do {
// Execute all immediate updates
while (true) {
- val update = queue.poll() ?: break
- if (update(now) && visited.add(update.ctx)) {
- collectAncestors(update.ctx, visited)
+ val ctx = queue.poll() ?: break
+ val shouldExecute = ctx.requiresUpdate(now)
+
+ if (shouldExecute) {
+ ctx.doUpdate(now)
+
+ if (visited.add(ctx)) {
+ collectAncestors(ctx, visited)
+ }
}
}
@@ -278,6 +291,26 @@ internal class SimResourceInterpreterImpl(private val context: CoroutineContext,
}
/**
+ * The pool of existing updates.
+ */
+ private val updatePool = ArrayDeque<Update>()
+
+ /**
+ * Allocate an [Update] object.
+ */
+ private fun allocUpdate(ctx: SimResourceContextImpl, timestamp: Long): Update {
+ val update = updatePool.poll()
+ return if (update != null) {
+ update.ctx = ctx
+ update.timestamp = timestamp
+ update.isCancelled = false
+ update
+ } else {
+ Update(ctx, timestamp)
+ }
+ }
+
+ /**
* A future interpreter invocation.
*
* This class is used to keep track of the future scheduler invocations created using the [Delay] instance. In case
@@ -299,7 +332,7 @@ internal class SimResourceInterpreterImpl(private val context: CoroutineContext,
* This class represents an update in the future at [timestamp] requested by [ctx]. A deferred update might be
* cancelled if the resource context was invalidated in the meantime.
*/
- class Update(@JvmField val ctx: SimResourceContextImpl, @JvmField val timestamp: Long) : Comparable<Update> {
+ class Update(@JvmField var ctx: SimResourceContextImpl, @JvmField var timestamp: Long) {
/**
* A flag to indicate that the task has been cancelled.
*/
@@ -313,19 +346,6 @@ internal class SimResourceInterpreterImpl(private val context: CoroutineContext,
isCancelled = true
}
- /**
- * Immediately run update.
- */
- operator fun invoke(timestamp: Long): Boolean {
- val shouldExecute = !isCancelled && ctx.requiresUpdate(timestamp)
- if (shouldExecute) {
- ctx.doUpdate(timestamp)
- }
- return shouldExecute
- }
-
- override fun compareTo(other: Update): Int = timestamp.compareTo(other.timestamp)
-
override fun toString(): String = "Update[ctx=$ctx,timestamp=$timestamp]"
}
}