testmtp1.lpr 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367
  1. program TestMTP1;
  2. {$mode objfpc}{$H+}
  3. uses
  4. {$IFDEF UNIX}
  5. cthreads, cmem,
  6. {$ENDIF}
  7. Math, SysUtils, Classes, MTProcs, MTPUtils, MultiThreadProcsLaz;
  8. type
  9. { TTestItem }
  10. TTestItem = class
  11. private
  12. FIndex: int64;
  13. public
  14. property Index: int64 read FIndex;
  15. constructor Create(NewIndex: int64);
  16. end;
  17. { TTests }
  18. TTests = class
  19. public
  20. procedure Work(Seconds: integer);
  21. // RTLeventSetEvent, RTLeventWaitFor
  22. procedure TestRTLevent_Set_WaitFor;
  23. // single thread test
  24. procedure TestSingleThread;
  25. procedure MTPLoop_TestSingleThread(Index: PtrInt; Data: Pointer;
  26. Item: TMultiThreadProcItem);
  27. // two threads test: run once
  28. procedure TestTwoThreads1;
  29. procedure MTPLoop_TestTwoThreads1(Index: PtrInt; Data: Pointer;
  30. Item: TMultiThreadProcItem);
  31. // 0 runs two seconds,
  32. // 1 runs a second then waits for 0 then runs a second
  33. // 2 runs a second then waits for 1
  34. // 3 waits for 0
  35. // 4 waits for 1
  36. // 5 waits for 2
  37. procedure TestMTPWaitForIndex;
  38. procedure MTPLoop_TestMTPWaitForIndex(Index: PtrInt; Data: Pointer;
  39. Item: TMultiThreadProcItem);
  40. // two threads test: various run times
  41. procedure TestMTPTwoThreads2;
  42. procedure MTPLoop_TestTwoThreads2(Index: PtrInt; Data: Pointer;
  43. Item: TMultiThreadProcItem);
  44. // test exception in starter thread
  45. procedure TestMTPExceptionInStarterThread;
  46. procedure MTPLoop_TestExceptionInStarterThread(Index: PtrInt; Data: Pointer;
  47. Item: TMultiThreadProcItem);
  48. // test exception in helper thread
  49. procedure TestMTPExceptionInHelperThread;
  50. procedure MTPLoop_TestExceptionInHelperThread(Index: PtrInt; Data: Pointer;
  51. Item: TMultiThreadProcItem);
  52. // test parallel sort
  53. procedure TestMTPSort;
  54. procedure MTPLoop_TestDoubleMTPSort(Index: PtrInt; Data: Pointer;
  55. Item: TMultiThreadProcItem);
  56. end;
  57. { TTestItem }
  58. constructor TTestItem.Create(NewIndex: int64);
  59. begin
  60. FIndex:=NewIndex;
  61. end;
  62. { TTests }
  63. procedure TTests.Work(Seconds: integer);
  64. var
  65. Start: TDateTime;
  66. begin
  67. Start:=Now;
  68. while (Now-Start)*86400<Seconds do if GetCurrentDir='' then ;
  69. end;
  70. procedure TTests.TestRTLevent_Set_WaitFor;
  71. var
  72. e: PRTLEvent;
  73. begin
  74. e:=RTLEventCreate;
  75. RTLeventSetEvent(e);
  76. RTLeventWaitFor(e);
  77. RTLeventdestroy(e);
  78. end;
  79. procedure TTests.TestSingleThread;
  80. begin
  81. ProcThreadPool.DoParallel(@MTPLoop_TestSingleThread,1,3,nil,1);
  82. end;
  83. procedure TTests.MTPLoop_TestSingleThread(Index: PtrInt; Data: Pointer;
  84. Item: TMultiThreadProcItem);
  85. begin
  86. writeln('TTests.MTPLoop_TestSingleThread Index=',Index);
  87. end;
  88. procedure TTests.TestTwoThreads1;
  89. begin
  90. WriteLn('TTests.TestTwoThreads1 START');
  91. ProcThreadPool.DoParallel(@MTPLoop_TestTwoThreads1,1,2,nil,2);
  92. WriteLn('TTests.TestTwoThreads1 END');
  93. end;
  94. procedure TTests.MTPLoop_TestTwoThreads1(Index: PtrInt; Data: Pointer;
  95. Item: TMultiThreadProcItem);
  96. var
  97. i: Integer;
  98. begin
  99. for i:=1 to 3 do begin
  100. WriteLn('TTests.MTPLoop_TestTwoThreads1 Index=',Index,' ',i);
  101. Work(1);
  102. end;
  103. end;
  104. procedure TTests.TestMTPWaitForIndex;
  105. var
  106. IndexStates: PInteger;
  107. begin
  108. ProcThreadPool.MaxThreadCount:=8;
  109. IndexStates:=nil;
  110. GetMem(IndexStates,SizeOf(Integer)*10);
  111. FillByte(IndexStates^,SizeOf(Integer)*10,0);
  112. WriteLn('TTests.TestMTPWaitForIndex START');
  113. ProcThreadPool.DoParallel(@MTPLoop_TestMTPWaitForIndex,0,5,IndexStates);
  114. FreeMem(IndexStates);
  115. WriteLn('TTests.TestMTPWaitForIndex END');
  116. end;
  117. procedure TTests.MTPLoop_TestMTPWaitForIndex(Index: PtrInt; Data: Pointer;
  118. Item: TMultiThreadProcItem);
  119. // 0 runs two seconds,
  120. // 1 runs a second then waits for 0 then runs a second
  121. // 2 runs a second then waits for 1
  122. // 3 waits for 0
  123. // 4 waits for 1
  124. // 5 waits for 2
  125. procedure WaitFor(OtherIndex: PtrInt);
  126. begin
  127. WriteLn('TTests.MTPLoop_TestMTPWaitForIndex Index='+IntToStr(Index)+' waiting for '+IntToStr(OtherIndex)+' ...');
  128. Item.WaitForIndex(OtherIndex);
  129. WriteLn('TTests.MTPLoop_TestMTPWaitForIndex Index='+IntToStr(Index)+' waited for '+IntToStr(OtherIndex)+'. working ...');
  130. if PInteger(Data)[OtherIndex]<>2 then begin
  131. WriteLn('TTests.MTPLoop_TestMTPWaitForIndex Index='+IntToStr(Index)+' ERROR: waited for '+IntToStr(OtherIndex)+' failed: OtherState='+IntToStr(PInteger(Data)[OtherIndex]));
  132. end;
  133. end;
  134. begin
  135. WriteLn('TTests.MTPLoop_TestMTPWaitForIndex Index='+IntToStr(Index)+' START');
  136. if PInteger(Data)[Index]<>0 then begin
  137. WriteLn('TTests.MTPLoop_TestMTPWaitForIndex Index='+IntToStr(Index)+' ERROR: IndexState='+IntToStr(PInteger(Data)[Index]));
  138. end;
  139. PInteger(Data)[Index]:=1;
  140. case Index of
  141. 0: Work(2);
  142. 1:begin
  143. Work(1);
  144. WaitFor(0);
  145. Work(1);
  146. end;
  147. 2:begin
  148. Work(1);
  149. WaitFor(1);
  150. end;
  151. 3:begin
  152. WaitFor(0);
  153. end;
  154. 4:begin
  155. WaitFor(1);
  156. end;
  157. 5:begin
  158. WaitFor(2);
  159. end;
  160. end;
  161. WriteLn('TTests.MTPLoop_TestMTPWaitForIndex Index='+IntToStr(Index)+' END');
  162. PInteger(Data)[Index]:=2;
  163. end;
  164. procedure TTests.TestMTPTwoThreads2;
  165. begin
  166. WriteLn('TTests.TestMTPTwoThreads1 START');
  167. ProcThreadPool.DoParallel(@MTPLoop_TestTwoThreads2,1,6,nil,2);
  168. WriteLn('TTests.TestMTPTwoThreads1 END');
  169. end;
  170. procedure TTests.MTPLoop_TestTwoThreads2(Index: PtrInt; Data: Pointer;
  171. Item: TMultiThreadProcItem);
  172. var
  173. i: Integer;
  174. begin
  175. for i:=1 to (Index mod 3)+1 do begin
  176. WriteLn('TTests.MTPLoop_TestTwoThreads1 Index=',Index,' i=',i,' ID=',PtrUint(GetThreadID));
  177. Work(1);
  178. end;
  179. end;
  180. type
  181. TMyException = class(Exception);
  182. procedure TTests.TestMTPExceptionInStarterThread;
  183. var
  184. IndexStates: PInteger;
  185. begin
  186. WriteLn('TTests.TestMTPExceptionInStarterThread START');
  187. ProcThreadPool.MaxThreadCount:=8;
  188. IndexStates:=nil;
  189. GetMem(IndexStates,SizeOf(Integer)*10);
  190. FillByte(IndexStates^,SizeOf(Integer)*10,0);
  191. try
  192. ProcThreadPool.DoParallel(@MTPLoop_TestExceptionInStarterThread,1,3,IndexStates,2);
  193. except
  194. on E: Exception do begin
  195. WriteLn('TTests.TestMTPExceptionInHelperThread E.ClassName=',E.ClassName,' E.Message=',E.Message);
  196. end;
  197. end;
  198. FreeMem(IndexStates);
  199. WriteLn('TTests.TestMTPExceptionInStarterThread END');
  200. end;
  201. procedure TTests.MTPLoop_TestExceptionInStarterThread(Index: PtrInt;
  202. Data: Pointer; Item: TMultiThreadProcItem);
  203. begin
  204. WriteLn('TTests.MTPLoop_TestExceptionInStarterThread START Index='+IntToStr(Index));
  205. if PInteger(Data)[Index]<>0 then
  206. WriteLn('TTests.MTPLoop_TestExceptionInStarterThread Index='+IntToStr(Index)+' ERROR: IndexState='+IntToStr(PInteger(Data)[Index]));
  207. PInteger(Data)[Index]:=1;
  208. case Index of
  209. 1:
  210. begin
  211. // Main Thread
  212. Work(1);
  213. WriteLn('TTests.MTPLoop_TestExceptionInStarterThread raising exception in Index='+IntToStr(Index)+' ...');
  214. raise Exception.Create('Exception in starter thread');
  215. end;
  216. else
  217. Work(Index);
  218. end;
  219. PInteger(Data)[Index]:=2;
  220. WriteLn('TTests.MTPLoop_TestExceptionInStarterThread END Index='+IntToStr(Index));
  221. end;
  222. procedure TTests.TestMTPExceptionInHelperThread;
  223. var
  224. IndexStates: PInteger;
  225. begin
  226. WriteLn('TTests.TestMTPExceptionInHelperThread START');
  227. ProcThreadPool.MaxThreadCount:=8;
  228. IndexStates:=nil;
  229. GetMem(IndexStates,SizeOf(Integer)*10);
  230. FillByte(IndexStates^,SizeOf(Integer)*10,0);
  231. try
  232. ProcThreadPool.DoParallel(@MTPLoop_TestExceptionInHelperThread,1,3,IndexStates,2);
  233. except
  234. on E: Exception do begin
  235. WriteLn('TTests.TestMTPExceptionInHelperThread E.ClassName=',E.ClassName,' E.Message=',E.Message);
  236. end;
  237. end;
  238. FreeMem(IndexStates);
  239. WriteLn('TTests.TestMTPExceptionInHelperThread END');
  240. end;
  241. procedure TTests.MTPLoop_TestExceptionInHelperThread(Index: PtrInt;
  242. Data: Pointer; Item: TMultiThreadProcItem);
  243. begin
  244. WriteLn('TTests.MTPLoop_TestExceptionInHelperThread START Index='+IntToStr(Index));
  245. if PInteger(Data)[Index]<>0 then
  246. WriteLn('TTests.MTPLoop_TestExceptionInHelperThread Index='+IntToStr(Index)+' ERROR: IndexState='+IntToStr(PInteger(Data)[Index]));
  247. PInteger(Data)[Index]:=1;
  248. case Index of
  249. 2:
  250. begin
  251. // Helper Thread 2
  252. Work(1);
  253. WriteLn('TTests.MTPLoop_TestExceptionInHelperThread raising exception in Index='+IntToStr(Index)+' ...');
  254. raise TMyException.Create('Exception in helper thread');
  255. end;
  256. else
  257. Work(Index+1);
  258. end;
  259. PInteger(Data)[Index]:=2;
  260. WriteLn('TTests.MTPLoop_TestExceptionInHelperThread END Index='+IntToStr(Index));
  261. end;
  262. function CompareTestItems(Data1, Data2: Pointer): integer;
  263. begin
  264. if TTestItem(Data1).Index>TTestItem(Data2).Index then
  265. Result:=1
  266. else if TTestItem(Data1).Index<TTestItem(Data2).Index then
  267. Result:=-1
  268. else
  269. Result:=0;
  270. end;
  271. procedure TTests.TestMTPSort;
  272. var
  273. OuterLoop: Integer;
  274. InnerLoop: Integer;
  275. begin
  276. OuterLoop:=1;
  277. InnerLoop:=0;
  278. if Paramcount=1 then begin
  279. InnerLoop:=StrToInt(ParamStr(1));
  280. end else if Paramcount=2 then begin
  281. OuterLoop:=StrToInt(ParamStr(1));
  282. InnerLoop:=StrToInt(ParamStr(2));
  283. end;
  284. writeln('TTests.TestMTPSort Running ',OuterLoop,'x',InnerLoop);
  285. ProcThreadPool.DoParallel(@MTPLoop_TestDoubleMTPSort,1,OuterLoop,@InnerLoop);
  286. end;
  287. procedure TTests.MTPLoop_TestDoubleMTPSort(Index: PtrInt; Data: Pointer;
  288. Item: TMultiThreadProcItem);
  289. var
  290. i: Integer;
  291. List: TFPList;
  292. t: double;
  293. begin
  294. // create an unsorted list of values
  295. List:=TFPList.Create;
  296. for i:=1 to 10000000 do List.Add(TTestItem.Create(Random(99999999999)));
  297. //QuickSort(List,0,List.Count-1,@AnsiCompareText);
  298. t:=Now;
  299. ParallelSortFPList(List,@CompareTestItems,PInteger(Data)^);
  300. t:=Now-t;
  301. writeln('TTests.TestMTPSort ',t*86400);
  302. // check
  303. sleep(1);
  304. for i:=0 to List.Count-2 do
  305. if CompareTestItems(List[i],List[i+1])>0 then raise Exception.Create('not sorted');
  306. for i:=0 to List.Count-1 do
  307. TObject(List[i]).Free;
  308. List.Free;
  309. end;
  310. var
  311. Tests: TTests;
  312. begin
  313. writeln('threads=',ProcThreadPool.MaxThreadCount);
  314. ProcThreadPool.MaxThreadCount:=8;
  315. Tests:=TTests.Create;
  316. //Tests.Test1;
  317. //Tests.Test2;
  318. //Tests.TestTwoThreads2;
  319. //Tests.TestRTLevent_Set_WaitFor;
  320. //Tests.TestMTPWaitForIndex;
  321. //Tests.TestMTPExceptionInStarterThread;
  322. Tests.TestMTPExceptionInHelperThread;
  323. //Tests.TestMTPSort;
  324. Tests.Free;
  325. end.