theapthread.pp 4.3 KB

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