tthread.inc 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298
  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. {does not make sense for netware}
  188. procedure TThread.Synchronize(Method: TThreadMethod);
  189. begin
  190. (*
  191. FSynchronizeException := nil;
  192. FMethod := Method;
  193. { SendMessage(ThreadWindow, CM_EXECPROC, 0, Longint(Self)); }
  194. {$warning Synchronize needs implementation}
  195. if Assigned(FSynchronizeException) then
  196. raise FSynchronizeException;
  197. *)
  198. end;
  199. procedure TThread.SetSuspended(Value: Boolean);
  200. begin
  201. if Value <> FSuspended then
  202. if Value then
  203. Suspend
  204. else
  205. Resume;
  206. end;
  207. procedure TThread.Suspend;
  208. begin
  209. SuspendThread (FHandle);
  210. FSuspended := true;
  211. end;
  212. procedure TThread.Resume;
  213. begin
  214. ResumeThread (FHandle);
  215. FSuspended := False;
  216. end;
  217. procedure TThread.Terminate;
  218. begin
  219. FTerminated := True;
  220. ThreadSwitch;
  221. end;
  222. function TThread.WaitFor: Integer;
  223. begin
  224. Result := WaitForThreadTerminate (FHandle,0);
  225. if Result = 0 then
  226. FHandle := 0;
  227. end;
  228. {
  229. $Log$
  230. Revision 1.3 2004-09-26 19:25:49 armin
  231. * exiting threads at nlm unload
  232. Revision 1.2 2004/07/30 15:05:25 armin
  233. make netware rtl compilable under 1.9.5
  234. Revision 1.1 2003/10/06 21:01:06 peter
  235. * moved classes unit to rtl
  236. Revision 1.3 2003/10/06 17:06:55 florian
  237. * applied Johannes Berg's patch for exception handling in threads
  238. Revision 1.2 2003/03/27 17:14:27 armin
  239. * more platform independent thread routines, needs to be implemented for unix
  240. Revision 1.1 2003/03/25 17:56:19 armin
  241. * first fcl implementation for netware
  242. Revision 1.7 2002/12/18 20:44:36 peter
  243. * use fillchar to clear sigset
  244. Revision 1.6 2002/09/07 15:15:27 peter
  245. * old logs removed and tabs fixed
  246. }