home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Columbia Kermit
/
kermit.zip
/
ckscripts
/
dining-philosophers
< prev
next >
Wrap
Lisp/Scheme
|
2020-01-01
|
5KB
|
206 lines
# From: Dat Thuc Nguyen -*-kermit-*-
# Date: Mon, 03 May 2004 15:12:56 -0400
# Subject: The Art of Programming in C-Kermit
#
# From time to time I sent in C-Kermit scripts that solve some problems people
# also solved in other programming languages.
#
# Today I am sending in a program that's difficult since it requires
# the notions of semaphore, process, timer and concurrency.
#
# The "dinning philosophers" problem is stated in Operating System Concepts by
# Peterson and Silberschatz, 1985, pp. 347-348.
#
# Requires the 'class' module.
#
# Version 2: I fine tune the Dinning Philosophers script to
# accomodate any numbers of hungry Philosophers instead of only five.
take class
define randnum {
# \%1 random seed
while true {
if {\fsexpr(> (let rd \frandom(\%1)) 0)} return \m(rd)
}
}
class Semaphore
define Semaphore::new: {
(setq \%1.Semaphore.stat -1)
_asg \%1.Semaphore.Queue |
(\%1)
}
define Semaphore>>acquire {
local s
(setq s (++ \%1.Semaphore.stat))
if > s 0 {
_asg \%1.Semaphore.Queue \m(\%1.Semaphore.Queue)\%2|
echo \%2 waits for \m(\%2.\%1.ChopStick)
} else {
echo \%2 grabs \m(\%2.\%1.ChopStick)
}
(! s)
}
define Semaphore>>release {
(-- \%1.Semaphore.stat)
local \&w[]
if > \fsplit(\m(\%1.Semaphore.Queue),&w,|) 0 {
_asg \%1.Semaphore.Queue \freplace(\m(\%1.Semaphore.Queue),|\&w[1]|,|)
DiningPhilosophers add: \&w[1]
echo \&w[1] grabs \m(\&w[1].\%1.ChopStick)
}
(\%1)
}
define Semaphore>>inspect {
echo \%1 \m(\%1.Semaphore.stat)
echo \%1 \m(\%1.Semaphore.Queue)
}
class Philosopher
define Philosopher::new:leftChopStick:rightChopStick:place: {
# \%2 leftChopStick
# \%3 rightChopStick
(setq \%1.leftChopStick \%2)
(setq \%1.rightChopStick \%3)
(setq \%1.Philosopher.Number \%4)
_asg \%1.\%2.ChopStick left ChopStick
_asg \%1.\%3.ChopStick right ChopStick
_asg \%1.Philosopher.act thinking
(setq \%1.Philosopher.timeRepeat (randnum 15))
(\%1)
}
define Philosopher>>act {
(-- \%1.Philosopher.timeRepeat)
if == \m(\%1.Philosopher.timeRepeat) 0 {
(setq \%1.Philosopher.timeRepeat (randnum 50))
return \fsexpr(\%1 '\m(\%1.Philosopher.act))
} else {
return 1 # line up in the process queue
}
}
define Philosopher>>thinking {
echo \%1 is thinking
_asg \%1.Philosopher.act getChopStick
(1) # line up in the process queue
}
define Philosopher>>getChopStick {
(AND (\%1 'getFirstChopStick) (\%1 'getSecondChopStick))
}
define Philosopher>>getFirstChopStick {
_asg \%1.Philosopher.act getSecondChopStick
if {\fsexpr(mod \%1.Philosopher.Number 2)} { # odd
return \fsexpr(\m(\%1.leftChopStick) 'acquire \%1)
} else { # even
return \fsexpr(\m(\%1.rightChopStick) 'acquire \%1)
}
}
define Philosopher>>getSecondChopStick {
_asg \%1.Philosopher.act eat
if {\fsexpr(mod \%1.Philosopher.Number 2)} { # odd
return \fsexpr(\m(\%1.rightChopStick) 'acquire \%1))
} else { # even
return \fsexpr(\m(\%1.leftChopStick) 'acquire \%1))
}
}
define Philosopher>>eat {
echo \%1 is eating
_asg \%1.Philosopher.act release_ChopSticks
(1)
}
define Philosopher>>release_ChopSticks {
echo \%1 releases both Chopsticks
_asg \%1.Philosopher.act sleep
(\m(\%1.leftChopStick) 'release)
(\m(\%1.rightChopStick) 'release)
(1)
}
define Philosopher>>sleep {
echo \%1 is sleeping
_asg \%1.Philosopher.act wakeup
(1)
}
define Philosopher>>wakeup {
echo \%1 wakes up
_asg \%1.Philosopher.act thinking
(1)
}
define Philosopher>>inspect {
echo \fsexp(\m(\%1.leftChopStick) 'inspect) and \fsexp(\m(\%1.rightChopStick) 'inspect)
(\%1)
}
class Process
define Process>>run {
while true {
local \&w[] \%n
asg \%n \fsplit(\m(\%1.Process.Queue),&w,|)
if = 0 \%n break
\%1 remove: \&w[1]
(if (\&w[1] 'act) (\%1 'add: \&w[1]))
}
}
define Process>>add: {
_asg \%1.Process.Queue \m(\%1.Process.Queue)\%2|
(\%1)
}
define Process>>remove: {
_asg \%1.Process.Queue \freplace(\m(\%1.Process.Queue),|\%2|,|)
(\%1)
}
define Process>>inspect {
echo \m(\%1.Process.Queue)
(\%1)
}
define Process::new:number: {
# \%2 Number of Philosophers and ChopSticks
_asg \%1.Process.Queue |
local \%i
for \%i 1 \%2 1 {
Semaphore new: chopstk_\%i
}
for \%i 1 \%2 1 {
(let \\\\%L \%i \\\\%R (+ (mod \%i \%2) 1))
Philosopher new: Philosopher_\%i leftChopStick: chopstk_\%L rightChopStick: chopstk_\%R place: \%i
\%1 add: Philosopher_\%i
}
(\%1)
}
define ASKME {
local \%n
while true {
ask \%n { Number of Philosophers: }
if not def \%n continue
if not numeric \%n {
echo Not numeric - "\%n"
continue
}
break
}
return \%n
}
(Process 'new: 'DiningPhilosophers 'number: (askme))
DiningPhilosophers run