Sunday, March 22, 2009

Ch8, Ex6

declare Channel
local
proc {MySend C M}
X in
{Send C.send send(M#X)}
{Wait X}
end
fun {Receive C}
M in
{Send C.receive receive(M)}
{Wait M}
M
end
proc {MReceive Cs}
%see later for MReceive definition
skip
end
fun {New}
P1 P2 S1 S2
{NewPort S1 P1} %for receive msgs
{NewPort S2 P2} %for send msgs
proc {Iter S1 S2}
case S1#S2 of (receive(R)|S1s)#(send(X#Y)|S2s)
then
R=X
Y = unit
{Iter S1s S2s}
end
end
in
thread {Iter S1 S2} end
channel(receive:P1 send:P2)
end
in
Channel = c(new:New send:MySend
receive:Receive
mreceive:MReceive)
end
From the book its not clear what mreceive is actually supposed to do, following are my various interpretations

mreceive version#1
In this version mreceive starts listeners for all the channels and exits immediately. All the Si will be called as and when messages are received on respective channels.
proc {MReceive Cs}
for Ci#Si in Cs do
thread
{Si {Channel.receive Ci}}
end
end
end

mreceive version#2
In this version mreceive starts listeners for all the channels and waits untill messages are received on all the channels and all corresponding Si are executed.
proc {MReceive Cs}
Exit Count = {NewCell 0} in
for Ci#Si in Cs do
thread
{Si {Channel.receive Ci}}
Count := 1+@Count
if @Count == {List.length Cs} then Exit=unit end
end
end
{Wait Exit}
end

mreceive version#3
In this version mreceive starts listeners for all the channels and waits. As soon as a message is received any of the channels, corresponding Si is executed and mreceive exits. In this case only one Si is executed on whose channel a message is received first.
proc {MReceive Cs}
Exit A = {NewCell 0} in
for Ci#Si in Cs do
thread
local M in
M = {Channel.receive Ci}
if @A==0 then
{Exchange A _ 1}
{Si M}
Exit = unit
end
end
end
end
{Wait Exit}
end

NOTE: I could not understand what exactly does the extended version of mreceive is supposed to do.

TESTS
%This test proves that receive operation blocks
%until there is a send
local C in
{Browse started}
C = {Channel.new}
thread {Browse rec1#{Channel.receive C}} end
thread {Browse rec2#{Channel.receive C}} end
thread {Browse rec3#{Channel.receive C}} end

{Delay 5000}
{Channel.send C msg1}
{Delay 5000}
{Channel.send C msg2}
{Delay 5000}
{Channel.send C msg3}

end

%This test proves that send operation blocks
%until there is a receive
local C in
{Browse started}
C = {Channel.new}
thread {Channel.send C msg1} {Browse send1done} end
thread {Channel.send C msg2} {Browse send2done} end
thread {Channel.send C msg3} {Browse send3done} end

{Delay 5000}
{Browse {Channel.receive C}}
{Delay 5000}
{Browse {Channel.receive C}}
{Delay 5000}
{Browse {Channel.receive C}}
end

No comments:

Post a Comment