June 2018 Update

This commit is contained in:
Ingy döt Net 2018-06-22 20:57:24 +00:00
parent ba8067c3b7
commit 22f33d4004
5278 changed files with 84726 additions and 14379 deletions

View file

@ -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*))))))

View file

@ -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
...

View 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)

View 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)
}

View file

@ -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