tthread.inc 4.8 KB

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