declare NewThread
local
M = {NewMonitor}
C = {NewCell 0}
proc {ExitOnTermination}
if {Not (@C==0)} then
{M.'lock' proc {$}
{M.wait}
{M.notifyAll}
end}
end
end
in
proc {NewThread P ?SubThread}
Is Pt={NewPort Is}
in
proc {SubThread P}
X Y in
{Exchange C X Y}
Y = X+1
thread {M.'lock'
proc {$} X Y in {P}
C:=@C-1
{M.notifyAll} end}
end
end
{SubThread P}
{ExitOnTermination}
end
end
%Test
local SubThread in
{NewThread
proc {$} {Browse started1}
{SubThread proc {$} {Delay 5000} {Browse f2} end}
{Browse finished1}
end
SubThread}
{Browse done}
end
%Complete Monitor impl code from book
%copying here as its needed to run
%the above solution
declare
fun {NewQueue}
X C={NewCell q(0 X X)} L={NewLock}
proc {Insert X}
N S E1 N1 in
{Exchange C q(N S X|E1) q(N1 S E1)}
N1=N+1
end
fun {Delete}
N S1 E N1 X in
{Exchange C q(N X|S1 E) q(N1 S1 E)}
N1=N-1
X
end
fun {Size}
lock L then @C.1 end
end
fun {DeleteAll}
lock L then
X q(_ S E)=@C in
C:=q(0 X X)
E=nil S
end
end
fun {DeleteNonBlock}
lock L then
if {Size}>0 then [{Delete}] else nil end
end
end
in
queue(insert:Insert delete:Delete size:Size
deleteAll:DeleteAll deleteNonBlock:DeleteNonBlock)
end
fun {NewGRLock}
Token1={NewCell unit}
Token2={NewCell unit}
CurThr={NewCell unit}
proc {GetLock}
if {Thread.this}\=@CurThr then Old New in
{Exchange Token1 Old New}
{Wait Old}
Token2:=New
CurThr:={Thread.this}
end
end
proc {ReleaseLock}
CurThr:=unit
unit=@Token2
end
in
'lock'(get:GetLock release:ReleaseLock)
end
fun {NewMonitor}
Q={NewQueue}
L={NewGRLock}
proc {LockM P}
{L.get} try {P} finally {L.release} end
end
proc {WaitM}
X in
{Q.insert X} {L.release} {Wait X} {L.get}
end
proc {NotifyM}
U={Q.deleteNonBlock} in
case U of [X] then X=unit else skip end
end
proc {NotifyAllM}
L={Q.deleteAll} in
for X in L do X=unit end
end
in
monitor('lock':LockM wait:WaitM notify:NotifyM
notifyAll:NotifyAllM)
end
Sunday, March 22, 2009
Ch8, Ex8
Subscribe to:
Post Comments (Atom)
No comments:
Post a Comment