2
0

IdSchedulerOfThreadPool.pas 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269
  1. {
  2. $Project$
  3. $Workfile$
  4. $Revision$
  5. $DateUTC$
  6. $Id$
  7. This file is part of the Indy (Internet Direct) project, and is offered
  8. under the dual-licensing agreement described on the Indy website.
  9. (http://www.indyproject.org/)
  10. Copyright:
  11. (c) 1993-2005, Chad Z. Hower and the Indy Pit Crew. All rights reserved.
  12. }
  13. {
  14. $Log$
  15. }
  16. {
  17. Rev 1.12 2004.02.03 4:17:06 PM czhower
  18. For unit name changes.
  19. Rev 1.11 2003.10.24 12:59:20 PM czhower
  20. Name change
  21. Rev 1.10 2003.10.21 12:19:00 AM czhower
  22. TIdTask support and fiber bug fixes.
  23. Rev 1.9 2003.10.11 5:49:50 PM czhower
  24. -VCL fixes for servers
  25. -Chain suport for servers (Super core)
  26. -Scheduler upgrades
  27. -Full yarn support
  28. Rev 1.8 2003.09.19 10:11:20 PM czhower
  29. Next stage of fiber support in servers.
  30. Rev 1.7 2003.09.19 11:54:32 AM czhower
  31. -Completed more features necessary for servers
  32. -Fixed some bugs
  33. Rev 1.6 2003.09.18 4:10:26 PM czhower
  34. Preliminary changes for Yarn support.
  35. Rev 1.5 7/6/2003 8:04:08 PM BGooijen
  36. Renamed IdScheduler* to IdSchedulerOf*
  37. Rev 1.4 7/5/2003 11:49:06 PM BGooijen
  38. Cleaned up and fixed av in threadpool
  39. Rev 1.3 4/15/2003 10:56:08 PM BGooijen
  40. fixes
  41. Rev 1.2 3/13/2003 10:18:34 AM BGooijen
  42. Server side fibers, bug fixes
  43. Rev 1.1 1/23/2003 7:28:46 PM BGooijen
  44. Rev 1.0 1/17/2003 03:29:58 PM JPMugaas
  45. Renamed from ThreadMgr for new design.
  46. Rev 1.0 11/13/2002 09:01:46 AM JPMugaas
  47. 2002-06-23 -Andrew P.Rybin
  48. -2 deadlock fix (and also in IdThread)
  49. }
  50. unit IdSchedulerOfThreadPool;
  51. interface
  52. {$i IdCompilerDefines.inc}
  53. uses
  54. {$IFDEF HAS_UNIT_Generics_Collections}
  55. System.Generics.Collections,
  56. {$ELSE}
  57. Classes,
  58. {$ENDIF}
  59. IdScheduler,
  60. IdSchedulerOfThread,
  61. IdThread,
  62. //IdThreadSafe,
  63. IdYarn;
  64. type
  65. {$IFDEF HAS_GENERICS_TThreadList}
  66. TIdPoolThreadList = TThreadList<TIdThreadWithTask>;
  67. TIdPoolList = TList<TIdThreadWithTask>;
  68. {$ELSE}
  69. // TODO: flesh out to match TThreadList<TIdThreadWithTask> and TList<TIdThreadWithTask> for non-Generics compilers
  70. TIdPoolThreadList = TThreadList;
  71. TIdPoolList = TList;
  72. {$ENDIF}
  73. TIdSchedulerOfThreadPool = class(TIdSchedulerOfThread)
  74. protected
  75. FPoolSize: Integer;
  76. FThreadPool: TIdPoolThreadList;
  77. public
  78. constructor Create(AOwner: TComponent); override;
  79. destructor Destroy; override;
  80. function AcquireYarn: TIdYarn; override;
  81. procedure Init; override;
  82. function NewThread: TIdThreadWithTask; override;
  83. procedure ReleaseYarn(AYarn: TIdYarn); override;
  84. procedure TerminateAllYarns; override;
  85. published
  86. //TODO: Poolsize is only looked at during loading and when threads are
  87. // needed. Probably should add an Active property to schedulers like
  88. // servers have.
  89. property PoolSize: Integer read FPoolSize write FPoolSize default 0;
  90. End;
  91. implementation
  92. uses
  93. {$IF DEFINED(WINDOWS) AND DEFINED(DCC_2010_OR_ABOVE)}
  94. Windows,
  95. {$IFEND}
  96. IdGlobal, SysUtils;
  97. type
  98. TIdYarnOfThreadAccess = class(TIdYarnOfThread)
  99. end;
  100. constructor TIdSchedulerOfThreadPool.Create(AOwner: TComponent);
  101. begin
  102. inherited Create(AOwner);
  103. FThreadPool := TIdPoolThreadList.Create;
  104. end;
  105. destructor TIdSchedulerOfThreadPool.Destroy;
  106. begin
  107. inherited Destroy;
  108. // Must be after, inherited calls TerminateThreads
  109. FThreadPool.Free;
  110. end;
  111. function TIdSchedulerOfThreadPool.AcquireYarn: TIdYarn;
  112. var
  113. LThread: TIdThreadWithTask;
  114. LList: TIdPoolList;
  115. begin
  116. LList := FThreadPool.LockList;
  117. try
  118. if LList.Count > 0 then begin
  119. LThread := {$IFDEF HAS_GENERICS_TList}LList.Items[0]{$ELSE}TIdThreadWithTask(LList.Items[0]){$ENDIF};
  120. LList.Delete(0);
  121. end else begin
  122. LThread := nil;
  123. end;
  124. finally
  125. FThreadPool.UnlockList;
  126. end;
  127. if LThread = nil then begin
  128. LThread := NewThread;
  129. end;
  130. Result := NewYarn(LThread);
  131. ActiveYarns.Add(Result);
  132. end;
  133. procedure TIdSchedulerOfThreadPool.ReleaseYarn(AYarn: TIdYarn);
  134. //only gets called from YarnOf(Fiber/Thread).Destroy
  135. var
  136. LThread: TIdThreadWithTask;
  137. LList: TIdPoolList;
  138. begin
  139. //take posession of the thread
  140. LThread := TIdYarnOfThread(AYarn).Thread;
  141. {$I IdObjectChecksOff.inc}
  142. TIdYarnOfThreadAccess(AYarn).FThread := nil;
  143. {$I IdObjectChecksOn.inc}
  144. //Currently LThread can =nil. Is that a valid condition?
  145. //Assert(LThread<>nil);
  146. // inherited removes from ActiveYarns list
  147. inherited ReleaseYarn(AYarn);
  148. if LThread <> nil then begin
  149. // need to redeposit the thread in the pool or destroy it
  150. LThread.Yarn := nil; // Yarn is being destroyed, de-couple it from the thread
  151. LList := FThreadPool.LockList;
  152. try
  153. if (LList.Count < PoolSize) and (not LThread.Terminated) then begin
  154. LList.Add(LThread);
  155. Exit;
  156. end;
  157. finally
  158. FThreadPool.UnlockList;
  159. end;
  160. LThread.Terminate;
  161. // RLebeau - ReleaseYarn() can be called in the context of
  162. // the yarn's thread (when TIdThread.Cleanup() destroys the
  163. // yarn between connnections), so have to check which context
  164. // we're in here so as not to deadlock the thread!
  165. if IsCurrentThread(LThread) then begin
  166. LThread.FreeOnTerminate := True;
  167. end else begin
  168. {$IFDEF DEPRECATED_TThread_SuspendResume}
  169. LThread.Suspended := False;
  170. {$ELSE}
  171. LThread.Resume;
  172. {$ENDIF}
  173. LThread.WaitFor;
  174. LThread.Free;
  175. end;
  176. end;
  177. end;
  178. procedure TIdSchedulerOfThreadPool.TerminateAllYarns;
  179. var
  180. LThread: TIdThreadWithTask;
  181. LList: TIdPoolList;
  182. begin
  183. // inherited will kill off ActiveYarns
  184. inherited TerminateAllYarns;
  185. // ThreadPool is nil if never Initted
  186. if FThreadPool <> nil then begin
  187. // Now we have to kill off the pooled threads
  188. LList := FThreadPool.LockList;
  189. try
  190. while LList.Count > 0 do begin
  191. LThread := {$IFDEF HAS_GENERICS_TList}LList.Items[0]{$ELSE}TIdThreadWithTask(LList.Items[0]){$ENDIF};
  192. LList.Delete(0);
  193. LThread.Terminate;
  194. {$IFDEF DEPRECATED_TThread_SuspendResume}
  195. LThread.Suspended := False;
  196. {$ELSE}
  197. LThread.Resume;
  198. {$ENDIF}
  199. LThread.WaitFor;
  200. LThread.Free;
  201. end;
  202. finally
  203. FThreadPool.UnlockList;
  204. end;
  205. end;
  206. end;
  207. procedure TIdSchedulerOfThreadPool.Init;
  208. var
  209. LList: TIdPoolList;
  210. begin
  211. inherited Init;
  212. Assert(FThreadPool<>nil);
  213. if not IsDesignTime then begin
  214. if PoolSize > 0 then begin
  215. LList := FThreadPool.LockList;
  216. try
  217. while LList.Count < PoolSize do begin
  218. LList.Add(NewThread);
  219. end;
  220. finally
  221. FThreadPool.UnlockList;
  222. end;
  223. end;
  224. end;
  225. end;
  226. function TIdSchedulerOfThreadPool.NewThread: TIdThreadWithTask;
  227. begin
  228. Result := inherited NewThread;
  229. Result.StopMode := smSuspend;
  230. end;
  231. end.