/examples/synchronize.pp

http://github.com/graemeg/lazarus · Puppet · 558 lines · 490 code · 68 blank · 0 comment · 25 complexity · ccdb47acbe0aa1fbeed51ae72f00c64d MD5 · raw file

  1. {
  2. /***************************************************************************
  3. synchronize - example
  4. ---------------------
  5. Just a simple example to show & verify functionality
  6. of the lazarus TThread.Synchronize / TProgressBar classes.
  7. Initial Revision : Sun Aug 15 1999
  8. by Stefan Hille <stoppok@osibisa.ms.sub.org>
  9. and Micha Nelissen
  10. ***************************************************************************/
  11. ***************************************************************************
  12. * *
  13. * This source is free software; you can redistribute it and/or modify *
  14. * it under the terms of the GNU General Public License as published by *
  15. * the Free Software Foundation; either version 2 of the License, or *
  16. * (at your option) any later version. *
  17. * *
  18. * This code is distributed in the hope that it will be useful, but *
  19. * WITHOUT ANY WARRANTY; without even the implied warranty of *
  20. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
  21. * General Public License for more details. *
  22. * *
  23. * A copy of the GNU General Public License is available on the World *
  24. * Wide Web at <http://www.gnu.org/copyleft/gpl.html>. You can also *
  25. * obtain it by writing to the Free Software Foundation, *
  26. * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
  27. * *
  28. ***************************************************************************
  29. }
  30. program Synchronize;
  31. {$mode objfpc}{$H+}
  32. { threading directive not needed anymore for 1.9.8+ }
  33. { $threading on}
  34. uses
  35. {$ifdef UNIX}
  36. CThreads,
  37. {$endif}
  38. Interfaces, Classes, StdCtrls, Forms, Buttons, Menus, ComCtrls,
  39. SysUtils, Extctrls;
  40. type
  41. TAThread = class(TThread)
  42. protected
  43. FTargetListBox: TListBox;
  44. FTargetProgress: TProgressBar;
  45. FTestStrings: TStrings;
  46. procedure ExecDone;
  47. procedure ShowStrings;
  48. public
  49. constructor Create(CreateSuspended: boolean);
  50. destructor Destroy; override;
  51. end;
  52. TThread1 = class(TAThread)
  53. public
  54. constructor Create;
  55. procedure Execute; override;
  56. end;
  57. TThread2 = class(TAThread)
  58. public
  59. constructor Create;
  60. procedure Execute; override;
  61. end;
  62. TForm1 = class(TForm)
  63. public
  64. Progre1: TProgressBar;
  65. Progre2: TProgressBar;
  66. Progre3: TProgressBar;
  67. Listbox1: TListBox;
  68. Listbox2: TListBox;
  69. Thread1: TThread1;
  70. Thread2: TThread2;
  71. ThreadList: TList;
  72. Button1: TButton;
  73. Button2: TButton;
  74. Button3: TButton;
  75. Button4: TButton;
  76. Button5: TButton;
  77. Button6: TButton;
  78. Button7: TButton;
  79. Button8: TButton;
  80. Button9: TButton;
  81. Button10: TButton;
  82. mnuFile: TMainMenu;
  83. itmFileQuit: TMenuItem;
  84. constructor Create(AOwner: TComponent); override;
  85. destructor Destroy; override;
  86. procedure LoadMainMenu;
  87. procedure mnuQuitClicked(Sender : TObject);
  88. protected
  89. procedure Button1CLick(Sender : TObject);
  90. procedure Button2CLick(Sender : TObject);
  91. procedure Button3CLick(Sender : TObject);
  92. procedure Button4CLick(Sender : TObject);
  93. procedure Button5CLick(Sender : TObject);
  94. procedure Button6CLick(Sender : TObject);
  95. procedure Button7CLick(Sender : TObject);
  96. procedure Button8CLick(Sender : TObject);
  97. procedure Button9CLick(Sender : TObject);
  98. procedure Button10CLick(Sender : TObject);
  99. function CloseQuery: boolean; override;
  100. end;
  101. threadvar
  102. threadvartest: integer;
  103. var
  104. Form1 : TForm1;
  105. TotalCount: integer;
  106. { GlobalData is an example of what you should NOT do :)
  107. Access from multiple threads to same variable unprotected }
  108. GlobalData: integer;
  109. constructor TAThread.Create(CreateSuspended: boolean);
  110. begin
  111. inherited;
  112. FTestStrings := TStringList.Create;
  113. end;
  114. destructor TAThread.Destroy;
  115. begin
  116. inherited;
  117. FTestStrings.Free;
  118. end;
  119. procedure TAThread.ExecDone;
  120. var
  121. lPos: integer;
  122. begin
  123. Form1.ThreadList.Remove(Self);
  124. FTargetListBox.Items.Insert(0, 'Thread terminated');
  125. if Form1.ThreadList.Count = 0 then
  126. begin
  127. lPos := Pos('[', Form1.Caption);
  128. if lPos > 0 then
  129. Form1.Caption := Copy(Form1.Caption, 1, lPos - 1) + '[done, ready to exit]';
  130. end;
  131. end;
  132. procedure TAThread.ShowStrings;
  133. var
  134. i: integer;
  135. begin
  136. FTargetListBox.Items.BeginUpdate;
  137. for i := 0 to FTestStrings.Count - 1 do
  138. begin
  139. FTargetListBox.Items.Insert(0, FTestStrings.Strings[i]);
  140. while FTargetListBox.Items.Count > 30 do
  141. FTargetListBox.Items.Delete(FTargetListBox.Items.Count-1);
  142. end;
  143. FTargetListBox.Items.EndUpdate;
  144. FTestStrings.Clear;
  145. if FTargetProgress.Position = FTargetProgress.Max then
  146. FTargetProgress.Position := FTargetProgress.Min;
  147. FTargetProgress.StepIt;
  148. end;
  149. constructor TThread1.Create;
  150. begin
  151. FTargetListBox := Form1.Listbox1;
  152. FTargetProgress := Form1.Progre1;
  153. FreeOnTerminate := true;
  154. inherited Create(false);
  155. end;
  156. function DoCalculation: integer;
  157. var
  158. i, k: integer;
  159. j: array[0..511] of integer;
  160. begin
  161. for i := 0 to 100000 do
  162. begin
  163. j[i mod $1ff] := i * i;
  164. k := j[(i + 3) and $1ff] div (i+1);
  165. j[(i + 5) and $1ff] := k - 3;
  166. end;
  167. result := j[5];
  168. end;
  169. procedure TThread1.Execute;
  170. var
  171. i: integer;
  172. begin
  173. threadvartest := 10;
  174. FTestStrings.Add('Threadvar is @'+IntToStr(ptrint(@threadvartest)));
  175. for i := 0 to TotalCount - 1 do
  176. begin
  177. GlobalData += 3;
  178. DoCalculation;
  179. FTestStrings.Add('Information: '+IntToStr(GlobalData-3)+' '+IntToStr(threadvartest));
  180. GlobalData -= 3;
  181. DoCalculation;
  182. Synchronize(@ShowStrings);
  183. threadvartest := 10;
  184. if Terminated then break;
  185. end;
  186. Synchronize(@ExecDone);
  187. end;
  188. constructor TThread2.Create;
  189. begin
  190. FTargetListBox := Form1.Listbox2;
  191. FTargetProgress := Form1.Progre2;
  192. FreeOnTerminate := true;
  193. inherited Create(false);
  194. end;
  195. procedure TThread2.Execute;
  196. var
  197. i: integer;
  198. begin
  199. threadvartest := 15;
  200. FTestStrings.Add('Threadvar is @'+IntToStr(ptrint(@threadvartest)));
  201. for i := 0 to TotalCount - 1 do
  202. begin
  203. GlobalData -= 3;
  204. DoCalculation;
  205. FTestStrings.Add('Information: '+IntToStr(GlobalData+3)+' '+IntToStr(threadvartest));
  206. threadvartest := 15;
  207. GlobalData += 3;
  208. DoCalculation;
  209. if (i and $3) = $3 then
  210. Synchronize(@ShowStrings);
  211. if Terminated then break;
  212. end;
  213. Synchronize(@ExecDone);
  214. end;
  215. constructor TForm1.Create(AOwner: TComponent);
  216. begin
  217. inherited CreateNew(AOwner, 1);
  218. Caption := 'Thread Synchronize Demo v0.1';
  219. ThreadList := TList.Create;
  220. LoadMainMenu;
  221. end;
  222. destructor TForm1.Destroy;
  223. begin
  224. inherited;
  225. FreeAndNil(ThreadList);
  226. end;
  227. function TForm1.CloseQuery: boolean;
  228. var
  229. I: integer;
  230. begin
  231. if ThreadList.Count > 0 then
  232. begin
  233. Caption := Caption + ' [wait for threads termination]';
  234. for I := 0 to ThreadList.Count - 1 do
  235. TThread(ThreadList.Items[I]).Terminate;
  236. Result := false;
  237. end else
  238. inherited;
  239. end;
  240. procedure TForm1.Button1Click(Sender : TObject);
  241. Begin
  242. if assigned (progre3) then begin
  243. progre3.Position := 0;
  244. progre3.Min := progre3.Min - 1
  245. end;
  246. End;
  247. procedure TForm1.Button2Click(Sender : TObject);
  248. Begin
  249. if assigned (progre3) then begin
  250. progre3.Position := 0;
  251. progre3.Min := progre3.Min + 1;
  252. end;
  253. End;
  254. procedure TForm1.Button3Click(Sender : TObject);
  255. Begin
  256. if assigned (progre3) then begin
  257. progre3.Position := 0;
  258. progre3.Max := progre3.Max +1;
  259. end;
  260. End;
  261. procedure TForm1.Button4Click(Sender : TObject);
  262. Begin
  263. if assigned (progre3) then begin
  264. progre3.Position := 0;
  265. progre3.Max := progre3.Max -1;
  266. end;
  267. End;
  268. procedure TForm1.Button10Click(Sender : TObject);
  269. Begin
  270. if assigned (progre3) then begin
  271. if progre3.position >= progre3.max then
  272. progre3.position := progre3.min;
  273. progre3.stepit;
  274. end;
  275. End;
  276. procedure TForm1.Button5Click(Sender : TObject);
  277. Begin
  278. if assigned (progre1) then begin
  279. Progre1.Smooth := not Progre1.Smooth;
  280. if assigned (Button6)
  281. then Button6.Visible := Progre1.Smooth;
  282. end;
  283. End;
  284. procedure TForm1.Button6Click(Sender : TObject);
  285. Begin
  286. if assigned (progre1) then begin
  287. Progre1.BarShowtext := not Progre1.BarShowtext;
  288. end;
  289. End;
  290. procedure TForm1.Button7Click(Sender : TObject);
  291. Begin
  292. if assigned (progre1) then
  293. begin
  294. case Progre1.Orientation of
  295. pbVertical : Progre1.Orientation := pbRightToLeft;
  296. pbRightToLeft : Progre1.Orientation := pbTopDown;
  297. pbTopDown : Progre1.Orientation := pbHorizontal;
  298. pbHorizontal : Progre1.Orientation := pbVertical;
  299. end;
  300. end;
  301. end;
  302. procedure TForm1.Button8Click(Sender : TObject);
  303. begin
  304. { Create the threads }
  305. TotalCount := 1000;
  306. GlobalData := 100;
  307. threadvartest := 20;
  308. Thread1 := TThread1.Create;
  309. Thread2 := TThread2.Create;
  310. ThreadList.Add(Thread1);
  311. ThreadList.Add(Thread2);
  312. End;
  313. procedure TForm1.Button9Click(Sender : TObject);
  314. begin
  315. Listbox1.Items.Clear;
  316. Listbox2.Items.Clear;
  317. end;
  318. {------------------------------------------------------------------------------}
  319. procedure TForm1.LoadMainMenu;
  320. begin
  321. { set the height and width }
  322. Height := 350;
  323. Width := 700;
  324. { Create a progressbar }
  325. Progre1 := TProgressBar.Create (Self);
  326. with Progre1 do
  327. begin
  328. Parent := Self;
  329. SetBounds(300, 10, 250, 20);
  330. Min := 0;
  331. Max := 10;
  332. Step := 1;
  333. BarShowText := true;
  334. Smooth := True;
  335. Show;
  336. end;
  337. Progre2 := TProgressBar.Create (Self);
  338. with Progre2 do
  339. begin
  340. Parent := Self;
  341. SetBounds(300, 35, 250, 20);
  342. Min := 0;
  343. Max := 10;
  344. Step := 1;
  345. BarShowText := true;
  346. Smooth := True;
  347. Show;
  348. end;
  349. Progre3 := TProgressBar.Create (Self);
  350. with Progre3 do
  351. begin
  352. Parent := Self;
  353. SetBounds(300, 60, 250, 20);
  354. Min := 0;
  355. Max := 10;
  356. Step := 1;
  357. BarShowText := true;
  358. Smooth := True;
  359. Show;
  360. end;
  361. { create listboxes to show thread results }
  362. Listbox1 := TListBox.Create(self);
  363. with Listbox1 do
  364. begin
  365. Parent := self;
  366. SetBounds(10, 120, 200, 180);
  367. end;
  368. Listbox2 := TListBox.Create(self);
  369. with Listbox2 do
  370. begin
  371. Parent := self;
  372. SetBounds(250, 120, 200, 180);
  373. end;
  374. { Create a few buttons }
  375. Button2 := TButton.Create(Self);
  376. Button2.Parent := Self;
  377. Button2.Left := 200;
  378. Button2.Top := 70;
  379. Button2.Width := 80;
  380. Button2.Height := 30;
  381. Button2.Show;
  382. Button2.Caption := 'PMin ++';
  383. // Button2.ToolTip := 'Tool Tip';
  384. // Button2.ShowToolTip := True;
  385. Button2.OnClick := @Button2Click;
  386. Button1 := TButton.Create(Self);
  387. Button1.Parent := Self;
  388. Button1.Left := 50;
  389. Button1.Top := 70;
  390. Button1.Width := 80;
  391. Button1.Height := 30;
  392. Button1.Show;
  393. Button1.Caption := 'PMin--';
  394. Button1.OnClick := @Button1Click;
  395. { Create 2 more buttons outside the groupbox }
  396. Button3 := TButton.Create(Self);
  397. Button3.Parent := Self;
  398. Button3.Left := 50;
  399. Button3.Top := 30;
  400. Button3.Width := 80;
  401. Button3.Height := 30;
  402. Button3.Show;
  403. Button3.Caption := 'PMax++';
  404. // Button3.ToolTip := 'Tool Tip';
  405. // Button3.ShowToolTip := True;
  406. Button3.OnClick := @Button3Click;
  407. Button4 := TButton.Create(Self);
  408. Button4.Parent := Self;
  409. Button4.Left := 200;
  410. Button4.Top := 30;
  411. Button4.Width := 80;
  412. Button4.Height := 30;
  413. Button4.Show;
  414. Button4.Caption := 'PMax--';
  415. Button4.OnClick := @Button4Click;
  416. Button10 := TButton.Create(Self);
  417. with Button10 do
  418. begin
  419. Parent := Self;
  420. SetBounds(140, 30, 50, 30);
  421. Show;
  422. Caption := 'Step It';
  423. OnClick := @Button10Click;
  424. end;
  425. Button5 := TButton.Create(Self);
  426. Button5.Parent := Self;
  427. Button5.Left := 500;
  428. Button5.Top := 110;
  429. Button5.Width := 130;
  430. Button5.Height := 30;
  431. Button5.Show;
  432. Button5.Caption := 'Toggle Smooth';
  433. Button5.OnClick := @Button5Click;
  434. Button6 := TButton.Create(Self);
  435. Button6.Parent := Self;
  436. Button6.Left := 500;
  437. Button6.Top := 150;
  438. Button6.Width := 130;
  439. Button6.Height := 30;
  440. Button6.Show;
  441. Button6.Caption := 'Toggle Text';
  442. Button6.OnClick := @Button6Click;
  443. Button6.Visible := Progre1.Smooth;
  444. Button7 := TButton.Create(Self);
  445. Button7.Parent := Self;
  446. Button7.Left := 500;
  447. Button7.Top := 190;
  448. Button7.Width := 130;
  449. Button7.Height := 30;
  450. Button7.Show;
  451. Button7.Caption := 'Orientation';
  452. Button7.OnClick := @Button7Click;
  453. Button8 := TButton.Create(Self);
  454. with Button8 do
  455. begin
  456. Parent := Self;
  457. SetBounds(500, 230, 130, 30);
  458. Show;
  459. Caption := 'Thread test';
  460. OnClick := @Button8Click;
  461. end;
  462. Button9 := TButton.Create(Self);
  463. with Button9 do
  464. begin
  465. Parent := Self;
  466. SetBounds(500, 270, 130, 30);
  467. Show;
  468. Caption := 'Clear listboxes';
  469. OnClick := @Button9Click;
  470. end;
  471. { create a menubar }
  472. mnuFile := TMainMenu.Create(Self);
  473. mnuFile.Name:='mnuFile';
  474. Menu := mnuFile;
  475. itmFileQuit := TMenuItem.Create(Self);
  476. itmFileQuit.Caption := 'Quit';
  477. itmFileQuit.OnClick := @mnuQuitClicked;
  478. mnuFile.Items.Add(itmFileQuit);
  479. end;
  480. {------------------------------------------------------------------------------}
  481. procedure TForm1.mnuQuitClicked(Sender : TObject);
  482. begin
  483. Close;
  484. end;
  485. {------------------------------------------------------------------------------}
  486. begin
  487. Application.Initialize; { calls InitProcedure which starts up GTK }
  488. Application.CreateForm(TForm1, Form1);
  489. Application.Run;
  490. end.