Skip to content

Commit 6e7dc21

Browse files
multunKhoyo
authored andcommitted
core: introduce a switch initialization policy
This initialization policy replaces the default switch configuration: - switches do not all have a default configuration - we may need to make pessimistic or optimistic assumptions, depending on the context
1 parent 73abb49 commit 6e7dc21

File tree

9 files changed

+31
-25
lines changed

9 files changed

+31
-25
lines changed

core/kt-osrd-sim-infra/src/main/kotlin/fr/sncf/osrd/sim_infra/api/SimInfra.kt

-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ interface MovableElementsInfra {
2222
val movableElements: StaticIdxSpace<MovableElement>
2323
fun getMovableElementConfigs(movableElement: MovableElementId): StaticIdxSpace<MovableElementConfig>
2424
fun getMovableElementDelay(movableElement: MovableElementId): Duration
25-
fun getMovableElementDefaultConfig(movableElement: MovableElementId): MovableElementConfigId
2625
fun getMovableElementConfigName(movableElement: MovableElementId, config: MovableElementConfigId): String
2726
}
2827

core/kt-osrd-sim-infra/src/main/kotlin/fr/sncf/osrd/sim_infra/impl/SimInfraBuilder.kt

+2-5
Original file line numberDiff line numberDiff line change
@@ -8,16 +8,13 @@ import kotlin.time.Duration
88
class MovableElementDescriptorBuilder @PublishedApi internal constructor (
99
private val delay: Duration,
1010
private val configs: StaticPool<MovableElementConfig, MovableElementConfigDescriptor>,
11-
var defaultConfig: MovableElementConfigId?
1211
) {
1312
fun config(name: String): MovableElementConfigId {
1413
return configs.add(MovableElementConfigDescriptor(name))
1514
}
1615

1716
@PublishedApi internal fun build(): MovableElementDescriptor {
18-
if (defaultConfig == null)
19-
throw RuntimeException("invalid MovableElement: there must be a default config")
20-
return MovableElementDescriptor(delay, configs, defaultConfig!!)
17+
return MovableElementDescriptor(delay, configs)
2118
}
2219
}
2320

@@ -43,7 +40,7 @@ class SimInfraBuilder @PublishedApi internal constructor(
4340
)
4441

4542
inline fun movableElement(delay: Duration, init: MovableElementDescriptorBuilder.() -> Unit): MovableElementId {
46-
val movableElementBuilder = MovableElementDescriptorBuilder(delay, StaticPool(), null)
43+
val movableElementBuilder = MovableElementDescriptorBuilder(delay, StaticPool())
4744
movableElementBuilder.init()
4845
val movableElement = movableElementBuilder.build()
4946
return movableElementPool.add(movableElement)

core/kt-osrd-sim-infra/src/main/kotlin/fr/sncf/osrd/sim_infra/impl/SimInfraImpl.kt

-5
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ value class MovableElementConfigDescriptor(val name: String)
1111
class MovableElementDescriptor(
1212
val delay: Duration,
1313
val configs: StaticPool<MovableElementConfig, MovableElementConfigDescriptor>,
14-
val defaultConfig: StaticIdx<MovableElementConfig>
1514
)
1615

1716
@JvmInline
@@ -66,10 +65,6 @@ class SimInfraImpl(
6665
return movableElementPool[movableElement].delay
6766
}
6867

69-
override fun getMovableElementDefaultConfig(movableElement: MovableElementId): MovableElementConfigId {
70-
return movableElementPool[movableElement].defaultConfig
71-
}
72-
7368
override fun getMovableElementConfigName(
7469
movableElement: MovableElementId,
7570
config: MovableElementConfigId

core/kt-osrd-sim-interlocking/src/main/kotlin/fr/sncf/osrd/sim/interlocking/InterlockingSim.kt

+7-1
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,14 @@ import kotlin.contracts.contract
99

1010
// region MOVABLE ELEMENTS
1111

12+
/** Defines how movable elements are initialized */
13+
enum class MovableElementInitPolicy {
14+
OPTIMISTIC,
15+
PESSIMISTIC,
16+
}
17+
1218
interface MovableElementSim {
13-
fun watchMovableElement(movable: MovableElementId): StateFlow<MovableElementConfigId>
19+
fun watchMovableElement(movable: MovableElementId): StateFlow<MovableElementConfigId?>
1420
suspend fun move(movable: MovableElementId, config: MovableElementConfigId)
1521
suspend fun lockMovableElement(movable: MovableElementId)
1622
suspend fun unlockMovableElement(movable: MovableElementId)

core/kt-osrd-sim-interlocking/src/main/kotlin/fr/sncf/osrd/sim/interlocking/impl/MovableElements.kt

+14-7
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package fr.sncf.osrd.sim.interlocking.impl
22

33
import fr.sncf.osrd.sim_infra.api.*
4+
import fr.sncf.osrd.sim.interlocking.api.MovableElementInitPolicy
45
import fr.sncf.osrd.sim.interlocking.api.MovableElementSim
56
import fr.sncf.osrd.utils.indexing.get
67
import kotlinx.coroutines.delay
@@ -10,18 +11,21 @@ import kotlinx.coroutines.flow.update
1011
import kotlinx.coroutines.sync.Mutex
1112

1213

13-
fun movableElementSim(infra: MovableElementsInfra): MovableElementSim {
14-
return MovableElementSimImpl(infra)
14+
fun movableElementSim(infra: MovableElementsInfra, initPolicy: MovableElementInitPolicy): MovableElementSim {
15+
return MovableElementSimImpl(infra, initPolicy)
1516
}
1617

17-
internal class MovableElementSimImpl(private val infra: MovableElementsInfra) : MovableElementSim {
18-
private val states = infra.movableElements.map { id ->
19-
MutableStateFlow(infra.getMovableElementDefaultConfig(id))
18+
internal class MovableElementSimImpl(
19+
private val infra: MovableElementsInfra,
20+
private val initPolicy: MovableElementInitPolicy,
21+
) : MovableElementSim {
22+
private val states: List<MutableStateFlow<MovableElementConfigId?>> = infra.movableElements.map { id ->
23+
MutableStateFlow(null)
2024
}
2125

2226
private val locks = infra.movableElements.map { Mutex() }
2327

24-
override fun watchMovableElement(movable: MovableElementId): StateFlow<MovableElementConfigId> {
28+
override fun watchMovableElement(movable: MovableElementId): StateFlow<MovableElementConfigId?> {
2529
return states[movable.index]
2630
}
2731

@@ -32,7 +36,10 @@ internal class MovableElementSimImpl(private val infra: MovableElementsInfra) :
3236
override suspend fun move(movable: MovableElementId, config: MovableElementConfigId) {
3337
assert(locks[movable.index].isLocked) { "cannot move a non-locked movable element" }
3438
states[movable.index].update { prevConfig ->
35-
if (prevConfig != config)
39+
if (prevConfig == null) {
40+
if (initPolicy == MovableElementInitPolicy.PESSIMISTIC)
41+
delay(infra.getMovableElementDelay(movable))
42+
} else if (prevConfig != config)
3643
delay(infra.getMovableElementDelay(movable))
3744
config
3845
}

core/kt-osrd-sim-interlocking/src/test/kotlin/fr/sncf/osrd/sim/TestLocation.kt

+1-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ class TestLocation {
2020
val infra = simInfra {
2121
// create a test switch
2222
val switchA = movableElement(delay = 42L.milliseconds) {
23-
defaultConfig = config("a")
23+
config("a")
2424
config("b")
2525
}
2626

core/kt-osrd-sim-interlocking/src/test/kotlin/fr/sncf/osrd/sim/TestMovableElement.kt

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package fr.sncf.osrd.sim
22

3+
import fr.sncf.osrd.sim.interlocking.api.MovableElementInitPolicy
34
import fr.sncf.osrd.sim.interlocking.impl.MovableElementSimImpl
45
import fr.sncf.osrd.sim.interlocking.api.withLock
56
import fr.sncf.osrd.sim_infra.impl.simInfra
@@ -17,12 +18,12 @@ class TestMovableElements {
1718
// setup test data
1819
val infra = simInfra {
1920
movableElement(delay = 42L.milliseconds) {
20-
defaultConfig = config("a")
21+
config("a")
2122
config("b")
2223
}
2324
}
2425

25-
val sim = MovableElementSimImpl(infra)
26+
val sim = MovableElementSimImpl(infra, MovableElementInitPolicy.PESSIMISTIC)
2627
val movableElement = infra.movableElements[0]
2728
val configs = infra.getMovableElementConfigs(movableElement)
2829

core/kt-osrd-sim-interlocking/src/test/kotlin/fr/sncf/osrd/sim/TestReservation.kt

+1-1
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ class TestReservation {
3939
// region build the test infrastructure
4040
val builder = SimInfraBuilder()
4141
val switch = builder.movableElement(delay = 42L.milliseconds) {
42-
defaultConfig = config("a")
42+
config("a")
4343
config("b")
4444
}
4545

core/kt-osrd-sim-interlocking/src/test/kotlin/fr/sncf/osrd/sim/TestRouting.kt

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package fr.sncf.osrd.sim
22

33
import fr.sncf.osrd.sim.interlocking.api.Train
4+
import fr.sncf.osrd.sim.interlocking.api.MovableElementInitPolicy
45
import fr.sncf.osrd.sim.interlocking.impl.LocationSimImpl
56
import fr.sncf.osrd.sim.interlocking.impl.movableElementSim
67
import fr.sncf.osrd.sim.interlocking.impl.reservationSim
@@ -42,7 +43,7 @@ class TestRouting {
4243
val builder = SimInfraBuilder()
4344
// region switches
4445
val switch = builder.movableElement(delay = 10L.milliseconds) {
45-
defaultConfig = config("xy")
46+
config("xy")
4647
config("vy")
4748
}
4849

@@ -105,7 +106,7 @@ class TestRouting {
105106
val locationSim = LocationSimImpl(infra)
106107
val simJob = Job()
107108
val reservationScope = CoroutineScope(coroutineContext + simJob)
108-
val movableElementSim = movableElementSim(infra)
109+
val movableElementSim = movableElementSim(infra, MovableElementInitPolicy.OPTIMISTIC)
109110
val reservationSim = reservationSim(infra, locationSim, reservationScope)
110111
val routingSim = routingSim(infra, movableElementSim, reservationSim, reservationScope)
111112

0 commit comments

Comments
 (0)