-
Notifications
You must be signed in to change notification settings - Fork 41
/
RealityShowPhilosophers.scala
92 lines (79 loc) · 2.64 KB
/
RealityShowPhilosophers.scala
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
/* scala-stm - (c) 2009-2011, Stanford University, PPL */
package scala.concurrent.stm
package examples
import annotation.tailrec
/** This extends a solution to the dining philosopher's problem to include an
* outside perspective that occasionally examines everything that is
* happening.
*/
object RealityShowPhilosophers {
class Fork {
val owner = Ref(None : Option[String])
}
class PhilosopherThread(val name: String, val meals: Int, left: Fork, right: Fork) extends Thread {
val mealsEaten = Ref(0)
override def run() {
for (m <- 0 until meals) {
// thinking
atomic { implicit txn =>
if (!(left.owner().isEmpty && right.owner().isEmpty))
retry
left.owner() = Some(name)
right.owner() = Some(name)
}
// eating
atomic { implicit txn =>
mealsEaten += 1
left.owner() = None
right.owner() = None
}
}
}
def done = mealsEaten.single() == meals
override def toString = {
"%s is %5.2f%% done".format(name, mealsEaten.single() * 100.0 / meals)
}
}
class CameraThread(intervalMilli: Int, forks: Seq[Fork], philosophers: Seq[PhilosopherThread]) extends Thread {
@tailrec final override def run() {
Thread.sleep(intervalMilli)
val (str, done) = image
println(str)
if (!done)
run()
}
/** We want to print exactly one image of the final state, so we check
* completion at the same time as building the image.
*/
def image: (String, Boolean) = atomic { implicit txn =>
val buf = new StringBuilder
for (i <- 0 until forks.length)
buf ++= "fork %d is owned by %s\n".format(i, forks(i).owner.single())
var done = true
for (p <- philosophers) {
buf ++= p.toString += '\n'
done &&= p.done
}
(buf.toString, done)
}
}
def time(names: Seq[String], meals: Int): Long = {
val forks = Array.tabulate(names.size) { _ => new Fork }
val pthreads = Array.tabulate(names.size) { i => new PhilosopherThread(names(i), meals, forks(i), forks((i + 1) % forks.length)) }
val camera = new CameraThread(1000 / 60, forks, pthreads)
val start = System.currentTimeMillis
camera.start()
for (t <- pthreads) t.start()
for (t <- pthreads) t.join()
val elapsed = System.currentTimeMillis - start
camera.join()
elapsed
}
def main(args: Array[String]) {
val meals = 100000
for (p <- 0 until 3) {
val elapsed = time(List("Aristotle", "Hippocrates", "Plato", "Pythagoras", "Socrates"), meals)
printf("%3.1f usec/meal\n", (elapsed * 1000.0) / meals)
}
}
}