June 2018 Update
This commit is contained in:
parent
ba8067c3b7
commit
22f33d4004
5278 changed files with 84726 additions and 14379 deletions
|
|
@ -0,0 +1,49 @@
|
|||
(ql:quickload '(:stmx :bordeaux-threads))
|
||||
|
||||
(defpackage :dining-philosophers
|
||||
(:use :cl))
|
||||
|
||||
(in-package :dining-philosophers)
|
||||
|
||||
(defstruct philosopher
|
||||
name
|
||||
left-fork
|
||||
right-fork)
|
||||
|
||||
(defparameter *philosophers* '("Aristotle" "Kant" "Spinoza" "Marx" "Russell"))
|
||||
(defparameter *eating-max* 5.0)
|
||||
(defparameter *thinking-max* 5.0)
|
||||
(defvar *log-lock* (bt:make-lock))
|
||||
(defvar *running* nil)
|
||||
|
||||
(defun print-log (name status)
|
||||
(bt:with-lock-held (*log-lock*)
|
||||
(format t "~a is ~a~%" name status)))
|
||||
|
||||
(defun philosopher-cycle (philosopher)
|
||||
"Continously atomically grab and return the left and right forks of the given PHILOSOPHER."
|
||||
(with-slots (name left-fork right-fork) philosopher
|
||||
(loop while *running*
|
||||
do
|
||||
(print-log name "hungry")
|
||||
(stmx:atomic
|
||||
(stmx.util:take left-fork)
|
||||
(stmx.util:take right-fork))
|
||||
(print-log name "eating")
|
||||
(sleep (random *eating-max*))
|
||||
(stmx:atomic
|
||||
(stmx.util:put left-fork t)
|
||||
(stmx.util:put right-fork t))
|
||||
(print-log name "thinking")
|
||||
(sleep (random *thinking-max*)))))
|
||||
|
||||
(defun scenario ()
|
||||
(let ((forks (loop repeat (length *philosophers*) collect (stmx.util:tcell t))))
|
||||
(setf *running* t)
|
||||
(loop for name in *philosophers*
|
||||
for left-fork in forks
|
||||
for right-fork in (append (cdr forks) (list (car forks)))
|
||||
do (let ((philosopher (make-philosopher :name name :left-fork left-fork :right-fork right-fork)))
|
||||
(bt:make-thread (lambda () (philosopher-cycle philosopher))
|
||||
:initial-bindings (cons (cons '*standard-output* *standard-output*)
|
||||
bt:*default-special-bindings*))))))
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
DINING-PHILOSOPHERS> (scenario)
|
||||
Aristotle is hungry
|
||||
Aristotle is eating
|
||||
Kant is hungry
|
||||
Spinoza is hungry
|
||||
Spinoza is eating
|
||||
Marx is hungry
|
||||
NIL
|
||||
Russell is hungry
|
||||
Aristotle is thinking
|
||||
Russell is eating
|
||||
Spinoza is thinking
|
||||
Kant is eating
|
||||
Spinoza is hungry
|
||||
Russell is thinking
|
||||
Marx is eating
|
||||
Kant is thinking
|
||||
Aristotle is hungry
|
||||
Aristotle is eating
|
||||
Marx is thinking
|
||||
Spinoza is eating
|
||||
Spinoza is thinking
|
||||
Marx is hungry
|
||||
Marx is eating
|
||||
Russell is hungry
|
||||
Marx is thinking
|
||||
Kant is hungry
|
||||
Aristotle is thinking
|
||||
Russell is eating
|
||||
Kant is eating
|
||||
Marx is hungry
|
||||
Spinoza is hungry
|
||||
Kant is thinking
|
||||
Spinoza is eating
|
||||
Kant is hungry
|
||||
Aristotle is hungry
|
||||
Russell is thinking
|
||||
Aristotle is eating
|
||||
Aristotle is thinking
|
||||
Aristotle is hungry
|
||||
Aristotle is eating
|
||||
Spinoza is thinking
|
||||
Marx is eating
|
||||
...
|
||||
83
Task/Dining-philosophers/Julia/dining-philosophers.julia
Normal file
83
Task/Dining-philosophers/Julia/dining-philosophers.julia
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
mutable struct Philosopher
|
||||
name::String
|
||||
hungry::Bool
|
||||
righthanded::Bool
|
||||
rightforkheld::Channel
|
||||
leftforkheld::Channel
|
||||
function Philosopher(name, leftfork, rightfork)
|
||||
this = new()
|
||||
this.name = name
|
||||
this.hungry = rand([false, true]) # not specified so start as either
|
||||
this.righthanded = (name == "Aristotle") ? false : true
|
||||
this.leftforkheld = leftfork
|
||||
this.rightforkheld = rightfork
|
||||
this
|
||||
end
|
||||
end
|
||||
|
||||
mutable struct FiveForkTable
|
||||
fork51::Channel
|
||||
fork12::Channel
|
||||
fork23::Channel
|
||||
fork34::Channel
|
||||
fork45::Channel
|
||||
function FiveForkTable()
|
||||
this = new()
|
||||
this.fork51 = Channel(1); put!(this.fork51, "fork") # start with one fork per channel
|
||||
this.fork12 = Channel(1); put!(this.fork12, "fork")
|
||||
this.fork23 = Channel(1); put!(this.fork23, "fork")
|
||||
this.fork34 = Channel(1); put!(this.fork34, "fork")
|
||||
this.fork45 = Channel(1); put!(this.fork45, "fork")
|
||||
this
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
table = FiveForkTable();
|
||||
tasks = [Philosopher("Aristotle", table.fork12, table.fork51),
|
||||
Philosopher("Kant", table.fork23, table.fork12),
|
||||
Philosopher("Spinoza", table.fork34, table.fork23),
|
||||
Philosopher("Marx", table.fork45, table.fork34),
|
||||
Philosopher("Russell", table.fork51, table.fork45)]
|
||||
|
||||
function dine(t,p)
|
||||
if p.righthanded
|
||||
take!(p.rightforkheld); println("$(p.name) takes right fork")
|
||||
take!(p.leftforkheld); println("$(p.name) takes left fork")
|
||||
else
|
||||
take!(p.leftforkheld); println("$(p.name) takes left fork")
|
||||
take!(p.rightforkheld); println("$(p.name) takes right fork")
|
||||
end
|
||||
end
|
||||
|
||||
function leavetothink(t, p)
|
||||
put!(p.rightforkheld, "fork"); println("$(p.name) puts down right fork")
|
||||
put!(p.leftforkheld, "fork"); println("$(p.name) puts down left fork")
|
||||
end
|
||||
|
||||
contemplate(t) = sleep(t)
|
||||
|
||||
function dophil(p, t, fullaftersecs=2.0, hungryaftersecs=10.0)
|
||||
while true
|
||||
if p.hungry
|
||||
println("$(p.name) is hungry")
|
||||
dine(table, p)
|
||||
sleep(fullaftersecs)
|
||||
p.hungry = false
|
||||
leavetothink(t, p)
|
||||
else
|
||||
println("$(p.name) is out of the dining room for now.")
|
||||
contemplate(hungryaftersecs)
|
||||
p.hungry = true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function runall(tasklist)
|
||||
for p in tasklist
|
||||
@async dophil(p, table)
|
||||
end
|
||||
while true begin sleep(5) end end
|
||||
end
|
||||
|
||||
runall(tasks)
|
||||
58
Task/Dining-philosophers/Kotlin/dining-philosophers.kotlin
Normal file
58
Task/Dining-philosophers/Kotlin/dining-philosophers.kotlin
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
// Version 1.2.31
|
||||
|
||||
import java.util.Random
|
||||
import java.util.concurrent.locks.Lock
|
||||
import java.util.concurrent.locks.ReentrantLock
|
||||
|
||||
val rand = Random()
|
||||
|
||||
class Fork(val name: String) {
|
||||
val lock = ReentrantLock()
|
||||
|
||||
fun pickUp(philosopher: String) {
|
||||
lock.lock()
|
||||
println(" $philosopher picked up $name")
|
||||
}
|
||||
|
||||
fun putDown(philosopher: String) {
|
||||
lock.unlock()
|
||||
println(" $philosopher put down $name")
|
||||
}
|
||||
}
|
||||
|
||||
class Philosopher(val pname: String, val f1: Fork, val f2: Fork) : Thread() {
|
||||
override fun run() {
|
||||
(1..20).forEach {
|
||||
println("$pname is hungry")
|
||||
f1.pickUp(pname)
|
||||
f2.pickUp(pname)
|
||||
println("$pname is eating bite $it")
|
||||
Thread.sleep(rand.nextInt(300) + 100L)
|
||||
f2.putDown(pname)
|
||||
f1.putDown(pname)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun diningPhilosophers(names: List<String>) {
|
||||
val size = names.size
|
||||
val forks = List(size) { Fork("Fork ${it + 1}") }
|
||||
val philosophers = mutableListOf<Philosopher>()
|
||||
names.forEachIndexed { i, n ->
|
||||
var i1 = i
|
||||
var i2 = (i + 1) % size
|
||||
if (i2 < i1) {
|
||||
i1 = i2
|
||||
i2 = i
|
||||
}
|
||||
val p = Philosopher(n, forks[i1], forks[i2])
|
||||
p.start()
|
||||
philosophers.add(p)
|
||||
}
|
||||
philosophers.forEach { it.join() }
|
||||
}
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
val names = listOf("Aristotle", "Kant", "Spinoza", "Marx", "Russell")
|
||||
diningPhilosophers(names)
|
||||
}
|
||||
|
|
@ -1,48 +1,48 @@
|
|||
/*REXX pgm demonstrates a solution in solving the dining philosophers problem.*/
|
||||
signal on halt /*branches to HALT: (on Ctrl─break).*/
|
||||
parse arg seed diners /*obtain optional arguments from the CL*/
|
||||
if datatype(seed,'W') then call random ,, seed /*for random repeatability.*/
|
||||
if diners='' then diners = 'Aristotle, Kant, Spinoza, Marx, Russell'
|
||||
tell=(left(seed,1)\=='+') /*Leading + in SEED? Then no statistics*/
|
||||
diners=space(translate(diners,,',')) /*change to an uncommatized diners list*/
|
||||
#=words(diners); @.= 0 /*#: the number of dining philosophers.*/
|
||||
eatL=15; eatH= 60 /*minimum & maximum minutes for eating.*/
|
||||
thinkL=30; thinkH=180 /* " " " " " thinking*/
|
||||
forks.=1 /*indicate that all forks are on table.*/
|
||||
do tic=1 /*'til halted.*/ /*use "minutes" for time advancement.*/
|
||||
call grabForks /*determine if anybody can grab 2 forks*/
|
||||
call passTime /*handle philosophers eating|thinking. */
|
||||
end /*tic*/ /* ··· and time marches on ··· */
|
||||
/* [↓] this REXX program was halted,*/
|
||||
halt: say ' ··· REXX program halted!' /*probably by Ctrl─Break or equivalent.*/
|
||||
exit /*stick a fork in it, we're all done. */
|
||||
/*──────────────────────────────────FORK subroutine───────────────────────────*/
|
||||
fork: parse arg x 1 ox; x=abs(x); L=x-1; if L==0 then L=# /*on a boundary? */
|
||||
if ox<0 then do; forks.L=1; forks.x=1; return; end /*drop the forks.*/
|
||||
got2=forks.L & forks.x /*get 2 forks │ ¬*/
|
||||
if got2 then do; forks.L=0; forks.x=0; end /*got two forks. */
|
||||
return got2 /*return with success ··· or failure. */
|
||||
/*──────────────────────────────────GRABFORKS subroutine──────────────────────*/
|
||||
grabForks: do person=1 for # /*see if any person can grab two forks.*/
|
||||
if @.person.state\==0 then iterate /*the diner ain't waiting. */
|
||||
if \fork(person) then iterate /*the diner didn't grab 2. */
|
||||
@.person.state= 'eating' /*diner spaghetti slurping.*/
|
||||
@.person.dur=random(eatL,eatH) /*how long will diner eat? */
|
||||
end /*person*/ /* [↑] handle all diners. */
|
||||
return
|
||||
/*──────────────────────────────────PASSTIME subroutine───────────────────────*/
|
||||
passTime: if tell then say /*display a handy blank line separator.*/
|
||||
do p=1 for # /*handle each of the diner's activity. */
|
||||
if tell then say right(tic,9,.) right(word(diners,p),20),
|
||||
right(word(@.p.state 'waiting', 1+(@.p.state==0)),9) right(@.p.dur,5)
|
||||
if @.p.dur==0 then iterate /*this diner is waiting for two forks. */
|
||||
@.p.dur=@.p.dur - 1 /*indicate single time unit has passed.*/
|
||||
if @.p.dur\==0 then iterate /*Activity done? No, then keep it up.*/
|
||||
if @.p.state=='eating' then do /*now, leave the table.*/
|
||||
call fork -p /*drop the darn forks. */
|
||||
@.p.state='thinking' /*status.*/
|
||||
@.p.dur=random(thinkL,thinkH) /*length.*/
|
||||
end /* [↓] diner ──► the table.*/
|
||||
else if @.p.state=='thinking' then @.p.state=0
|
||||
end /*p*/ /*[↑] P (person) ≡dining philosophers.*/
|
||||
return
|
||||
/*REXX program demonstrates a solution in solving the dining philosophers problem. */
|
||||
signal on halt /*branches to HALT: (on Ctrl─break).*/
|
||||
parse arg seed diners /*obtain optional arguments from the CL*/
|
||||
if datatype(seed, 'W') then call random ,, seed /*this allows for random repeatability.*/
|
||||
if diners= '' then diners = 'Aristotle, Kant, Spinoza, Marx, Russell'
|
||||
tell=(left(seed, 1) \== '+') /*Leading + in SEED? Then no statistics*/
|
||||
diners=space( translate(diners, , ',') ) /*change to an uncommatized diners list*/
|
||||
#=words(diners); @.= 0 /*#: the number of dining philosophers.*/
|
||||
eatL=15; eatH= 60 /*minimum & maximum minutes for eating.*/
|
||||
thinkL=30; thinkH=180 /* " " " " " thinking*/
|
||||
forks.=1 /*indicate that all forks are on table.*/
|
||||
do tic=1 /*'til halted.*/ /*use "minutes" for time advancement.*/
|
||||
call grabForks /*determine if anybody can grab 2 forks*/
|
||||
call passTime /*handle philosophers eating|thinking. */
|
||||
end /*tic*/ /* ··· and time marches on ··· */
|
||||
/* [↓] this REXX program was halted,*/
|
||||
halt: say ' ··· REXX program halted!' /*probably by Ctrl─Break or equivalent.*/
|
||||
exit /*stick a fork in it, we're all done. */
|
||||
/*──────────────────────────────────────────────────────────────────────────────────────*/
|
||||
fork: parse arg x 1 ox; x=abs(x); L=x - 1; if L==0 then L=# /*use "round Robin".*/
|
||||
if ox<0 then do; forks.L=1; forks.x=1; return; end /*drop the forks. */
|
||||
got2= forks.L & forks.x /*get 2 forks or not*/
|
||||
if got2 then do; forks.L=0; forks.x=0; end /*obtained 2 forks. */
|
||||
return got2 /*return with success ··· or failure. */
|
||||
/*──────────────────────────────────────────────────────────────────────────────────────*/
|
||||
grabForks: do person=1 for # /*see if any person can grab two forks.*/
|
||||
if @.person.state\==0 then iterate /*this diner ain't in a waiting state. */
|
||||
if \fork(person) then iterate /*this diner didn't grab two forks. */
|
||||
@.person.state= 'eating' /*this diner is slurping spaghetti. */
|
||||
@.person.dur=random(eatL, eatH) /*how long will this diner eat pasta ? */
|
||||
end /*person*/ /* [↑] process the dining philosophers*/
|
||||
return /*all the diners have been examined. */
|
||||
/*──────────────────────────────────────────────────────────────────────────────────────*/
|
||||
passTime: if tell then say /*display a handy blank line separator.*/
|
||||
do p=1 for # /*handle each of the diner's activity. */
|
||||
if tell then say right(tic, 9, .) right( word( diners, p), 20),
|
||||
right(word(@.p.state 'waiting',1+(@.p.state==0)),9) right(@.p.dur,5)
|
||||
if @.p.dur==0 then iterate /*this diner is waiting for two forks. */
|
||||
@.p.dur= @.p.dur - 1 /*indicate single time unit has passed.*/
|
||||
if @.p.dur\==0 then iterate /*Activity done? No, then keep it up.*/
|
||||
if @.p.state=='eating' then do /*now, leave the table.*/
|
||||
call fork -p /*drop the darn forks. */
|
||||
@.p.state= 'thinking' /*status.*/
|
||||
@.p.dur=random(thinkL, thinkH) /*length.*/
|
||||
end /* [↓] a diner goes ──► the table. */
|
||||
else if @.p.state=='thinking' then @.p.state=0
|
||||
end /*p*/ /*[↑] P (person)≡ dining philosophers.*/
|
||||
return
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue