ChainClients.pas 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288
  1. { $HDR$}
  2. {**********************************************************************}
  3. { Unit archived using Team Coherence }
  4. { Team Coherence is Copyright 2002 by Quality Software Components }
  5. { }
  6. { For further information / comments, visit our WEB site at }
  7. { http://www.TeamCoherence.com }
  8. {**********************************************************************}
  9. {}
  10. { $Log: 18245: ChainClients.pas
  11. {
  12. { Rev 1.5 6/24/2003 01:15:08 PM JPMugaas
  13. { Updated for API change.
  14. }
  15. {
  16. { Rev 1.4 2003.05.19 10:18:02 AM czhower
  17. }
  18. {
  19. { Rev 1.3 2003.04.22 9:56:18 PM czhower
  20. }
  21. {
  22. Rev 1.2 4/16/2003 4:51:54 PM BGooijen
  23. }
  24. {
  25. { Rev 1.1 2003.04.15 12:46:10 PM czhower
  26. }
  27. {
  28. { Rev 1.11 2003.04.10 11:23:46 PM czhower
  29. }
  30. {
  31. { Rev 1.10 2003.03.27 1:32:06 AM czhower
  32. { More fiber tests
  33. }
  34. {
  35. { Rev 1.9 2003.03.27 12:46:20 AM czhower
  36. }
  37. {
  38. { Rev 1.8 2003.03.27 12:29:34 AM czhower
  39. }
  40. {
  41. { Rev 1.7 2003.02.27 12:55:40 AM czhower
  42. }
  43. {
  44. { Rev 1.6 2003.02.25 1:38:28 AM czhower
  45. }
  46. {
  47. { Rev 1.5 2003.02.18 1:36:18 PM czhower
  48. }
  49. {
  50. { Rev 1.4 2003.01.17 4:41:30 PM czhower
  51. }
  52. {
  53. { Rev 1.3 2003.01.09 11:25:30 PM czhower
  54. }
  55. {
  56. { Rev 1.0 2002.12.07 6:44:02 PM czhower
  57. }
  58. unit ChainClients;
  59. interface
  60. uses
  61. Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms,
  62. Dialogs, StdCtrls,
  63. IdFiber, IdTCPClient, IdSync, ExtCtrls, IdIOHandlerChain,
  64. ComCtrls, BXBubble;
  65. type
  66. TformChainClients = class(TForm)
  67. Panel1: TPanel;
  68. Label2: TLabel;
  69. Label1: TLabel;
  70. Label4: TLabel;
  71. Label3: TLabel;
  72. lablThreads: TLabel;
  73. lablReturns: TLabel;
  74. butnFiber: TButton;
  75. editFibers: TEdit;
  76. editRepeat: TEdit;
  77. editDocument: TEdit;
  78. editHost: TEdit;
  79. memoTest: TMemo;
  80. ChainClient: TBXBubble;
  81. GroupBox1: TGroupBox;
  82. radoTCP: TRadioButton;
  83. radoHTTP: TRadioButton;
  84. GroupBox2: TGroupBox;
  85. radoWinsock: TRadioButton;
  86. radoIOCP: TRadioButton;
  87. procedure butnFiberClick(Sender: TObject);
  88. procedure ChainClientPlayground(Sender: TBXBubble);
  89. private
  90. protected
  91. FMainFiber: TIdConvertedFiber;
  92. FStream: TStringStream;
  93. FReturnCount: Integer;
  94. FThreadCount: Integer;
  95. //
  96. procedure HTTPTestFiber(const AUseHTTP: Boolean; const AUseIOCP: Boolean);
  97. procedure OnFiberIdle(AFiber: TObject);
  98. procedure OnFiberSwitch(AFiberWeaver: TIdFiberWeaver; AFiber: TIdFiberBase);
  99. procedure UpdateLabels;
  100. public
  101. end;
  102. TClientFiber = class(TIdFiber)
  103. protected
  104. FChainEngine: TIdChainEngine;
  105. FDocument: string;
  106. FFiberWeaver: TIdFiberWeaver;
  107. FHost: string;
  108. end;
  109. TTCPFiber = class(TClientFiber)
  110. protected
  111. procedure Execute; override;
  112. end;
  113. THTTPFiber = class(TClientFiber)
  114. protected
  115. procedure Execute; override;
  116. end;
  117. var
  118. formChainClients: TformChainClients;
  119. implementation
  120. {$R *.dfm}
  121. uses
  122. IdIOHandlerStack, IdChainEngineIOCP, IdCoreGlobal, IdStack,
  123. IdChainEngineStack, IdHTTP, IdFiberWeaverDefault,
  124. SyncObjs;
  125. procedure TformChainClients.UpdateLabels;
  126. begin
  127. lablThreads.Caption := 'Threads: ' + IntToStr(FThreadCount);
  128. lablReturns.Caption := 'Returns: ' + IntToStr(FReturnCount);
  129. end;
  130. procedure TformChainClients.butnFiberClick(Sender: TObject);
  131. var
  132. i: Integer;
  133. begin
  134. for i := 1 to StrToInt(editRepeat.Text) do begin
  135. HTTPTestFiber(radoHTTP.Checked, radoIOCP.Checked);
  136. end;
  137. memoTest.Lines.Add(' ======= Done ========== ');
  138. end;
  139. { TTCPFiber }
  140. procedure TTCPFiber.Execute;
  141. var
  142. LHTTPResult: TStringStream;
  143. LIOHandler: TIdIOHandlerChain;
  144. begin
  145. // The IOHandlerChain "links" the IOHandler to the FiberWeaver and integrates
  146. // with its scheduling mechanism
  147. //
  148. // The fiber is also passed so it knows which fiber it will use for this
  149. // instance of IOHandler.
  150. //
  151. // The IOHandlerChain is actually independent of the IO itself, it merely
  152. // queues and communicates with the ChainEngine. The ChainEngine does all the
  153. // actuall IO and will be pluggable. Right now its using Stack as Phase I, but
  154. // later will have options to use IOCP, Overlapped IO or other.
  155. LIOHandler := TIdIOHandlerChain.Create(nil, FChainEngine, FFiberWeaver
  156. , Self); try
  157. with TIdTCPClient.Create(nil) do try
  158. IOHandler := LIOHandler;
  159. Host := FHost;
  160. Port := 80;
  161. Connect; try
  162. IOHandler.Write('GET ' + FDocument + ' HTTP/1.0' + EOL + EOL);
  163. LHTTPResult := TStringStream.Create(''); try
  164. IOHandler.ReadStream(LHTTPResult, -1, True);
  165. with formChainClients.memoTest.Lines do begin
  166. Add(LHTTPResult.DataString);
  167. Add(EOL + '_____________________' + EOL);
  168. end;
  169. Inc(formChainClients.FReturnCount);
  170. formChainClients.UpdateLabels;
  171. finally FreeAndNil(LHTTPResult); end;
  172. finally Disconnect; end;
  173. finally Free; end;
  174. finally FreeAndNil(LIOHandler); end;
  175. end;
  176. procedure TformChainClients.HTTPTestFiber(const AUseHTTP: Boolean;
  177. const AUseIOCP: Boolean);
  178. var
  179. i: Integer;
  180. LChainEngine: TIdChainEngine;
  181. LFiberWeaver: TIdFiberWeaverDefault;
  182. LFibers: TList;
  183. LFiber: TClientFiber;
  184. LSelfFiber: TIdConvertedFiber;
  185. begin
  186. if AUseIOCP then begin
  187. LChainEngine := TIdChainEngineIOCP.Create(nil);
  188. end else begin
  189. LChainEngine := TIdChainEngineStack.Create(nil);
  190. end;
  191. try
  192. // All fibers MUST have a parent fiber. The parent fiber is the
  193. // fiber that gets "fallen back" on when all other fibers have finished.
  194. // A converted fiber is a special fiber, its a fiber that is created "out of"
  195. // the current thread.
  196. LSelfFiber := TIdConvertedFiber.Create; try
  197. LSelfFiber.Name := 'Converted';
  198. // The fiber weaver is a scheduler for the fibers. It schedules the fibers
  199. // onto threads and
  200. LFiberWeaver := TIdFiberWeaverDefault.Create(nil); try
  201. // This is a list of fibers so we can destroy them later.
  202. LFibers := TList.Create; try
  203. // Create the specified number of fibers and add them to the FiberWeaver
  204. for i := 1 to StrToInt(editFibers.Text) do begin
  205. if AUseHTTP then begin
  206. LFiber := THTTPFiber.Create(LSelfFiber, LFiberWeaver);
  207. end else begin
  208. LFiber := TTCPFiber.Create(LSelfFiber, LFiberWeaver);
  209. end;
  210. LFiber.Name := 'Fiber ' + IntToStr(i);
  211. with LFiber do begin
  212. FChainEngine := LChainEngine;
  213. FFiberWeaver := LFiberWeaver;
  214. FHost := Trim(editHost.Text);
  215. FDocument := Trim(editDocument.Text);
  216. end;
  217. LFibers.Add(LFiber);
  218. end;
  219. // Run fibers. This will run all fibers until every fiber has run and
  220. // completed. It will then return. In this case, all fibers will run
  221. // under this thread.
  222. LFiberWeaver.ProcessInThisFiber(LSelfFiber);
  223. // Free the fibers
  224. for i := 0 to LFibers.Count - 1 do begin
  225. TIdFiber(LFibers[i]).Free;
  226. end;
  227. finally FreeAndNil(LFibers); end;
  228. // Freeing causes AVs - trying to fix this now
  229. finally FreeAndNil(LFiberWeaver); end;
  230. finally FreeAndNil(LSelfFiber); end;
  231. finally FreeAndNil(LChainEngine); end;
  232. end;
  233. procedure TformChainClients.OnFiberSwitch(AFiberWeaver: TIdFiberWeaver;
  234. AFiber: TIdFiberBase);
  235. begin
  236. Application.ProcessMessages;
  237. end;
  238. procedure TformChainClients.OnFiberIdle(AFiber: TObject);
  239. begin
  240. Application.ProcessMessages;
  241. end;
  242. { THTTPFiber }
  243. procedure THTTPFiber.Execute;
  244. var
  245. LHTTPResult: TStringStream;
  246. LIOHandler: TIdIOHandlerChain;
  247. begin
  248. LIOHandler := TIdIOHandlerChain.Create(nil, FChainEngine, FFiberWeaver
  249. , Self); try
  250. with TIdHTTP.Create(nil) do try
  251. IOHandler := LIOHandler;
  252. LHTTPResult := TStringStream.Create(''); try
  253. Get('http://' + FHost + FDocument, LHTTPResult);
  254. with formChainClients.memoTest.Lines do begin
  255. Add(LHTTPResult.DataString);
  256. Add(EOL + '_____________________' + EOL);
  257. end;
  258. Inc(formChainClients.FReturnCount);
  259. formChainClients.UpdateLabels;
  260. finally FreeAndNil(LHTTPResult); end;
  261. finally Free; end;
  262. finally FreeAndNil(LIOHandler); end;
  263. end;
  264. procedure TformChainClients.ChainClientPlayground(Sender: TBXBubble);
  265. begin
  266. ShowModal;
  267. end;
  268. end.