fork download
  1. declare
  2. Philosophers = [aristotle kant spinoza marx russell]
  3.  
  4. proc {Start}
  5. Forks = {MakeList {Length Philosophers}}
  6. in
  7. {ForAll Forks NewFork}
  8. for
  9. Name in Philosophers
  10. LeftFork in Forks
  11. RightFork in {RightShift Forks}
  12. do
  13. thread
  14. {Philosopher Name LeftFork RightFork}
  15. end
  16. end
  17. end
  18.  
  19. proc {Philosopher Name LeftFork RightFork}
  20. for do
  21. {ShowInfo Name#" is hungry."}
  22.  
  23. {TakeForks [LeftFork RightFork]}
  24. {ShowInfo Name#" got forks."}
  25. {WaitRandom}
  26. {ReleaseFork LeftFork}
  27. {ReleaseFork RightFork}
  28.  
  29. {ShowInfo Name#" is thinking."}
  30. {WaitRandom}
  31. end
  32. end
  33.  
  34. proc {WaitRandom}
  35. {Delay 1000 + {OS.rand} mod 4000} %% 1-5 seconds
  36. end
  37.  
  38. proc {TakeForks Forks}
  39. {ForAll Forks WaitForFork}
  40. case {TryAtomically proc {$}
  41. {ForAll Forks TakeFork}
  42. end}
  43. of true then
  44. {ForAll Forks InitForkNotifier}
  45. [] false then
  46. {TakeForks Forks}
  47. end
  48. end
  49.  
  50. %%
  51. %% Fork type
  52. %%
  53.  
  54. %% A fork is a mutable reference to a pair
  55. fun {NewFork}
  56. {NewCell
  57. unit(taken:_ %% a fork is taken by setting this value to a unique value
  58. notify:unit %% to wait for a taken fork
  59. )}
  60. end
  61.  
  62. proc {TakeFork F}
  63. (@F).taken = {NewName}
  64. end
  65.  
  66. proc {InitForkNotifier F}
  67. %% we cannot do this in TakeFork
  68. %% because side effect are not allowed in subordinate spaces
  69. New Old
  70. in
  71. {Exchange F Old New}
  72. New = unit(taken:Old.taken notify:_)
  73. end
  74.  
  75. proc {ReleaseFork F}
  76. New Old
  77. in
  78. {Exchange F Old New}
  79. New = unit(taken:_ notify:unit)
  80. Old.notify = unit %% notify waiters
  81. end
  82.  
  83. proc {WaitForFork F}
  84. {Wait (@F).notify} %% returns immediatly if fork is free, otherwise blocks
  85. end
  86.  
  87. %%
  88. %% Helpers
  89. %%
  90.  
  91. %% Implements transactions on data flow variables
  92. %% with computation spaces. Returns success.
  93. fun {TryAtomically P}
  94. try
  95. S = {Space.new
  96. proc {$ Sync}
  97. {P}
  98. Sync = unit
  99. end}
  100. in
  101. {Space.askVerbose S} \= failed = true
  102. {Wait {Space.merge S}}
  103. true
  104. catch _ then
  105. false
  106. end
  107. end
  108.  
  109. fun {RightShift Xs} %% circular
  110. case Xs of nil then nil
  111. else {Append Xs.2 [Xs.1]}
  112. end
  113. end
  114.  
  115. ShowInfo = System.showInfo
  116. in
  117. {Start}
Compilation error #stdin compilation error #stdout 0s 0KB
stdin
Standard input is empty
compilation info
Mozart Compiler 1.4.0 (20080704) playing Oz 3

%%% feeding file prog.oz

%********************* binding analysis error *******************
%**
%** variable OS not introduced
%**
%** in file "./prog.oz", line 35, column 20

%********************* binding analysis error *******************
%**
%** variable Space not introduced
%**
%** in file "./prog.oz", line 95, column 6

%********************* binding analysis error *******************
%**
%** variable System not introduced
%**
%** in file "./prog.oz", line 115, column 13
%** ------------------ rejected (3 errors)
stdout
Standard output is empty