tthread.inc 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268
  1. {
  2. $Id$
  3. This file is part of the Free Component Library (FCL)
  4. Copyright (c) 2003-2004 Armin Diehl, member of the Free Pascal
  5. development team
  6. Netware clib TThread implementation
  7. See the file COPYING.FPC, included in this distribution,
  8. for details about the copyright.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  12. **********************************************************************}
  13. type
  14. PThreadRec=^TThreadRec;
  15. TThreadRec=record
  16. thread : TThread;
  17. next : PThreadRec;
  18. end;
  19. var
  20. ThreadRoot : PThreadRec;
  21. ThreadsInited : boolean;
  22. DisableRemoveThread : boolean;
  23. Const
  24. ThreadCount: longint = 0;
  25. {function ThreadSelf:TThread;
  26. var
  27. hp : PThreadRec;
  28. sp : longint;
  29. begin
  30. sp:=SPtr;
  31. hp:=ThreadRoot;
  32. while assigned(hp) do
  33. begin
  34. if (sp<=hp^.Thread.FStackPointer) and
  35. (sp>(hp^.Thread.FStackPointer-hp^.Thread.FStackSize)) then
  36. begin
  37. Result:=hp^.Thread;
  38. exit;
  39. end;
  40. hp:=hp^.next;
  41. end;
  42. Result:=nil;
  43. end;}
  44. procedure InitThreads;
  45. begin
  46. ThreadRoot:=nil;
  47. ThreadsInited:=true;
  48. DisableRemoveThread:=false;
  49. end;
  50. {DoneThreads will terminate all remaining threads}
  51. procedure DoneThreads;
  52. var
  53. hp,next : PThreadRec;
  54. begin
  55. DisableRemoveThread := true; {to avoid that Destroy calling RemoveThread modifies Thread List}
  56. while assigned(ThreadRoot) do
  57. begin
  58. ThreadRoot^.Thread.Destroy;
  59. hp:=ThreadRoot;
  60. ThreadRoot:=ThreadRoot^.Next;
  61. dispose(hp);
  62. {$ifdef DEBUG_MT}
  63. ConsolePrintf(#13'DoneThreads: called destroy, remaining threads: %d ThreadRoot: %x'#13#10,ThreadCount,longint(ThreadRoot));
  64. {$endif}
  65. end;
  66. ThreadsInited:=false;
  67. end;
  68. procedure AddThread(t:TThread);
  69. var
  70. hp : PThreadRec;
  71. begin
  72. { Need to initialize threads ? }
  73. if not ThreadsInited then
  74. InitThreads;
  75. { Put thread in the linked list }
  76. new(hp);
  77. hp^.Thread:=t;
  78. hp^.next:=ThreadRoot;
  79. ThreadRoot:=hp;
  80. inc(ThreadCount);
  81. end;
  82. procedure RemoveThread(t:TThread);
  83. var
  84. lasthp,hp : PThreadRec;
  85. begin
  86. if not DisableRemoveThread then {disabled while in DoneThreads}
  87. begin
  88. hp:=ThreadRoot;
  89. lasthp:=nil;
  90. while assigned(hp) do
  91. begin
  92. if hp^.Thread=t then
  93. begin
  94. if assigned(lasthp) then
  95. lasthp^.next:=hp^.next
  96. else
  97. ThreadRoot:=hp^.next;
  98. dispose(hp);
  99. Dec(ThreadCount);
  100. if ThreadCount = 0 then ThreadsInited := false;
  101. exit;
  102. end;
  103. lasthp:=hp;
  104. hp:=hp^.next;
  105. end;
  106. end else
  107. dec(ThreadCount);
  108. end;
  109. { TThread }
  110. function ThreadProc(args:pointer): Integer;
  111. var
  112. FreeThread: Boolean;
  113. Thread : TThread absolute args;
  114. begin
  115. try
  116. Thread.Execute;
  117. except
  118. Thread.FFatalException := TObject(AcquireExceptionObject);
  119. end;
  120. FreeThread := Thread.FFreeOnTerminate;
  121. ThreadProc := Thread.FReturnValue;
  122. Thread.FFinished := True;
  123. Thread.DoTerminate;
  124. if FreeThread then
  125. begin
  126. Thread.Destroy;
  127. Thread.Free;
  128. end;
  129. EndThread(Result);
  130. end;
  131. constructor TThread.Create(CreateSuspended: Boolean);
  132. var
  133. Flags: Integer;
  134. begin
  135. inherited Create;
  136. AddThread(self);
  137. FSuspended := CreateSuspended;
  138. { Create new thread }
  139. FHandle := BeginThread (@ThreadProc,pointer(self));
  140. if FSuspended then Suspend;
  141. FThreadID := FHandle;
  142. FFatalException := nil;
  143. end;
  144. destructor TThread.Destroy;
  145. begin
  146. if not FFinished then
  147. begin
  148. Terminate;
  149. if Suspended then
  150. ResumeThread (FHandle); {netware can not kill a thread, the thread has to}
  151. {leave it's execute routine if terminated is true}
  152. WaitFor; {wait for the thread to terminate}
  153. end;
  154. FFatalException.Free;
  155. FFatalException := nil;
  156. inherited Destroy;
  157. RemoveThread(self); {remove it from the list of active threads}
  158. end;
  159. procedure TThread.CallOnTerminate;
  160. begin
  161. FOnTerminate(Self);
  162. end;
  163. procedure TThread.DoTerminate;
  164. begin
  165. if Assigned(FOnTerminate) then
  166. Synchronize(@CallOnTerminate);
  167. end;
  168. const
  169. Priorities: array [TThreadPriority] of Integer =
  170. (THREAD_PRIORITY_IDLE, THREAD_PRIORITY_LOWEST, THREAD_PRIORITY_BELOW_NORMAL,
  171. THREAD_PRIORITY_NORMAL, THREAD_PRIORITY_ABOVE_NORMAL,
  172. THREAD_PRIORITY_HIGHEST, THREAD_PRIORITY_TIME_CRITICAL);
  173. function TThread.GetPriority: TThreadPriority;
  174. var
  175. P: Integer;
  176. I: TThreadPriority;
  177. begin
  178. P := ThreadGetPriority(FHandle);
  179. Result := tpNormal;
  180. for I := Low(TThreadPriority) to High(TThreadPriority) do
  181. if Priorities[I] = P then Result := I;
  182. end;
  183. procedure TThread.SetPriority(Value: TThreadPriority);
  184. begin
  185. ThreadSetPriority(FHandle, Priorities[Value]);
  186. end;
  187. procedure TThread.SetSuspended(Value: Boolean);
  188. begin
  189. if Value <> FSuspended then
  190. if Value then
  191. Suspend
  192. else
  193. Resume;
  194. end;
  195. procedure TThread.Suspend;
  196. begin
  197. SuspendThread (FHandle);
  198. FSuspended := true;
  199. end;
  200. procedure TThread.Resume;
  201. begin
  202. ResumeThread (FHandle);
  203. FSuspended := False;
  204. end;
  205. procedure TThread.Terminate;
  206. begin
  207. FTerminated := True;
  208. ThreadSwitch;
  209. end;
  210. function TThread.WaitFor: Integer;
  211. begin
  212. Result := WaitForThreadTerminate (FHandle,0);
  213. if Result = 0 then
  214. FHandle := 0;
  215. end;
  216. {
  217. $Log$
  218. Revision 1.5 2005-02-25 21:41:09 florian
  219. * generic tthread.synchronize
  220. * delphi compatible wakemainthread
  221. Revision 1.4 2005/02/14 17:13:30 peter
  222. * truncate log
  223. }