tthread.inc 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  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. procedure TThread.SysCreate(CreateSuspended: Boolean;
  109. const StackSize: SizeUInt);
  110. var
  111. Flags: Integer;
  112. begin
  113. AddThread(self);
  114. FSuspended := CreateSuspended;
  115. { Create new thread }
  116. FHandle := BeginThread (@ThreadProc,pointer(self));
  117. if FSuspended then Suspend;
  118. FThreadID := FHandle;
  119. FFatalException := nil;
  120. end;
  121. procedure TThread.SysDestroy;
  122. begin
  123. if not FFinished then
  124. begin
  125. Terminate;
  126. if Suspended then
  127. ResumeThread (FHandle); {netware can not kill a thread, the thread has to}
  128. {leave it's execute routine if terminated is true}
  129. WaitFor; {wait for the thread to terminate}
  130. end;
  131. FFatalException.Free;
  132. FFatalException := nil;
  133. RemoveThread(self); {remove it from the list of active threads}
  134. end;
  135. procedure TThread.CallOnTerminate;
  136. begin
  137. FOnTerminate(Self);
  138. end;
  139. procedure TThread.DoTerminate;
  140. begin
  141. if Assigned(FOnTerminate) then
  142. Synchronize(@CallOnTerminate);
  143. end;
  144. const
  145. Priorities: array [TThreadPriority] of Integer =
  146. (THREAD_PRIORITY_IDLE, THREAD_PRIORITY_LOWEST, THREAD_PRIORITY_BELOW_NORMAL,
  147. THREAD_PRIORITY_NORMAL, THREAD_PRIORITY_ABOVE_NORMAL,
  148. THREAD_PRIORITY_HIGHEST, THREAD_PRIORITY_TIME_CRITICAL);
  149. function TThread.GetPriority: TThreadPriority;
  150. var
  151. P: Integer;
  152. I: TThreadPriority;
  153. begin
  154. P := ThreadGetPriority(FHandle);
  155. Result := tpNormal;
  156. for I := Low(TThreadPriority) to High(TThreadPriority) do
  157. if Priorities[I] = P then Result := I;
  158. end;
  159. procedure TThread.SetPriority(Value: TThreadPriority);
  160. begin
  161. ThreadSetPriority(FHandle, Priorities[Value]);
  162. end;
  163. procedure TThread.SetSuspended(Value: Boolean);
  164. begin
  165. if Value <> FSuspended then
  166. if Value then
  167. Suspend
  168. else
  169. Resume;
  170. end;
  171. procedure TThread.Suspend;
  172. begin
  173. SuspendThread (FHandle);
  174. FSuspended := true;
  175. end;
  176. procedure TThread.Resume;
  177. begin
  178. ResumeThread (FHandle);
  179. FSuspended := False;
  180. end;
  181. procedure TThread.Terminate;
  182. begin
  183. FTerminated := True;
  184. TerminatedSet;
  185. ThreadSwitch;
  186. end;
  187. function TThread.WaitFor: Integer;
  188. begin
  189. Result := WaitForThreadTerminate (FHandle,0);
  190. if Result = 0 then
  191. FHandle := 0;
  192. end;