diff options
| author | Fabian Mastenbroek <mail.fabianm@gmail.com> | 2021-06-20 22:56:33 +0200 |
|---|---|---|
| committer | Fabian Mastenbroek <mail.fabianm@gmail.com> | 2021-06-21 12:19:43 +0200 |
| commit | d54ac10449083a490e741d6c54e6f3aa07b71af0 (patch) | |
| tree | 64632acc289887610c8ccd39b4f0aec9515881ef /opendc-simulator/opendc-simulator-resources/src/main | |
| parent | 4b9559ce78e1853600c816f8228205ddf405c5a2 (diff) | |
simulator: Remove concept of resource lifecycle
This change removes the AutoCloseable interface from the
SimResourceProvider and removes the concept of a resource lifecycle.
Instead, resource providers are now either active (running a resource
consumer) or in-active (being idle), which simplifies implementation.
Diffstat (limited to 'opendc-simulator/opendc-simulator-resources/src/main')
10 files changed, 87 insertions, 77 deletions
diff --git a/opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/SimAbstractResourceAggregator.kt b/opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/SimAbstractResourceAggregator.kt index 5fe7d7bb..84217278 100644 --- a/opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/SimAbstractResourceAggregator.kt +++ b/opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/SimAbstractResourceAggregator.kt @@ -56,8 +56,6 @@ public abstract class SimAbstractResourceAggregator( /* SimResourceAggregator */ override fun addInput(input: SimResourceProvider) { - check(state != SimResourceState.Stopped) { "Aggregator has been stopped" } - val consumer = Consumer() _inputs.add(input) _inputConsumers.add(consumer) @@ -70,8 +68,8 @@ public abstract class SimAbstractResourceAggregator( private val _inputConsumers = mutableListOf<Consumer>() /* SimResourceProvider */ - override val state: SimResourceState - get() = _output.state + override val isActive: Boolean + get() = _output.isActive override val capacity: Double get() = _output.capacity @@ -97,10 +95,6 @@ public abstract class SimAbstractResourceAggregator( _output.interrupt() } - override fun close() { - _output.close() - } - private val _output = object : SimAbstractResourceProvider(interpreter, parent, initialCapacity = 0.0) { override fun createLogic(): SimResourceProviderLogic { return object : SimResourceProviderLogic { diff --git a/opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/SimAbstractResourceProvider.kt b/opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/SimAbstractResourceProvider.kt index de26f99e..c1b1450e 100644 --- a/opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/SimAbstractResourceProvider.kt +++ b/opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/SimAbstractResourceProvider.kt @@ -33,6 +33,12 @@ public abstract class SimAbstractResourceProvider( initialCapacity: Double ) : SimResourceProvider { /** + * A flag to indicate that the resource provider is active. + */ + public override val isActive: Boolean + get() = ctx != null + + /** * The capacity of the resource. */ public override var capacity: Double = initialCapacity @@ -67,12 +73,6 @@ public abstract class SimAbstractResourceProvider( private set /** - * The state of the resource provider. - */ - final override var state: SimResourceState = SimResourceState.Pending - private set - - /** * Construct the [SimResourceProviderLogic] instance for a new consumer. */ protected abstract fun createLogic(): SimResourceProviderLogic @@ -96,21 +96,15 @@ public abstract class SimAbstractResourceProvider( } final override fun startConsumer(consumer: SimResourceConsumer) { - check(state == SimResourceState.Pending) { "Resource is in invalid state" } + check(ctx == null) { "Resource is in invalid state" } val ctx = interpreter.newContext(consumer, createLogic(), parent) ctx.capacity = capacity this.ctx = ctx - this.state = SimResourceState.Active start(ctx) } - override fun close() { - cancel() - state = SimResourceState.Stopped - } - final override fun interrupt() { ctx?.interrupt() } @@ -121,10 +115,6 @@ public abstract class SimAbstractResourceProvider( this.ctx = null ctx.close() } - - if (state != SimResourceState.Stopped) { - state = SimResourceState.Pending - } } override fun toString(): String = "SimAbstractResourceProvider[capacity=$capacity]" diff --git a/opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/SimResourceCloseableProvider.kt b/opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/SimResourceCloseableProvider.kt new file mode 100644 index 00000000..bce8274b --- /dev/null +++ b/opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/SimResourceCloseableProvider.kt @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2021 AtLarge Research + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package org.opendc.simulator.resources + +/** + * A [SimResourceProvider] that has a controllable and limited lifetime. + * + * This interface is used to signal that the resource provider may be closed and not reused after that point. + */ +public interface SimResourceCloseableProvider : SimResourceProvider, AutoCloseable { + /** + * End the lifetime of the resource provider. + * + * This operation cancels the existing resource consumer and prevents the resource provider from being reused. + */ + public override fun close() +} diff --git a/opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/SimResourceDistributor.kt b/opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/SimResourceDistributor.kt index e0333ff9..6bfbfc99 100644 --- a/opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/SimResourceDistributor.kt +++ b/opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/SimResourceDistributor.kt @@ -29,10 +29,10 @@ public interface SimResourceDistributor : SimResourceConsumer { /** * The output resource providers to which resource consumers can be attached. */ - public val outputs: Set<SimResourceProvider> + public val outputs: Set<SimResourceCloseableProvider> /** * Create a new output for the distributor. */ - public fun newOutput(): SimResourceProvider + public fun newOutput(): SimResourceCloseableProvider } 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 be9e89fb..f7c5c5d7 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 @@ -32,7 +32,7 @@ public class SimResourceDistributorMaxMin( private val interpreter: SimResourceInterpreter, private val parent: SimResourceSystem? = null ) : SimResourceDistributor { - override val outputs: Set<SimResourceProvider> + override val outputs: Set<SimResourceCloseableProvider> get() = _outputs private val _outputs = mutableSetOf<Output>() @@ -57,7 +57,7 @@ public class SimResourceDistributorMaxMin( private var totalAllocatedSpeed = 0.0 /* SimResourceDistributor */ - override fun newOutput(): SimResourceProvider { + override fun newOutput(): SimResourceCloseableProvider { val provider = Output(ctx?.capacity ?: 0.0) _outputs.add(provider) return provider @@ -178,7 +178,16 @@ public class SimResourceDistributorMaxMin( /** * An internal [SimResourceProvider] implementation for switch outputs. */ - private inner class Output(capacity: Double) : SimAbstractResourceProvider(interpreter, parent, capacity), SimResourceProviderLogic, Comparable<Output> { + private inner class Output(capacity: Double) : + SimAbstractResourceProvider(interpreter, parent, capacity), + SimResourceCloseableProvider, + SimResourceProviderLogic, + Comparable<Output> { + /** + * A flag to indicate that the output is closed. + */ + private var isClosed: Boolean = false + /** * The current command that is processed by the resource. */ @@ -209,6 +218,8 @@ public class SimResourceDistributorMaxMin( override fun createLogic(): SimResourceProviderLogic = this override fun start(ctx: SimResourceControllableContext) { + check(!isClosed) { "Cannot re-use closed output" } + activeOutputs += this interpreter.batch { @@ -219,13 +230,9 @@ public class SimResourceDistributorMaxMin( } override fun close() { - val state = state - - super.close() - - if (state != SimResourceState.Stopped) { - _outputs.remove(this) - } + isClosed = true + cancel() + _outputs.remove(this) } /* SimResourceProviderLogic */ diff --git a/opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/SimResourceProvider.kt b/opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/SimResourceProvider.kt index f709ca17..b68b7261 100644 --- a/opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/SimResourceProvider.kt +++ b/opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/SimResourceProvider.kt @@ -29,11 +29,11 @@ import kotlin.coroutines.resumeWithException /** * A [SimResourceProvider] provides a resource that can be consumed by a [SimResourceConsumer]. */ -public interface SimResourceProvider : AutoCloseable { +public interface SimResourceProvider { /** - * The state of the resource. + * A flag to indicate that the resource provider is currently being consumed by a [SimResourceConsumer]. */ - public val state: SimResourceState + public val isActive: Boolean /** * The resource capacity available at this instant. @@ -71,13 +71,6 @@ public interface SimResourceProvider : AutoCloseable { * Cancel the current resource consumer. If there is no consumer active, this operation will be a no-op. */ public fun cancel() - - /** - * End the lifetime of the resource. - * - * This operation terminates the existing resource consumer. - */ - public override fun close() } /** diff --git a/opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/SimResourceSwitch.kt b/opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/SimResourceSwitch.kt index e224285e..f6e7b22f 100644 --- a/opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/SimResourceSwitch.kt +++ b/opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/SimResourceSwitch.kt @@ -29,7 +29,7 @@ public interface SimResourceSwitch : AutoCloseable { /** * The output resource providers to which resource consumers can be attached. */ - public val outputs: Set<SimResourceProvider> + public val outputs: Set<SimResourceCloseableProvider> /** * The input resources that will be switched between the output providers. @@ -44,7 +44,7 @@ public interface SimResourceSwitch : AutoCloseable { /** * Create a new output on the switch. */ - public fun newOutput(): SimResourceProvider + public fun newOutput(): SimResourceCloseableProvider /** * Add the specified [input] to the switch. diff --git a/opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/SimResourceSwitchExclusive.kt b/opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/SimResourceSwitchExclusive.kt index 2950af80..4ff741ed 100644 --- a/opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/SimResourceSwitchExclusive.kt +++ b/opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/SimResourceSwitchExclusive.kt @@ -35,7 +35,7 @@ public class SimResourceSwitchExclusive : SimResourceSwitch { private var isClosed: Boolean = false private val _outputs = mutableSetOf<Provider>() - override val outputs: Set<SimResourceProvider> + override val outputs: Set<SimResourceCloseableProvider> get() = _outputs private val availableResources = ArrayDeque<SimResourceTransformer>() @@ -61,7 +61,7 @@ public class SimResourceSwitchExclusive : SimResourceSwitch { override fun toString(): String = "SimResourceCounters[demand=$demand,actual=$actual,overcommit=$overcommit]" } - override fun newOutput(): SimResourceProvider { + override fun newOutput(): SimResourceCloseableProvider { check(!isClosed) { "Switch has been closed" } check(availableResources.isNotEmpty()) { "No capacity to serve request" } val forwarder = availableResources.poll() @@ -101,7 +101,7 @@ public class SimResourceSwitchExclusive : SimResourceSwitch { _inputs.forEach(SimResourceProvider::cancel) } - private inner class Provider(private val forwarder: SimResourceTransformer) : SimResourceProvider by forwarder { + private inner class Provider(private val forwarder: SimResourceTransformer) : SimResourceCloseableProvider, SimResourceProvider by forwarder { override fun close() { // We explicitly do not close the forwarder here in order to re-use it across output resources. _outputs -= this diff --git a/opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/SimResourceSwitchMaxMin.kt b/opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/SimResourceSwitchMaxMin.kt index 684a1b52..50d58798 100644 --- a/opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/SimResourceSwitchMaxMin.kt +++ b/opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/SimResourceSwitchMaxMin.kt @@ -33,7 +33,7 @@ public class SimResourceSwitchMaxMin( /** * The output resource providers to which resource consumers can be attached. */ - override val outputs: Set<SimResourceProvider> + override val outputs: Set<SimResourceCloseableProvider> get() = distributor.outputs /** @@ -70,7 +70,7 @@ public class SimResourceSwitchMaxMin( /** * Add an output to the switch. */ - override fun newOutput(): SimResourceProvider { + override fun newOutput(): SimResourceCloseableProvider { check(!isClosed) { "Switch has been closed" } return distributor.newOutput() @@ -88,7 +88,7 @@ public class SimResourceSwitchMaxMin( override fun close() { if (!isClosed) { isClosed = true - aggregator.close() + aggregator.cancel() } } } diff --git a/opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/SimResourceTransformer.kt b/opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/SimResourceTransformer.kt index fd3d1230..cec27e1c 100644 --- a/opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/SimResourceTransformer.kt +++ b/opendc-simulator/opendc-simulator-resources/src/main/kotlin/org/opendc/simulator/resources/SimResourceTransformer.kt @@ -33,7 +33,7 @@ import org.opendc.simulator.resources.impl.SimResourceCountersImpl public class SimResourceTransformer( private val isCoupled: Boolean = false, private val transform: (SimResourceContext, SimResourceCommand) -> SimResourceCommand -) : SimResourceFlow { +) : SimResourceFlow, AutoCloseable { /** * The [SimResourceContext] in which the forwarder runs. */ @@ -49,11 +49,8 @@ public class SimResourceTransformer( */ private var hasDelegateStarted: Boolean = false - /** - * The state of the forwarder. - */ - override var state: SimResourceState = SimResourceState.Pending - private set + override val isActive: Boolean + get() = delegate != null override val capacity: Double get() = ctx?.capacity ?: 0.0 @@ -69,9 +66,8 @@ public class SimResourceTransformer( private val _counters = SimResourceCountersImpl() override fun startConsumer(consumer: SimResourceConsumer) { - check(state == SimResourceState.Pending) { "Resource is in invalid state" } + check(delegate == null) { "Resource transformer already active" } - state = SimResourceState.Active delegate = consumer // Interrupt the provider to replace the consumer @@ -86,19 +82,18 @@ public class SimResourceTransformer( val delegate = delegate val ctx = ctx - state = SimResourceState.Pending - - if (delegate != null && ctx != null) { + if (delegate != null) { this.delegate = null - delegate.onEvent(ctx, SimResourceEvent.Exit) + + if (ctx != null) { + delegate.onEvent(ctx, SimResourceEvent.Exit) + } } } override fun close() { val ctx = ctx - state = SimResourceState.Stopped - if (ctx != null) { this.ctx = null ctx.interrupt() @@ -114,9 +109,7 @@ public class SimResourceTransformer( updateCounters(ctx) - return if (state == SimResourceState.Stopped) { - SimResourceCommand.Exit - } else if (delegate != null) { + return if (delegate != null) { val command = transform(ctx, delegate.onNext(ctx)) _work = if (command is SimResourceCommand.Consume) command.work else 0.0 @@ -128,7 +121,7 @@ public class SimResourceTransformer( delegate.onEvent(ctx, SimResourceEvent.Exit) - if (isCoupled || state == SimResourceState.Stopped) + if (isCoupled) SimResourceCommand.Exit else onNext(ctx) @@ -184,10 +177,6 @@ public class SimResourceTransformer( private fun reset() { delegate = null hasDelegateStarted = false - - if (state != SimResourceState.Stopped) { - state = SimResourceState.Pending - } } /** |
