in src/jvm/main/org/jetbrains/kotlinx/lincheck/strategy/managed/modelchecking/ModelCheckingStrategy.kt [358:396]
fun chooseThread(iThread: Int): Int {
val availableThreads = availableThreads(iThread)
val nextThread = if (currentInterleavingPosition < threadSwitchChoices.size) {
// Use the predefined choice.
val nextThread = threadSwitchChoices[currentInterleavingPosition++]
// Update current node.
if (shouldMoveCurrentNode && !loopDetector.replayModeEnabled) {
currentInterleavingNode = currentInterleavingNode
.getChildNode(executionPosition)!!
.getChildNode(nextThread)!!
as SwitchChoosingNode
// we reached the next `SwitchChoosingNode` node, so mark it as initialized
currentInterleavingNode.initialize()
}
check(nextThread in availableThreads) {
"""
Trying to switch the execution to thread $nextThread,
but only the following threads are eligible to switch: $availableThreads
""".trimIndent()
}
nextThread
} else {
// There is no predefined choice.
// This can happen if there were forced thread switches after the last predefined one
// (e.g., thread end, coroutine suspension, acquiring an already acquired lock or monitor.wait).
// We use a deterministic random here to choose the next thread.
// end of tracked execution positions, so tell strategy not to generate switch points any further
shouldAddNewSwitchPoints = false
// in case no switchable thread available we return -1, this way
// the strategy will either report an error or stay on the calling
// thread if the switch was not mandatory
if (availableThreads.isEmpty()) -1
else availableThreads.random(interleavingFinishingRandom)
}
if (currentInterleavingPosition == threadSwitchChoices.size) {
shouldMoveCurrentNode = false
}
return nextThread
}