beschde lösung

This commit is contained in:
2022-09-29 15:46:00 +02:00
parent d3aa16361b
commit 72abf3267c

View File

@@ -0,0 +1,123 @@
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock
class Fork(id: String) : Observable<String?>(id) {
//TODO
// --------------- EDIT CODE BELOW ---------------
val lock = Mutex()
suspend fun take(philosopher: String) = lock.withLock {
setOccupiedBy(philosopher)
}
suspend fun release() {
setOccupiedBy(null)
}
// --------------- EDIT CODE ABOVE ---------------
private suspend fun setOccupiedBy(philosopher: String?) {
delay(5L)
onChange(philosopher)
occupiedBy = philosopher
}
private var occupiedBy: String? = null
fun available() = occupiedBy == null
}
class Philosopher(
id: String,
private val leftFork: Fork,
private val rightFork: Fork,
) : Observable<String>(id) {
//TODO
// --------------- EDIT CODE BELOW ---------------
suspend fun start() = repeat(10) {
think()
takeForks()
eat()
releaseForks()
}.also { changeState("FINISHED") }
private suspend fun takeForks() {
while (!forksavailable()) {
wait()
}
leftFork.take(id)
rightFork.take(id)
}
private fun forksavailable() : Boolean {
return leftFork.available() && rightFork.available()
}
private suspend fun releaseForks() {
leftFork.release()
rightFork.release()
}
// --------------- EDIT CODE ABOVE ---------------
private suspend fun wait() {
delay(1)
}
private suspend fun eat() {
changeState("EATING")
delay((0L..10L).random())
}
private suspend fun think() {
changeState("THINKING")
delay((0L..10L).random())
changeState("HUNGRY")
}
private suspend fun changeState(state: String) {
onChange(state)
this.state = state
}
private var state = "THINKING"
}
open class Observable<T>(val id: String) {
var onChange: suspend (String, T) -> Unit = { _, _ -> }
protected suspend fun onChange(state: T) = onChange(id, state)
}
suspend fun main(args: Array<String>) = runBlocking {
val number = 5
val forks = Array(number) { Fork("Fork$it") }
val philosophers = Array(number) { index ->
Philosopher(
id = "Philosopher$index",
leftFork = forks[index],
rightFork = forks[(index + 1) % number]
)
}
philosophers.forEach {
it.onChange = { philosopher, state ->
println("$philosopher is now $state")
}
}
forks.forEach {
it.onChange = { fork, philosopher ->
println(philosopher?.let { "$fork acquired by $it" } ?: "$fork released")
}
}
philosophers.forEach {
launch { it.start() }
}
}