declare proc {Loop S Clock UpdatePort P1 P2} NewClock Response in case S of H|T then if H.clock > Clock then NewClock = H.clock + 1 else NewClock = Clock + 1 end {Send UpdatePort NewClock#H} Response = msg(clock:NewClock value:H.value+1) {Send P1 Response} {Send P2 Response} {Loop T NewClock UpdatePort P1 P2} end end fun {ClockFilter L Clock DisplayPort} case L of H|T then if Clock > H.clock then {Send DisplayPort H.value} {ClockFilter T Clock DisplayPort} else H|{ClockFilter T Clock DisplayPort} end [] nil then nil end end proc {Display Updates Stack DisplayPort} case Updates of (Clock#Msg)|T then {Display T {ClockFilter Msg|Stack Clock DisplayPort} DisplayPort} end end proc {DumbDisplay Updates Stack DisplayPort} for _#Msg in Updates do {Send DisplayPort Msg.value} end end proc {Process Name S1 S2 P1 P2} Msgs MsgPort = {NewPort Msgs} Updates UpdatePort = {NewPort Updates} Displayed DisplayPort = {NewPort Displayed} in thread for X in S1 do {Send MsgPort X} end end thread for X in S2 do {Send MsgPort X} end end thread {Loop Msgs 0 UpdatePort P1 P2} end % Replacing Display by DumbDisplay breaks the garantee that causal order % will be respected. thread {Display Updates nil DisplayPort} end {Browse Name(Displayed)} end fun {DelayStream S} thread case S of H|T then {Delay {OS.rand} mod 2000 + 500} H|{DelayStream T} end end end proc {MakeDelayPort Port Stream} Tmp in Port = {NewPort Tmp} Stream = {DelayStream Tmp} end S12 P12 {MakeDelayPort P12 S12} S13 P13 {MakeDelayPort P13 S13} S21 P21 {MakeDelayPort P21 S21} S23 P23 {MakeDelayPort P23 S23} S31 P31 {MakeDelayPort P31 S31} S32 P32 {MakeDelayPort P32 S32} C12 = {Connection.offer S12} C13 = {Connection.offer S13} C21 = {Connection.offer S21} C23 = {Connection.offer S23} C31 = {Connection.offer S31} C32 = {Connection.offer S32} {Process n1 S21 S31 P12 P13} {Process n2 S12 S32 P21 P23} {Process n3 S13 S23 P31 P32} {Send P21 msg(clock:0 value:0)}