diff options
3 files changed, 79 insertions, 81 deletions
diff --git a/opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/SimResourceAggregatorMaxMin.kt b/opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/SimResourceAggregatorMaxMin.kt index c39c1aca..991cda7a 100644 --- a/opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/SimResourceAggregatorMaxMin.kt +++ b/opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/SimResourceAggregatorMaxMin.kt @@ -45,7 +45,7 @@ public class SimResourceAggregatorMaxMin( val command = if (grantedWork > 0.0 && grantedSpeed > 0.0) SimResourceCommand.Consume(grantedWork, grantedSpeed, deadline) else - SimResourceCommand.Idle(deadline) + SimResourceCommand.Idle() input.push(command) } } diff --git a/opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/SimResourceDistributorMaxMin.kt b/opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/SimResourceDistributorMaxMin.kt index f7c5c5d7..d8fc8cb6 100644 --- a/opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/SimResourceDistributorMaxMin.kt +++ b/opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/SimResourceDistributorMaxMin.kt @@ -65,7 +65,7 @@ public class SimResourceDistributorMaxMin( /* SimResourceConsumer */ override fun onNext(ctx: SimResourceContext): SimResourceCommand { - return doNext(ctx.capacity) + return doNext(ctx) } override fun onEvent(ctx: SimResourceContext, event: SimResourceEvent) { @@ -94,12 +94,13 @@ public class SimResourceDistributorMaxMin( /** * Schedule the work of the outputs. */ - private fun doNext(capacity: Double): SimResourceCommand { + private fun doNext(ctx: SimResourceContext): SimResourceCommand { // If there is no work yet, mark the input as idle. if (activeOutputs.isEmpty()) { return SimResourceCommand.Idle() } + val capacity = ctx.capacity var duration: Double = Double.MAX_VALUE var deadline: Long = Long.MAX_VALUE var availableSpeed = capacity @@ -112,7 +113,7 @@ public class SimResourceDistributorMaxMin( output.pull() // Remove outputs that have finished - if (output.isFinished) { + if (!output.isActive) { outputIterator.remove() } } @@ -125,33 +126,23 @@ public class SimResourceDistributorMaxMin( var remaining = activeOutputs.size for (output in activeOutputs) { val availableShare = availableSpeed / remaining-- + val grantedSpeed = min(output.allowedSpeed, availableShare) + deadline = min(deadline, output.deadline) - when (val command = output.activeCommand) { - is SimResourceCommand.Idle -> { - deadline = min(deadline, command.deadline) - output.actualSpeed = 0.0 - } - is SimResourceCommand.Consume -> { - val grantedSpeed = min(output.allowedSpeed, availableShare) - deadline = min(deadline, command.deadline) - - // Ignore idle computation - if (grantedSpeed <= 0.0 || command.work <= 0.0) { - output.actualSpeed = 0.0 - continue - } + // Ignore idle computation + if (grantedSpeed <= 0.0 || output.work <= 0.0) { + output.actualSpeed = 0.0 + continue + } - totalRequestedSpeed += command.limit - totalRequestedWork += command.work + totalRequestedSpeed += output.limit + totalRequestedWork += output.work - output.actualSpeed = grantedSpeed - availableSpeed -= grantedSpeed + output.actualSpeed = grantedSpeed + availableSpeed -= grantedSpeed - // The duration that we want to run is that of the shortest request of an output - duration = min(duration, command.work / grantedSpeed) - } - SimResourceCommand.Exit -> assert(false) { "Did not expect output to be stopped" } - } + // The duration that we want to run is that of the shortest request of an output + duration = min(duration, output.work / grantedSpeed) } assert(deadline >= interpreter.clock.millis()) { "Deadline already passed" } @@ -189,9 +180,19 @@ public class SimResourceDistributorMaxMin( private var isClosed: Boolean = false /** - * The current command that is processed by the resource. + * The current requested work. + */ + var work: Double = 0.0 + + /** + * The requested limit. */ - var activeCommand: SimResourceCommand = SimResourceCommand.Idle() + var limit: Double = 0.0 + + /** + * The current deadline. + */ + var deadline: Long = Long.MAX_VALUE /** * The processing speed that is allowed by the model constraints. @@ -204,12 +205,6 @@ public class SimResourceDistributorMaxMin( var actualSpeed: Double = 0.0 /** - * A flag to indicate that the output is finished. - */ - val isFinished - get() = activeCommand is SimResourceCommand.Exit - - /** * The timestamp at which we received the last command. */ private var lastCommandTimestamp: Long = Long.MIN_VALUE @@ -238,15 +233,19 @@ public class SimResourceDistributorMaxMin( /* SimResourceProviderLogic */ override fun onIdle(ctx: SimResourceControllableContext, deadline: Long): Long { allowedSpeed = 0.0 - activeCommand = SimResourceCommand.Idle(deadline) + this.deadline = deadline + work = 0.0 + limit = 0.0 lastCommandTimestamp = ctx.clock.millis() return Long.MAX_VALUE } override fun onConsume(ctx: SimResourceControllableContext, work: Double, limit: Double, deadline: Long): Long { - allowedSpeed = ctx.speed - activeCommand = SimResourceCommand.Consume(work, limit, deadline) + allowedSpeed = min(ctx.capacity, limit) + this.work = work + this.limit = limit + this.deadline = deadline lastCommandTimestamp = ctx.clock.millis() return Long.MAX_VALUE @@ -257,7 +256,9 @@ public class SimResourceDistributorMaxMin( } override fun onFinish(ctx: SimResourceControllableContext) { - activeCommand = SimResourceCommand.Exit + work = 0.0 + limit = 0.0 + deadline = Long.MAX_VALUE lastCommandTimestamp = ctx.clock.millis() } diff --git a/opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/impl/SimResourceContextImpl.kt b/opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/impl/SimResourceContextImpl.kt index 5c3f95e8..90c7bc75 100644 --- a/opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/impl/SimResourceContextImpl.kt +++ b/opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/impl/SimResourceContextImpl.kt @@ -212,11 +212,15 @@ internal class SimResourceContextImpl( // 2. The resource capacity cannot satisfy the demand. // 3. The resource consumer should be interrupted (e.g., someone called .interrupt()) if ((isConsume && remainingWork == 0.0) || _deadline <= timestamp || isInterrupted) { - next(timestamp) + when (val command = consumer.onNext(this)) { + is SimResourceCommand.Idle -> interpretIdle(timestamp, command.deadline) + is SimResourceCommand.Consume -> interpretConsume(timestamp, command.work, command.limit, command.deadline) + is SimResourceCommand.Exit -> interpretExit() + } } else if (isConsume) { - interpret(SimResourceCommand.Consume(remainingWork, _limit, _deadline), timestamp) + interpretConsume(timestamp, remainingWork, _limit, _deadline) } else { - interpret(SimResourceCommand.Idle(_deadline), timestamp) + interpretIdle(timestamp, _deadline) } } } @@ -249,57 +253,50 @@ internal class SimResourceContextImpl( } /** - * Interpret the specified [SimResourceCommand] that was submitted by the resource consumer. + * Interpret the [SimResourceCommand.Consume] command. */ - private fun interpret(command: SimResourceCommand, now: Long): SimResourceState { - return when (command) { - is SimResourceCommand.Idle -> { - val deadline = command.deadline - - require(deadline >= now) { "Deadline already passed" } - - _speed = 0.0 - _work = 0.0 - _limit = 0.0 - _deadline = deadline + private fun interpretConsume(now: Long, work: Double, limit: Double, deadline: Long): SimResourceState { + require(deadline >= now) { "Deadline already passed" } - val timestamp = logic.onIdle(this, deadline) - scheduleUpdate(timestamp) + _speed = min(capacity, limit) + _work = work + _limit = limit + _deadline = deadline - SimResourceState.Active - } - is SimResourceCommand.Consume -> { - val work = command.work - val limit = command.limit - val deadline = command.deadline + val timestamp = logic.onConsume(this, work, limit, deadline) + scheduleUpdate(timestamp) - require(deadline >= now) { "Deadline already passed" } + return SimResourceState.Active + } - _speed = min(capacity, limit) - _work = work - _limit = limit - _deadline = deadline + /** + * Interpret the [SimResourceCommand.Idle] command. + */ + private fun interpretIdle(now: Long, deadline: Long): SimResourceState { + require(deadline >= now) { "Deadline already passed" } - val timestamp = logic.onConsume(this, work, limit, deadline) - scheduleUpdate(timestamp) + _speed = 0.0 + _work = 0.0 + _limit = 0.0 + _deadline = deadline - SimResourceState.Active - } - is SimResourceCommand.Exit -> { - _speed = 0.0 - _work = 0.0 - _limit = 0.0 - _deadline = Long.MAX_VALUE + val timestamp = logic.onIdle(this, deadline) + scheduleUpdate(timestamp) - SimResourceState.Stopped - } - } + return SimResourceState.Active } /** - * Request the workload for more work. + * Interpret the [SimResourceCommand.Exit] command. */ - private fun next(now: Long): SimResourceState = interpret(consumer.onNext(this), now) + private fun interpretExit(): SimResourceState { + _speed = 0.0 + _work = 0.0 + _limit = 0.0 + _deadline = Long.MAX_VALUE + + return SimResourceState.Stopped + } private var _remainingWork: Double = 0.0 private var _remainingWorkFlush: Long = Long.MIN_VALUE |
