tthread.inc 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258
  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. const StackSize: SizeUInt = DefaultStackSize);
  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;