libasync.pp 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241
  1. {
  2. $Id$
  3. libasync: Asynchronous event management
  4. Copyright (C) 2001-2002 by
  5. Areca Systems GmbH / Sebastian Guenther, [email protected]
  6. Unix implementation
  7. See the file COPYING.FPC, included in this distribution,
  8. for details about the copyright.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  12. }
  13. unit libasync;
  14. {$MODE objfpc}
  15. interface
  16. type
  17. TAsyncData = record
  18. IsRunning, DoBreak: Boolean;
  19. HasCallbacks: Boolean; // True as long as callbacks are set
  20. FirstTimer: Pointer;
  21. FirstIOCallback: Pointer;
  22. CurIOCallback: Pointer; // current callback being processed within 'run'
  23. NextIOCallback: Pointer; // next callback to get processed within 'run'
  24. FDData: Pointer;
  25. HighestHandle: LongInt;
  26. end;
  27. {$INCLUDE libasynch.inc}
  28. implementation
  29. {$ifdef VER1_0}
  30. uses Linux;
  31. {$else}
  32. uses baseunix, Unix;
  33. {$endif}
  34. const
  35. MaxHandle = SizeOf(TFDSet) * 8 - 1;
  36. type
  37. PIOCallbackData = ^TIOCallbackData;
  38. TIOCallbackData = record
  39. Next: PIOCallbackData;
  40. IOHandle: LongInt;
  41. ReadCallback, WriteCallback: TAsyncCallback;
  42. ReadUserData, WriteUserData: Pointer;
  43. SavedHandleFlags: LongInt;
  44. end;
  45. {$INCLUDE libasync.inc}
  46. procedure InternalInit(Handle: TAsyncHandle);
  47. begin
  48. Handle^.Data.HighestHandle := -1;
  49. end;
  50. procedure InternalFree(Handle: TAsyncHandle);
  51. var
  52. IOCallback: PIOCallbackData;
  53. begin
  54. IOCallback := PIOCallbackData(Handle^.Data.FirstIOCallback);
  55. while Assigned(IOCallback) do
  56. begin
  57. if (IOCallback^.SavedHandleFlags and Open_NonBlock) = 0 then
  58. {$ifdef VER1_0}fcntl{$else}fpfcntl{$endif}(IOCallback^.IOHandle, F_SetFl, IOCallback^.SavedHandleFlags);
  59. IOCallback := IOCallback^.Next;
  60. end;
  61. if Assigned(Handle^.Data.FDData) then
  62. FreeMem(Handle^.Data.FDData);
  63. end;
  64. procedure InternalRun(Handle: TAsyncHandle; TimeOut: Int64);
  65. var
  66. AsyncResult: Integer;
  67. CurReadFDSet, CurWriteFDSet: TFDSet;
  68. CurIOCallback: PIOCallbackData;
  69. begin
  70. if Handle^.Data.HighestHandle < 0 then
  71. // No I/O checks to do, so just wait...
  72. AsyncResult := {$ifdef VER1_0}Select{$else}fpselect{$endif}(0, nil, nil, nil, TimeOut)
  73. else
  74. begin
  75. CurReadFDSet := PFDSet(Handle^.Data.FDData)[0];
  76. CurWriteFDSet := PFDSet(Handle^.Data.FDData)[1];
  77. AsyncResult := {$ifdef VER1_0}Select{$else}fpselect{$endif}(Handle^.Data.HighestHandle + 1,
  78. @CurReadFDSet, @CurWriteFDSet, nil, TimeOut);
  79. if AsyncResult > 0 then
  80. begin
  81. // Check for I/O events
  82. Handle^.Data.CurIOCallback := Handle^.Data.FirstIOCallback;
  83. while Assigned(Handle^.Data.CurIOCallback) do
  84. begin
  85. CurIOCallback := PIOCallbackData(Handle^.Data.CurIOCallback);
  86. Handle^.Data.NextIOCallback := CurIOCallback^.Next;
  87. {$ifdef VER1_0}
  88. if (FD_IsSet(CurIOCallback^.IOHandle,CurReadFDSet)) and
  89. (FD_IsSet(CurIOCallback^.IOHandle, PFDSet(Handle^.Data.FDData)[0])) and
  90. {$else}
  91. if (fpFD_ISSET(CurIOCallback^.IOHandle,CurReadFDSet) > 0) and
  92. (fpFD_ISSET(CurIOCallback^.IOHandle, PFDSet(Handle^.Data.FDData)[0]) > 0) and
  93. {$endif}
  94. Assigned(CurIOCallback^.ReadCallback) then
  95. begin
  96. CurIOCallback^.ReadCallback(CurIOCallback^.ReadUserData);
  97. if Handle^.Data.DoBreak then
  98. break;
  99. end;
  100. CurIOCallback := PIOCallbackData(Handle^.Data.CurIOCallback);
  101. if Assigned(CurIOCallback) and
  102. {$ifdef VER1_0}
  103. (FD_IsSet(CurIOCallback^.IOHandle, CurWriteFDSet)) and
  104. (FD_IsSet(CurIOCallback^.IOHandle, PFDSet(Handle^.Data.FDData)[1])) and
  105. {$else}
  106. (fpFD_ISSET(CurIOCallback^.IOHandle, CurWriteFDSet) > 0) and
  107. (fpFD_ISSET(CurIOCallback^.IOHandle, PFDSet(Handle^.Data.FDData)[1]) > 0) and
  108. {$endif}
  109. Assigned(CurIOCallback^.WriteCallback) then
  110. begin
  111. CurIOCallback^.WriteCallback(CurIOCallback^.WriteUserData);
  112. if Handle^.Data.DoBreak then
  113. break;
  114. end;
  115. Handle^.Data.CurIOCallback := Handle^.Data.NextIOCallback;
  116. end;
  117. end;
  118. end;
  119. end;
  120. procedure InternalInitIOCallback(Handle: TAsyncHandle; Data: PIOCallbackData;
  121. InitData: Boolean; CallbackTypes: TCallbackTypes);
  122. var
  123. i: LongInt;
  124. begin
  125. if InitData then
  126. begin
  127. if not Assigned(Handle^.Data.FDData) then
  128. begin
  129. GetMem(Handle^.Data.FDData, SizeOf(TFDSet) * 2);
  130. {$ifdef VER1_0}FD_ZERO{$else}fpFD_ZERO{$endif}(PFDSet(Handle^.Data.FDData)[0]);
  131. {$ifdef VER1_0}FD_ZERO{$else}fpFD_ZERO{$endif}(PFDSet(Handle^.Data.FDData)[1]);
  132. end;
  133. if Data^.IOHandle > Handle^.Data.HighestHandle then
  134. Handle^.Data.HighestHandle := Data^.IOHandle;
  135. end;
  136. Data^.SavedHandleFlags := {$ifdef VER1_0}fcntl{$else}fpfcntl{$endif}(Data^.IOHandle, F_GetFl);
  137. {$ifdef VER1_0}fcntl{$else}fpfcntl{$endif}(Data^.IOHandle, F_SetFl, Data^.SavedHandleFlags or Open_NonBlock);
  138. case Data^.IOHandle of
  139. StdInputHandle:
  140. i := Open_RdOnly;
  141. StdOutputHandle, StdErrorHandle:
  142. i := Open_WrOnly;
  143. else
  144. i := Data^.SavedHandleFlags and Open_Accmode;
  145. end;
  146. case i of
  147. Open_RdOnly:
  148. if cbRead in CallbackTypes then
  149. {$ifdef VER1_0}FD_Set{$else}fpFD_SET{$endif}(Data^.IOHandle, PFDSet(Handle^.Data.FDData)[0]);
  150. Open_WrOnly:
  151. if cbWrite in CallbackTypes then
  152. {$ifdef VER1_0}FD_Set{$else}fpFD_SET{$endif}(Data^.IOHandle, PFDSet(Handle^.Data.FDData)[1]);
  153. Open_RdWr:
  154. begin
  155. if cbRead in CallbackTypes then
  156. {$ifdef VER1_0}FD_Set{$else}fpFD_SET{$endif}(Data^.IOHandle, PFDSet(Handle^.Data.FDData)[0]);
  157. if cbWrite in CallbackTypes then
  158. {$ifdef VER1_0}FD_Set{$else}fpFD_SET{$endif}(Data^.IOHandle, PFDSet(Handle^.Data.FDData)[1]);
  159. end;
  160. end;
  161. end;
  162. procedure InternalClearIOCallback(Handle: TAsyncHandle; IOHandle: LongInt;
  163. CallbackTypes: TCallbackTypes);
  164. begin
  165. if not Assigned(Handle) then
  166. exit;
  167. if cbRead in CallbackTypes then
  168. {$ifdef VER1_0}FD_CLR{$else}fpFD_CLR{$endif}(IOHandle, PFDSet(Handle^.Data.FDData)[0]);
  169. if cbWrite in CallbackTypes then
  170. {$ifdef VER1_0}FD_CLR{$else}fpFD_CLR{$endif}(IOHandle, PFDSet(Handle^.Data.FDData)[1]);
  171. end;
  172. function asyncGetTicks: Int64; cdecl;
  173. var
  174. Time: TimeVal;
  175. begin
  176. {$ifdef ver1_0}
  177. GetTimeOfDay(time);
  178. Result := Int64(Time.Sec) * 1000 + Int64(Time.USec div 1000);
  179. {$else}
  180. fpGetTimeOfDay(@time,nil);
  181. Result := Int64(Time.tv_Sec) * 1000 + Int64(Time.tv_USec div 1000);
  182. {$endif}
  183. end;
  184. end.
  185. {
  186. $Log$
  187. Revision 1.9 2003-11-30 12:26:54 sg
  188. * Small typo fixes for making libasync working in mainbranch
  189. Revision 1.8 2003/11/21 01:06:18 sg
  190. * Now resistent against clearing already removed notify handles
  191. Revision 1.7 2003/09/28 09:38:17 peter
  192. * fixed for 1.0.x
  193. Revision 1.6 2003/09/19 17:46:23 marco
  194. * Unix reform stage III aftermath
  195. Revision 1.5 2002/09/25 21:53:39 sg
  196. * Split in common implementation an platform dependent implementation
  197. Revision 1.4 2002/09/15 15:51:09 sg
  198. * Removed debugging output code
  199. }