IdContext.pas 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  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.14 6/16/2004 2:08:48 PM JPMugaas
  18. Binding made public for the FTP Server.
  19. Rev 1.13 6/4/2004 1:34:24 PM DSiders
  20. Removed unused TIdContextDoRun, TIdContextMethod types.
  21. Rev 1.12 2004.02.03 4:17:08 PM czhower
  22. For unit name changes.
  23. Rev 1.11 21.1.2004 ã. 12:31:04 DBondzhev
  24. Fix for Indy source. Workaround for dccil bug
  25. now it can be compiled using Compile instead of build
  26. Rev 1.10 2003.10.21 12:18:58 AM czhower
  27. TIdTask support and fiber bug fixes.
  28. Rev 1.9 2003.10.11 5:47:18 PM czhower
  29. -VCL fixes for servers
  30. -Chain suport for servers (Super core)
  31. -Scheduler upgrades
  32. -Full yarn support
  33. Rev 1.8 2003.09.19 11:54:28 AM czhower
  34. -Completed more features necessary for servers
  35. -Fixed some bugs
  36. Rev 1.7 3/22/2003 09:45:26 PM JPMugaas
  37. Now should compile under D4.
  38. Rev 1.6 3/13/2003 10:18:38 AM BGooijen
  39. Server side fibers, bug fixes
  40. Rev 1.5 1/31/2003 7:24:18 PM BGooijen
  41. Added a .Binding function
  42. Rev 1.4 1/23/2003 8:33:20 PM BGooijen
  43. Rev 1.3 1/23/2003 11:06:06 AM BGooijen
  44. Rev 1.2 1-17-2003 23:58:30 BGooijen
  45. removed OnCreate/OnDestroy again, they had no use
  46. Rev 1.0 1-17-2003 22:28:58 BGooijen
  47. }
  48. unit IdContext;
  49. interface
  50. {$i IdCompilerDefines.inc}
  51. uses
  52. Classes,
  53. IdSocketHandle, IdTCPConnection, IdTask, IdYarn, IdThreadSafe,
  54. {$IFDEF HAS_GENERICS_TThreadList}
  55. System.Generics.Collections,
  56. {$ENDIF}
  57. SysUtils;
  58. type
  59. TIdContext = class;
  60. TIdContextClass = class of TIdContext;
  61. TIdContextRun = function(AContext: TIdContext): Boolean of object;
  62. TIdContextEvent = procedure(AContext: TIdContext) of object;
  63. TIdContextExceptionEvent = procedure(AContext: TIdContext; AException: Exception) of object;
  64. {$IFDEF HAS_GENERICS_TThreadList}
  65. TIdContextThreadList = TIdThreadSafeObjectList<TIdContext>;
  66. TIdContextList = TList<TIdContext>;
  67. {$ELSE}
  68. // TODO: flesh out to match TThreadList<TIdContext> and TList<TIdContext> for non-Generics compilers
  69. TIdContextThreadList = TIdThreadSafeObjectList;
  70. TIdContextList = TList;
  71. {$ENDIF}
  72. TIdContext = class(TIdTask)
  73. protected
  74. // A list in which this context is registered, this can be nil, and should
  75. // therefore not be used
  76. FContextList: TIdContextThreadList;
  77. FConnection: TIdTCPConnection; // TODO: should this be [Weak] on ARC systems?
  78. FOwnsConnection: Boolean;
  79. FOnRun: TIdContextRun;
  80. FOnBeforeRun: TIdContextEvent;
  81. FOnAfterRun: TIdContextEvent;
  82. FOnException: TIdContextExceptionEvent;
  83. //
  84. procedure BeforeRun; override;
  85. function Run: Boolean; override;
  86. procedure AfterRun; override;
  87. procedure HandleException(AException: Exception); override;
  88. function GetBinding: TIdSocketHandle;
  89. public
  90. constructor Create(
  91. AConnection: TIdTCPConnection;
  92. AYarn: TIdYarn;
  93. AList: TIdContextThreadList = nil
  94. ); reintroduce; virtual;
  95. destructor Destroy; override;
  96. procedure RemoveFromList;
  97. //
  98. property Binding: TIdSocketHandle read GetBinding;
  99. property Connection: TIdTCPConnection read FConnection;
  100. //
  101. property OnAfterRun: TIdContextEvent read FOnAfterRun write FOnAfterRun;
  102. property OnBeforeRun: TIdContextEvent read FOnBeforeRun write FOnBeforeRun;
  103. property OnRun: TIdContextRun read FOnRun write FOnRun;
  104. property OnException: TIdContextExceptionEvent read FOnException write FOnException;
  105. end;
  106. implementation
  107. { TIdContext }
  108. uses
  109. {$IFDEF VCL_XE3_OR_ABOVE}
  110. System.Types,
  111. {$ENDIF}
  112. IdGlobal,
  113. IdIOHandlerSocket;
  114. constructor TIdContext.Create(AConnection: TIdTCPConnection; AYarn: TIdYarn;
  115. AList: TIdContextThreadList = nil);
  116. begin
  117. inherited Create(AYarn);
  118. FConnection := AConnection;
  119. FOwnsConnection := True;
  120. FContextList := AList;
  121. end;
  122. destructor TIdContext.Destroy;
  123. begin
  124. if Assigned(FContextList) then begin
  125. FContextList.Remove(Self);
  126. end;
  127. if FOwnsConnection then begin
  128. IdDisposeAndNil(FConnection);
  129. end;
  130. inherited Destroy;
  131. end;
  132. procedure TIdContext.RemoveFromList;
  133. begin
  134. FContextList := nil;
  135. end;
  136. procedure TIdContext.BeforeRun;
  137. begin
  138. //Context must be added to ContextList outside of create. This avoids
  139. //the possibility of another thread accessing a context (specifically
  140. //a subclass) that is still creating. similar logic for remove/destroy.
  141. if Assigned(FContextList) then begin
  142. FContextList.Add(Self);
  143. end;
  144. if Assigned(OnBeforeRun) then begin
  145. OnBeforeRun(Self);
  146. end;
  147. end;
  148. function TIdContext.Run: Boolean;
  149. begin
  150. if Assigned(OnRun) then begin
  151. Result := OnRun(Self);
  152. end else begin
  153. Result := True;
  154. end;
  155. end;
  156. procedure TIdContext.AfterRun;
  157. begin
  158. if Assigned(OnAfterRun) then begin
  159. OnAfterRun(Self);
  160. end;
  161. if FContextList <> nil then begin
  162. FContextList.Remove(Self);
  163. end;
  164. end;
  165. procedure TIdContext.HandleException(AException: Exception);
  166. begin
  167. if Assigned(OnException) then begin
  168. OnException(Self, AException);
  169. end;
  170. end;
  171. function TIdContext.GetBinding: TIdSocketHandle;
  172. var
  173. // under ARC, convert a weak reference to a strong reference before working with it
  174. LConn: TIdTCPConnection;
  175. LSocket: TIdIOHandlerSocket;
  176. begin
  177. Result := nil;
  178. LConn := Connection;
  179. if LConn <> nil then begin
  180. LSocket := LConn.Socket;
  181. if LSocket <> nil then begin
  182. Result := LSocket.Binding;
  183. end;
  184. end;
  185. end;
  186. end.