IdSchedulerOfThreadPool.pas 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271
  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. procedure InitComponent; override;
  78. public
  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. {$IFDEF VCL_2010_OR_ABOVE}
  94. {$IFDEF WINDOWS}
  95. Windows,
  96. {$ENDIF}
  97. {$ENDIF}
  98. IdGlobal, SysUtils;
  99. type
  100. TIdYarnOfThreadAccess = class(TIdYarnOfThread)
  101. end;
  102. destructor TIdSchedulerOfThreadPool.Destroy;
  103. begin
  104. inherited Destroy;
  105. // Must be after, inherited calls TerminateThreads
  106. FreeAndNil(FThreadPool);
  107. end;
  108. function TIdSchedulerOfThreadPool.AcquireYarn: TIdYarn;
  109. var
  110. LThread: TIdThreadWithTask;
  111. LList: TIdPoolList;
  112. begin
  113. LList := FThreadPool.LockList;
  114. try
  115. if LList.Count > 0 then begin
  116. LThread := {$IFDEF HAS_GENERICS_TList}LList.Items[0]{$ELSE}TIdThreadWithTask(LList.Items[0]){$ENDIF};
  117. LList.Delete(0);
  118. end else begin
  119. LThread := nil;
  120. end;
  121. finally
  122. FThreadPool.UnlockList;
  123. end;
  124. if LThread = nil then begin
  125. LThread := NewThread;
  126. end;
  127. Result := NewYarn(LThread);
  128. ActiveYarns.Add(Result);
  129. end;
  130. procedure TIdSchedulerOfThreadPool.ReleaseYarn(AYarn: TIdYarn);
  131. //only gets called from YarnOf(Fiber/Thread).Destroy
  132. var
  133. LThread: TIdThreadWithTask;
  134. LList: TIdPoolList;
  135. begin
  136. //take posession of the thread
  137. LThread := TIdYarnOfThread(AYarn).Thread;
  138. {$I IdObjectChecksOff.inc}
  139. TIdYarnOfThreadAccess(AYarn).FThread := nil;
  140. {$I IdObjectChecksOn.inc}
  141. //Currently LThread can =nil. Is that a valid condition?
  142. //Assert(LThread<>nil);
  143. // inherited removes from ActiveYarns list
  144. inherited ReleaseYarn(AYarn);
  145. if LThread <> nil then begin
  146. // need to redeposit the thread in the pool or destroy it
  147. LThread.Yarn := nil; // Yarn is being destroyed, de-couple it from the thread
  148. LList := FThreadPool.LockList;
  149. try
  150. if (LList.Count < PoolSize) and (not LThread.Terminated) then begin
  151. LList.Add(LThread);
  152. Exit;
  153. end;
  154. finally
  155. FThreadPool.UnlockList;
  156. end;
  157. LThread.Terminate;
  158. // RLebeau - ReleaseYarn() can be called in the context of
  159. // the yarn's thread (when TIdThread.Cleanup() destroys the
  160. // yarn between connnections), so have to check which context
  161. // we're in here so as not to deadlock the thread!
  162. if IsCurrentThread(LThread) then begin
  163. LThread.FreeOnTerminate := True;
  164. end else begin
  165. {$IFDEF DEPRECATED_TThread_SuspendResume}
  166. LThread.Suspended := False;
  167. {$ELSE}
  168. LThread.Resume;
  169. {$ENDIF}
  170. LThread.WaitFor;
  171. LThread.Free;
  172. end;
  173. end;
  174. end;
  175. procedure TIdSchedulerOfThreadPool.TerminateAllYarns;
  176. var
  177. LThread: TIdThreadWithTask;
  178. LList: TIdPoolList;
  179. begin
  180. // inherited will kill off ActiveYarns
  181. inherited TerminateAllYarns;
  182. // ThreadPool is nil if never Initted
  183. if FThreadPool <> nil then begin
  184. // Now we have to kill off the pooled threads
  185. LList := FThreadPool.LockList;
  186. try
  187. while LList.Count > 0 do begin
  188. LThread := {$IFDEF HAS_GENERICS_TList}LList.Items[0]{$ELSE}TIdThreadWithTask(LList.Items[0]){$ENDIF};
  189. LList.Delete(0);
  190. LThread.Terminate;
  191. {$IFDEF DEPRECATED_TThread_SuspendResume}
  192. LThread.Suspended := False;
  193. {$ELSE}
  194. LThread.Resume;
  195. {$ENDIF}
  196. LThread.WaitFor;
  197. LThread.Free;
  198. end;
  199. finally
  200. FThreadPool.UnlockList;
  201. end;
  202. end;
  203. end;
  204. procedure TIdSchedulerOfThreadPool.Init;
  205. var
  206. LList: TIdPoolList;
  207. begin
  208. inherited Init;
  209. Assert(FThreadPool<>nil);
  210. if not IsDesignTime then begin
  211. if PoolSize > 0 then begin
  212. LList := FThreadPool.LockList;
  213. try
  214. while LList.Count < PoolSize do begin
  215. LList.Add(NewThread);
  216. end;
  217. finally
  218. FThreadPool.UnlockList;
  219. end;
  220. end;
  221. end;
  222. end;
  223. function TIdSchedulerOfThreadPool.NewThread: TIdThreadWithTask;
  224. begin
  225. Result := inherited NewThread;
  226. Result.StopMode := smSuspend;
  227. end;
  228. procedure TIdSchedulerOfThreadPool.InitComponent;
  229. begin
  230. inherited;
  231. FThreadPool := TIdPoolThreadList.Create;
  232. end;
  233. end.