Time for an 2014 update…
This commit is contained in:
parent
372c577f83
commit
09687c4926
2520 changed files with 34227 additions and 7318 deletions
|
|
@ -1,3 +1,10 @@
|
|||
(in-package :common-lisp-user)
|
||||
|
||||
;;
|
||||
;; FLAG -- if using quicklisp, you can get bordeaux-threads loaded up
|
||||
;; with: (ql:quickload :bordeaux-threads)
|
||||
;;
|
||||
|
||||
(defvar *philosophers* '(Aristotle Kant Spinoza Marx Russell))
|
||||
|
||||
(defclass philosopher ()
|
||||
|
|
@ -7,7 +14,7 @@
|
|||
(meals-left :initarg :meals-left :accessor meals-left-of)))
|
||||
|
||||
(defclass fork ()
|
||||
((lock :initform (make-lock "fork") :reader lock-of)))
|
||||
((lock :initform (bt:make-lock "fork") :reader lock-of)))
|
||||
|
||||
(defun random-normal (&optional (mean 0.0) (sd 1.0))
|
||||
(do* ((x1 #1=(1- (* 2.0d0 (random 1d0))) #1#)
|
||||
|
|
@ -31,9 +38,9 @@
|
|||
:right-fork (nth (mod (1+ i) count) forks)
|
||||
:name name
|
||||
:meals-left meals)))
|
||||
(condition (make-condition-variable))
|
||||
(lock (make-lock "main loop"))
|
||||
(output-lock (make-lock "output lock")))
|
||||
(condition (bt:make-condition-variable))
|
||||
(lock (bt:make-lock "main loop"))
|
||||
(output-lock (bt:make-lock "output lock")))
|
||||
(dolist (p philosophers)
|
||||
(labels ((think ()
|
||||
(/me "is now thinking")
|
||||
|
|
@ -41,33 +48,33 @@
|
|||
(/me "is now hungry")
|
||||
(dine))
|
||||
(dine ()
|
||||
(with-lock-held ((lock-of (left-fork-of p)))
|
||||
(or (acquire-lock (lock-of (right-fork-of p)) nil)
|
||||
(bt:with-lock-held ((lock-of (left-fork-of p)))
|
||||
(or (bt:acquire-lock (lock-of (right-fork-of p)) nil)
|
||||
(progn (/me "couldn't get a fork and ~
|
||||
returns to thinking")
|
||||
(release-lock (lock-of (left-fork-of p)))
|
||||
(bt:release-lock (lock-of (left-fork-of p)))
|
||||
(return-from dine (think))))
|
||||
(/me "is eating")
|
||||
(sleep* (apply #'random-normal dining-time))
|
||||
(release-lock (lock-of (right-fork-of p)))
|
||||
(bt:release-lock (lock-of (right-fork-of p)))
|
||||
(/me "is done eating (~A meals left)"
|
||||
(decf (meals-left-of p))))
|
||||
(cond ((<= (meals-left-of p) 0)
|
||||
(/me "leaves the dining room")
|
||||
(with-lock-held (lock)
|
||||
(bt:with-lock-held (lock)
|
||||
(setq philosophers (delete p philosophers))
|
||||
(condition-notify condition)))
|
||||
(bt:condition-notify condition)))
|
||||
(t (think))))
|
||||
(/me (control &rest args)
|
||||
(with-lock-held (output-lock)
|
||||
(bt:with-lock-held (output-lock)
|
||||
(write-sequence (string (name-of p)) e)
|
||||
(write-char #\Space e)
|
||||
(apply #'format e (concatenate 'string control "~%")
|
||||
args))))
|
||||
(make-thread #'think)))
|
||||
(loop (with-lock-held (lock)
|
||||
(bt:make-thread #'think)))
|
||||
(loop (bt:with-lock-held (lock)
|
||||
(when (endp philosophers)
|
||||
(format e "all philosophers are done dining~%")
|
||||
(return)))
|
||||
(with-lock-held (lock)
|
||||
(condition-wait condition lock)))))
|
||||
(bt:with-lock-held (lock)
|
||||
(bt:condition-wait condition lock)))))
|
||||
|
|
|
|||
|
|
@ -1,20 +1,19 @@
|
|||
import std.stdio, std.algorithm, std.string, std.parallelism,
|
||||
core.sync.mutex;
|
||||
core.sync.mutex;
|
||||
|
||||
void eat(in uint i, in string name, Mutex[] forks) {
|
||||
void eat(in size_t i, in string name, Mutex[] forks) {
|
||||
writeln(name, " is hungry.");
|
||||
|
||||
immutable j = (i + 1) % forks.length;
|
||||
|
||||
// Take forks i and j. The lower one first to prevent deadlock.
|
||||
auto fork1 = forks[min(i, j)];
|
||||
auto fork2 = forks[max(i, j)];
|
||||
|
||||
fork1.lock();
|
||||
scope(exit) fork1.unlock();
|
||||
fork1.lock;
|
||||
scope(exit) fork1.unlock;
|
||||
|
||||
fork2.lock();
|
||||
scope(exit) fork2.unlock();
|
||||
fork2.lock;
|
||||
scope(exit) fork2.unlock;
|
||||
|
||||
writeln(name, " is eating.");
|
||||
writeln(name, " is full.");
|
||||
|
|
@ -25,16 +24,16 @@ void think(in string name) {
|
|||
}
|
||||
|
||||
void main() {
|
||||
const philosophers = "Aristotle Kant Spinoza Marx Russell".split();
|
||||
const philosophers = "Aristotle Kant Spinoza Marx Russell".split;
|
||||
Mutex[philosophers.length] forks;
|
||||
foreach (ref fork; forks)
|
||||
fork = new Mutex();
|
||||
fork = new Mutex;
|
||||
|
||||
defaultPoolThreads = forks.length;
|
||||
foreach (i, philo; taskPool.parallel(philosophers)) {
|
||||
foreach (_; 0 .. 100) {
|
||||
foreach (immutable _; 0 .. 100) {
|
||||
eat(i, philo, forks);
|
||||
think(philo);
|
||||
philo.think;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
56
Task/Dining-philosophers/Groovy/dining-philosophers.groovy
Normal file
56
Task/Dining-philosophers/Groovy/dining-philosophers.groovy
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
import groovy.transform.Canonical
|
||||
|
||||
import java.util.concurrent.locks.Lock
|
||||
import java.util.concurrent.locks.ReentrantLock
|
||||
|
||||
@Canonical
|
||||
class Fork {
|
||||
String name
|
||||
Lock lock = new ReentrantLock()
|
||||
|
||||
void pickUp(String philosopher) {
|
||||
lock.lock()
|
||||
println " $philosopher picked up $name"
|
||||
}
|
||||
|
||||
void putDown(String philosopher) {
|
||||
lock.unlock()
|
||||
println " $philosopher put down $name"
|
||||
}
|
||||
}
|
||||
|
||||
@Canonical
|
||||
class Philosopher extends Thread {
|
||||
Fork f1
|
||||
Fork f2
|
||||
|
||||
@Override
|
||||
void run() {
|
||||
def random = new Random()
|
||||
(1..20).each { bite ->
|
||||
println "$name is hungry"
|
||||
f1.pickUp name
|
||||
f2.pickUp name
|
||||
println "$name is eating bite $bite"
|
||||
Thread.sleep random.nextInt(300) + 100
|
||||
f2.putDown name
|
||||
f1.putDown name
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void diningPhilosophers(names) {
|
||||
def forks = (1..names.size()).collect { new Fork(name: "Fork $it") }
|
||||
def philosophers = []
|
||||
names.eachWithIndex{ n, i ->
|
||||
def (i1, i2) = [i, (i + 1) % 5]
|
||||
if (i2 < i1) (i1, i2) = [i2, i]
|
||||
|
||||
def p = new Philosopher(name: n, f1: forks[i1], f2: forks[i2])
|
||||
p.start()
|
||||
philosophers << p
|
||||
}
|
||||
philosophers.each { it.join() }
|
||||
}
|
||||
|
||||
diningPhilosophers(['Aristotle', 'Kant', 'Spinoza', 'Marx', 'Russell'])
|
||||
55
Task/Dining-philosophers/Perl-6/dining-philosophers.pl6
Normal file
55
Task/Dining-philosophers/Perl-6/dining-philosophers.pl6
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
class Fork {
|
||||
has $!lock = Lock.new;
|
||||
method grab($who, $which) {
|
||||
remark "$who grabbing $which fork";
|
||||
$!lock.lock;
|
||||
}
|
||||
method drop($who, $which) {
|
||||
remark "$who dropping $which fork";
|
||||
$!lock.unlock;
|
||||
}
|
||||
}
|
||||
|
||||
class Lollipop {
|
||||
has $!channel = Channel.new;
|
||||
method mine($who) { $!channel.send($who) }
|
||||
method yours { $!channel.receive }
|
||||
}
|
||||
|
||||
my $out = Channel.new;
|
||||
sub remark($msg) { $out.send($msg) }
|
||||
start { loop { $out.receive.say } }
|
||||
|
||||
sub dally($sec) { sleep 0.01 + rand * $sec }
|
||||
|
||||
sub MAIN(*@names) {
|
||||
@names ||= <Aristotle Kant Spinoza Marx Russell>;
|
||||
|
||||
my @lfork = Fork.new xx @names;
|
||||
my @rfork = @lfork.rotate;
|
||||
|
||||
my $lollipop = Lollipop.new;
|
||||
start { $lollipop.yours; }
|
||||
|
||||
my @philosophers = do for @names Z @lfork Z @rfork -> $n, $l, $r {
|
||||
start {
|
||||
sleep 1 + rand*4;
|
||||
loop {
|
||||
$l.grab($n,'left');
|
||||
dally 1; # give opportunity for deadlock
|
||||
$r.grab($n,'right');
|
||||
remark "$n eating";
|
||||
dally 10;
|
||||
$l.drop($n,'left');
|
||||
$r.drop($n,'right');
|
||||
|
||||
$lollipop.mine($n);
|
||||
sleep 1; # lick at least once
|
||||
remark "$n lost lollipop to $lollipop.yours(), now digesting";
|
||||
|
||||
dally 20;
|
||||
}
|
||||
}
|
||||
}
|
||||
await @philosophers;
|
||||
}
|
||||
40
Task/Dining-philosophers/Perl/dining-philosophers-2.pl
Normal file
40
Task/Dining-philosophers/Perl/dining-philosophers-2.pl
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
#!/usr/bin/perl
|
||||
use common::sense;
|
||||
use Coro;
|
||||
use AnyEvent;
|
||||
use Coro::AnyEvent;
|
||||
use EV;
|
||||
|
||||
my @philosophers = qw(Aristotle Kant Spinoza Marx Russell);
|
||||
my @forks = (1..@philosophers);
|
||||
my @fork_sem;
|
||||
|
||||
$fork_sem[$_] = new Coro::Semaphore for (0..$#philosophers);
|
||||
|
||||
|
||||
for(my $i = $#philosophers; $i >= 0; $i--){
|
||||
say $philosophers[$i] . " has fork #" . $forks[$i] . " and fork #" . $forks[$i-1];
|
||||
async {
|
||||
my ($name, ,$no, $forks_got) = (@_);
|
||||
|
||||
$Coro::current->{desc} = $name;
|
||||
Coro::AnyEvent::sleep(rand 4);
|
||||
|
||||
while(1){
|
||||
say $name . " is hungry.";
|
||||
$$forks_got[$no]->down();
|
||||
Coro::AnyEvent::sleep(rand 1); #Let's make deadlock!
|
||||
$$forks_got[$no-1]->down();
|
||||
say $name . " is eating.";
|
||||
Coro::AnyEvent::sleep(1 + rand 8);
|
||||
|
||||
$$forks_got[$no]->up();
|
||||
$$forks_got[$no-1]->up();
|
||||
|
||||
say $name . " is thinking.";
|
||||
Coro::AnyEvent::sleep(1 + rand 8);
|
||||
}
|
||||
}($philosophers[$i], $i, \@fork_sem);
|
||||
}
|
||||
|
||||
EV::loop;
|
||||
48
Task/Dining-philosophers/REXX/dining-philosophers.rexx
Normal file
48
Task/Dining-philosophers/REXX/dining-philosophers.rexx
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
/*REXX prm demonstrates a solution to solve dining philosophers problem.*/
|
||||
parse arg seed diners /*get optional arguments from CL.*/
|
||||
if seed\=='' & seed\==',' then call random ,, seed /*for repeatability*/
|
||||
if diners='' then diners='Aristotle,Kant,Spinoza,Marx,Russell'
|
||||
tell=left(seed,1)\=='+' /*Leading + in SEED? No stats.*/
|
||||
diners=translate(diners,,',') /*change a commatized diners list*/
|
||||
#=words(diners); @.=0 /*the number of dining philospers*/
|
||||
eatL=15; eatH= 60 /*min & max minutes for eating. */
|
||||
thinkL=30; thinkH=180 /* " " " " " thinking.*/
|
||||
forks.=1 /*indicate all forks are on table*/
|
||||
do tic=1 /*use minutes as time advancement*/
|
||||
call grabForks /*see if anybody can grab 2 forks*/
|
||||
call passTime /*handle diners eating | thinking*/
|
||||
end /*tic*/ /* ··· and time marches on ··· */
|
||||
exit /*stick a fork in it, we're done.*/
|
||||
/*──────────────────────────────────FORK subroutine─────────────────────*/
|
||||
fork: parse arg x 1 ox; x=abs(x); L=x-1; if L==0 then L=# /*boundry ? */
|
||||
if ox<0 then do; forks.L=1; forks.x=1; return; end /*drop forks*/
|
||||
got2=forks.L & forks.x /*did we get two forks or not? */
|
||||
if got2 then do; forks.L=0; forks.x=0; end /*got forks.*/
|
||||
return got2 /*return with success or failure.*/
|
||||
/*──────────────────────────────────GRABFORKS subroutine────────────────*/
|
||||
grabForks: do person=1 for # /*see if any person can grab two.*/
|
||||
if @.person.status\==0 then iterate /*diner ain't waiting*/
|
||||
if \fork(person) then iterate /*diner didn't grab 2*/
|
||||
@.person.status='eating' /*diner now chomps on spaghetti. */
|
||||
@.person.dur=random(eatL,eatH) /*how long will diner eat? */
|
||||
end /*person*/
|
||||
return
|
||||
/*──────────────────────────────────PASSTIME subroutine─────────────────*/
|
||||
passTime: if tell then say /*show a (blank line) separator. */
|
||||
do p=1 for # /*process each diner's activity. */
|
||||
if tell then say right(tic,9,'.') right(word(diners,p),20),
|
||||
right(word(@.p.status 'waiting',1+(@.p.status==0)),9) right(@.p.dur,5)
|
||||
if @.p.dur==0 then iterate /*diner is waiting for two forks.*/
|
||||
@.p.dur=@.p.dur-1 /*indicate 1 timeUnit has gone by*/
|
||||
if @.p.dur\==0 then iterate /*Activity done? No, keep it up.*/
|
||||
select /*handle the activity being done.*/
|
||||
when @.p.status=='eating' then do /*now, leave the table.*/
|
||||
call fork -p /*drop the forks.*/
|
||||
@.p.status='thinking' /*status.*/
|
||||
@.p.dur=random(thinkL,thinkH)
|
||||
end
|
||||
when @.p.status=='thinking' then @.p.status=0 /*──► table*/
|
||||
otherwise nop /*diner must be waiting on forks.*/
|
||||
end /*select*/
|
||||
end /*p*/
|
||||
return
|
||||
Loading…
Add table
Add a link
Reference in a new issue