thread.inc 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268
  1. {
  2. $Id$
  3. This file is part of the Free Component Library (FCL)
  4. Copyright (c) 1999-2003 by the Free Pascal development team
  5. Netware 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. // MainThreadID: longint;
  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. end;
  48. procedure DoneThreads;
  49. var
  50. hp : PThreadRec;
  51. begin
  52. while assigned(ThreadRoot) do
  53. begin
  54. ThreadRoot^.Thread.Destroy;
  55. hp:=ThreadRoot;
  56. ThreadRoot:=ThreadRoot^.Next;
  57. dispose(hp);
  58. end;
  59. ThreadsInited:=false;
  60. end;
  61. procedure AddThread(t:TThread);
  62. var
  63. hp : PThreadRec;
  64. begin
  65. { Need to initialize threads ? }
  66. if not ThreadsInited then
  67. InitThreads;
  68. { Put thread in the linked list }
  69. new(hp);
  70. hp^.Thread:=t;
  71. hp^.next:=ThreadRoot;
  72. ThreadRoot:=hp;
  73. inc(ThreadCount, 1);
  74. end;
  75. procedure RemoveThread(t:TThread);
  76. var
  77. lasthp,hp : PThreadRec;
  78. begin
  79. hp:=ThreadRoot;
  80. lasthp:=nil;
  81. while assigned(hp) do
  82. begin
  83. if hp^.Thread=t then
  84. begin
  85. if assigned(lasthp) then
  86. lasthp^.next:=hp^.next
  87. else
  88. ThreadRoot:=hp^.next;
  89. dispose(hp);
  90. exit;
  91. end;
  92. lasthp:=hp;
  93. hp:=hp^.next;
  94. end;
  95. Dec(ThreadCount, 1);
  96. if ThreadCount = 0 then DoneThreads;
  97. end;
  98. { TThread }
  99. function ThreadProc(args:pointer): Integer;cdecl;
  100. var
  101. FreeThread: Boolean;
  102. Thread : TThread absolute args;
  103. begin
  104. Thread.Execute;
  105. FreeThread := Thread.FFreeOnTerminate;
  106. Result := Thread.FReturnValue;
  107. Thread.FFinished := True;
  108. Thread.DoTerminate;
  109. if FreeThread then
  110. Thread.Free;
  111. EndThread(Result);
  112. end;
  113. constructor TThread.Create(CreateSuspended: Boolean);
  114. var
  115. Flags: Integer;
  116. begin
  117. inherited Create;
  118. AddThread(self);
  119. FSuspended := CreateSuspended;
  120. { Create new thread }
  121. FHandle := BeginThread (@ThreadProc,self);
  122. if FSuspended then Suspend;
  123. FThreadID := FHandle;
  124. //IsMultiThread := TRUE; {already set by systhrds}
  125. end;
  126. destructor TThread.Destroy;
  127. begin
  128. if not FFinished {and not Suspended} then
  129. begin
  130. if Suspended then ResumeThread (FHandle); {netware can not kill a thread}
  131. Terminate;
  132. WaitFor;
  133. end;
  134. if FHandle <> -1 then
  135. KillThread (FHandle); {something went wrong, kill the thread (not possible on netware)}
  136. inherited Destroy;
  137. RemoveThread(self);
  138. end;
  139. procedure TThread.CallOnTerminate;
  140. begin
  141. FOnTerminate(Self);
  142. end;
  143. procedure TThread.DoTerminate;
  144. begin
  145. if Assigned(FOnTerminate) then
  146. Synchronize(@CallOnTerminate);
  147. end;
  148. const
  149. Priorities: array [TThreadPriority] of Integer =
  150. (THREAD_PRIORITY_IDLE, THREAD_PRIORITY_LOWEST, THREAD_PRIORITY_BELOW_NORMAL,
  151. THREAD_PRIORITY_NORMAL, THREAD_PRIORITY_ABOVE_NORMAL,
  152. THREAD_PRIORITY_HIGHEST, THREAD_PRIORITY_TIME_CRITICAL);
  153. function TThread.GetPriority: TThreadPriority;
  154. var
  155. P: Integer;
  156. I: TThreadPriority;
  157. begin
  158. P := ThreadGetPriority(FHandle);
  159. Result := tpNormal;
  160. for I := Low(TThreadPriority) to High(TThreadPriority) do
  161. if Priorities[I] = P then Result := I;
  162. end;
  163. procedure TThread.SetPriority(Value: TThreadPriority);
  164. begin
  165. ThreadSetPriority(FHandle, Priorities[Value]);
  166. end;
  167. {does not make sense for netware}
  168. procedure TThread.Synchronize(Method: TThreadMethod);
  169. begin
  170. {$ifndef netware}
  171. FSynchronizeException := nil;
  172. FMethod := Method;
  173. { SendMessage(ThreadWindow, CM_EXECPROC, 0, Longint(Self)); }
  174. {$warning Synchronize needs implementation}
  175. if Assigned(FSynchronizeException) then
  176. raise FSynchronizeException;
  177. {$endif}
  178. end;
  179. procedure TThread.SetSuspended(Value: Boolean);
  180. begin
  181. if Value <> FSuspended then
  182. if Value then
  183. Suspend
  184. else
  185. Resume;
  186. end;
  187. procedure TThread.Suspend;
  188. begin
  189. SuspendThread (FHandle);
  190. FSuspended := true;
  191. end;
  192. procedure TThread.Resume;
  193. begin
  194. ResumeThread (FHandle);
  195. FSuspended := False;
  196. end;
  197. procedure TThread.Terminate;
  198. begin
  199. FTerminated := True;
  200. ThreadSwitch;
  201. end;
  202. function TThread.WaitFor: Integer;
  203. begin
  204. Result := WaitForThreadTerminate (FHandle,0);
  205. if Result = 0 then
  206. FHandle := -1;
  207. end;
  208. {
  209. $Log$
  210. Revision 1.2 2003-03-27 17:14:27 armin
  211. * more platform independent thread routines, needs to be implemented for unix
  212. Revision 1.1 2003/03/25 17:56:19 armin
  213. * first fcl implementation for netware
  214. Revision 1.7 2002/12/18 20:44:36 peter
  215. * use fillchar to clear sigset
  216. Revision 1.6 2002/09/07 15:15:27 peter
  217. * old logs removed and tabs fixed
  218. }