theapthread.pp 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241
  1. {%skiptarget=$nothread }
  2. { %TIMEOUT=105 }
  3. {$mode objfpc}{$h+}
  4. uses
  5. {$ifdef UNIX}
  6. cthreads,
  7. {$endif}
  8. sysutils,
  9. classes;
  10. const
  11. fifolength = 1024;
  12. type
  13. tpair = class;
  14. tproducethread = class(tthread)
  15. running: boolean;
  16. pair: tpair;
  17. constructor create(apair: tpair);
  18. procedure execute; override;
  19. end;
  20. tconsumethread = class(tthread)
  21. running: boolean;
  22. pair: tpair;
  23. constructor create(apair: tpair);
  24. procedure execute; override;
  25. end;
  26. tpair = class(tobject)
  27. public
  28. readindex: integer;
  29. writeindex: integer;
  30. fifo: array[0..fifolength-1] of pointer;
  31. shared: pointer;
  32. freefifolock: trtlcriticalsection;
  33. produce_thread: tproducethread;
  34. consume_thread: tconsumethread;
  35. constructor create;
  36. destructor destroy; override;
  37. procedure resume;
  38. procedure waitfor;
  39. end;
  40. var
  41. done: boolean;
  42. constructor tproducethread.create(apair: tpair);
  43. begin
  44. pair := apair;
  45. inherited create(false);
  46. end;
  47. constructor tconsumethread.create(apair: tpair);
  48. begin
  49. pair := apair;
  50. inherited create(false);
  51. end;
  52. constructor tpair.create;
  53. begin
  54. filldword(fifo, sizeof(fifo) div sizeof(dword), 0);
  55. readindex := 0;
  56. writeindex := 0;
  57. initcriticalsection(freefifolock);
  58. produce_thread := tproducethread.create(self);
  59. consume_thread := tconsumethread.create(self);
  60. end;
  61. destructor tpair.destroy;
  62. begin
  63. produce_thread.free;
  64. consume_thread.free;
  65. donecriticalsection(freefifolock);
  66. end;
  67. procedure tpair.resume;
  68. begin
  69. produce_thread.resume;
  70. consume_thread.resume;
  71. end;
  72. procedure tpair.waitfor;
  73. begin
  74. produce_thread.waitfor;
  75. consume_thread.waitfor;
  76. end;
  77. type
  78. ttestarray = array[0..31] of pointer;
  79. procedure exercise_heap(var p: ttestarray; var i, j: integer);
  80. begin
  81. if p[i] = nil then
  82. p[i] := getmem(((j*11) mod 532)+8)
  83. else begin
  84. freemem(p[i]);
  85. p[i] := nil;
  86. end;
  87. inc(i);
  88. if i >= 32 then
  89. dec(i, 32);
  90. inc(j, 13);
  91. if j >= 256 then
  92. dec(j, 256);
  93. end;
  94. procedure freearray(p: ppointer; count: integer);
  95. var
  96. i: integer;
  97. begin
  98. for i := 0 to count-1 do
  99. begin
  100. freemem(p[i]);
  101. p[i] := nil;
  102. end;
  103. end;
  104. procedure producer(pair: tpair);
  105. var
  106. p: ttestarray;
  107. i, j, k: longint;
  108. begin
  109. done := false;
  110. filldword(p, sizeof(p) div sizeof(dword), 0);
  111. i := 0;
  112. j := 0;
  113. k := 0;
  114. while not done do
  115. begin
  116. if ((pair.writeindex+1) mod fifolength) <> pair.readindex then
  117. begin
  118. { counterpart for the writebarrier in the consumer: ensure that we see
  119. the write to pair.fifo[pair.readindex] now that we've seen the write
  120. to pair.readindex }
  121. readbarrier;
  122. freemem(pair.fifo[pair.writeindex]);
  123. pair.fifo[pair.writeindex] := getmem(((pair.writeindex*17) mod 520)+8);
  124. writebarrier;
  125. pair.writeindex := (pair.writeindex + 1) mod 1024;
  126. end else begin
  127. exercise_heap(p,i,j);
  128. inc(k);
  129. if k = 100 then
  130. begin
  131. k := 0;
  132. ThreadSwitch;
  133. end;
  134. end;
  135. end;
  136. freearray(p, sizeof(p) div sizeof(pointer));
  137. entercriticalsection(pair.freefifolock);
  138. sleep(200);
  139. freearray(pair.fifo, sizeof(pair.fifo) div sizeof(pointer));
  140. freemem(pair.shared);
  141. leavecriticalsection(pair.freefifolock);
  142. end;
  143. procedure consumer(pair: tpair);
  144. var
  145. p: ttestarray;
  146. i, j, k: longint;
  147. begin
  148. done := false;
  149. filldword(p, sizeof(p) div sizeof(dword), 0);
  150. i := 0;
  151. j := 0;
  152. k := 0;
  153. entercriticalsection(pair.freefifolock);
  154. while not done do
  155. begin
  156. if pair.readindex <> pair.writeindex then
  157. begin
  158. { counterpart for the writebarrier in the producer: ensure that we see
  159. the write to pair.fifo[pair.writeindex] now that we've seen the write
  160. to pair.writeindex }
  161. readbarrier;
  162. freemem(pair.fifo[pair.readindex]);
  163. pair.fifo[pair.readindex] := getmem(((pair.writeindex*17) mod 520)+8);
  164. writebarrier;
  165. pair.readindex := (pair.readindex + 1) mod fifolength;
  166. end else begin
  167. exercise_heap(p,i,j);
  168. inc(k);
  169. if k = 100 then
  170. begin
  171. k := 0;
  172. ThreadSwitch;
  173. end;
  174. end;
  175. end;
  176. pair.shared := getmem(12);
  177. leavecriticalsection(pair.freefifolock);
  178. freearray(p, sizeof(p) div sizeof(pointer));
  179. end;
  180. procedure tproducethread.execute;
  181. begin
  182. running:=true;
  183. producer(pair);
  184. end;
  185. procedure tconsumethread.execute;
  186. begin
  187. running:=true;
  188. consumer(pair);
  189. end;
  190. const
  191. numpairs = 2;
  192. var
  193. pairs: array[1..numpairs] of tpair;
  194. i, iter, num_iterations: integer;
  195. begin
  196. num_iterations := 20;
  197. if paramcount > 0 then
  198. num_iterations := strtointdef(paramstr(1), num_iterations);
  199. for iter := 1 to num_iterations do
  200. begin
  201. done := false;
  202. for i := low(pairs) to high(pairs) do
  203. pairs[i] := tpair.create;
  204. for i := low(pairs) to high(pairs) do
  205. pairs[i].resume;
  206. { wait till all threads are really resumed }
  207. for i := low(pairs) to high(pairs) do
  208. while not(pairs[i].produce_thread.running) or not(pairs[i].consume_thread.running) do
  209. sleep(100);
  210. done := true;
  211. for i := low(pairs) to high(pairs) do
  212. begin
  213. pairs[i].waitfor;
  214. pairs[i].free;
  215. end;
  216. end;
  217. end.