tthread.inc 5.2 KB

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