monex.pp 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. program TMonitorTest;
  2. {$APPTYPE CONSOLE}
  3. {$mode objfpc}
  4. {$h+}
  5. uses
  6. {$ifdef unix}
  7. cthreads,
  8. {$endif}
  9. SysUtils, Classes, fpMonitor;
  10. type
  11. Drop = class(TObject)
  12. private
  13. // Message sent from producer to consumer.
  14. Msg: string;
  15. // True if consumer should wait for producer to send message, false
  16. // if producer should wait for consumer to retrieve message.
  17. Empty: Boolean;
  18. public
  19. constructor Create;
  20. function Take: string;
  21. procedure Put(AMessage: string);
  22. end;
  23. Producer = class(TThread)
  24. private
  25. FDrop: Drop;
  26. public
  27. constructor Create(ADrop: Drop);
  28. procedure Execute; override;
  29. end;
  30. Consumer = class(TThread)
  31. private
  32. FDrop: Drop;
  33. public
  34. constructor Create(ADrop: Drop);
  35. procedure Execute; override;
  36. end;
  37. { Drop }
  38. constructor Drop.Create;
  39. begin
  40. Empty := True;
  41. end;
  42. function Drop.Take: string;
  43. begin
  44. TMonitor.Enter(Self);
  45. try
  46. // Wait until message is available.
  47. while Empty do
  48. begin
  49. TMonitor.Wait(Self, INFINITE);
  50. end;
  51. // Toggle status.
  52. Empty := True;
  53. // Notify producer that status has changed.
  54. TMonitor.PulseAll(Self);
  55. Result := Msg;
  56. finally
  57. TMonitor.Exit(Self);
  58. end;
  59. end;
  60. procedure Drop.Put(AMessage: string);
  61. begin
  62. TMonitor.Enter(Self);
  63. try
  64. // Wait until message has been retrieved.
  65. while not Empty do
  66. begin
  67. TMonitor.Wait(Self, INFINITE);
  68. end;
  69. // Toggle status.
  70. Empty := False;
  71. // Store message.
  72. Msg := AMessage;
  73. // Notify consumer that status has changed.
  74. TMonitor.PulseAll(Self);
  75. finally
  76. TMonitor.Exit(Self);
  77. end;
  78. end;
  79. { Producer }
  80. constructor Producer.Create(ADrop: Drop);
  81. begin
  82. FDrop := ADrop;
  83. inherited Create(False);
  84. end;
  85. procedure Producer.Execute;
  86. var
  87. Msgs: array of string;
  88. I: Integer;
  89. begin
  90. SetLength(Msgs, 4);
  91. Msgs[0] := 'Mares eat oats';
  92. Msgs[1] := 'Does eat oats';
  93. Msgs[2] := 'Little lambs eat ivy';
  94. Msgs[3] := 'A kid will eat ivy too';
  95. for I := 0 to Length(Msgs) - 1 do
  96. begin
  97. FDrop.Put(Msgs[I]);
  98. Sleep(Random(50{00}));
  99. end;
  100. FDrop.Put('DONE');
  101. end;
  102. { Consumer }
  103. constructor Consumer.Create(ADrop: Drop);
  104. begin
  105. FDrop := ADrop;
  106. inherited Create(False);
  107. end;
  108. procedure Consumer.Execute;
  109. var
  110. Msg: string;
  111. begin
  112. repeat
  113. Msg := FDrop.Take;
  114. WriteLn('Received: ' + Msg);
  115. Sleep(Random(50{00}));
  116. until Msg = 'DONE';
  117. end;
  118. var
  119. ADrop: Drop;
  120. begin
  121. Randomize;
  122. ADrop := Drop.Create;
  123. Producer.Create(ADrop);
  124. Consumer.Create(ADrop).WaitFor;
  125. {$IFDEF WINDOWS}
  126. ReadLn;
  127. {$ENDIF}
  128. end.