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