beschde lösung
This commit is contained in:
123
SteveToggiTim/DiningPhilosophers.kt
Normal file
123
SteveToggiTim/DiningPhilosophers.kt
Normal 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() }
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user