Browse Source

* Improved error reporting

sg 23 năm trước cách đây
mục cha
commit
605ea806aa

+ 16 - 10
packages/base/libasync/libasync.inc

@@ -26,6 +26,12 @@ type
 
 
   TAsyncCallback = procedure(UserData: Pointer); cdecl;
   TAsyncCallback = procedure(UserData: Pointer); cdecl;
 
 
+  TAsyncResult = (
+    asyncOK,
+    asyncInvalidHandle,
+    asyncInvalidFileHandle,
+    asyncHandlerAlreadySet);
+
 
 
 // Construction and destruction
 // Construction and destruction
 
 
@@ -59,9 +65,9 @@ function asyncGetTicks: Int64; cdecl;
 function asyncAddTimer(
 function asyncAddTimer(
   Handle: TAsyncHandle;
   Handle: TAsyncHandle;
   MSec: LongInt;
   MSec: LongInt;
-  Periodic: Boolean;            // False = One-shot timer, True = Periodic timer
+  Periodic: Boolean;		// False = One-shot timer, True = Periodic timer
   Callback: TAsyncCallback;
   Callback: TAsyncCallback;
-  UserData: Pointer             // User data for callback
+  UserData: Pointer		// User data for callback
   ): TAsyncTimer; cdecl;
   ): TAsyncTimer; cdecl;
 
 
 procedure asyncRemoveTimer(
 procedure asyncRemoveTimer(
@@ -71,31 +77,31 @@ procedure asyncRemoveTimer(
 
 
 // I/O callback management
 // I/O callback management
 
 
-procedure asyncSetIOCallback(
+function asyncSetIOCallback(
   Handle: TAsyncHandle;
   Handle: TAsyncHandle;
   IOHandle: LongInt;
   IOHandle: LongInt;
   Callback: TAsyncCallback;
   Callback: TAsyncCallback;
-  UserData: Pointer); cdecl;
+  UserData: Pointer): TAsyncResult; cdecl;
 
 
 procedure asyncClearIOCallback(
 procedure asyncClearIOCallback(
   Handle: TAsyncHandle;
   Handle: TAsyncHandle;
   IOHandle: LongInt); cdecl;
   IOHandle: LongInt); cdecl;
 
 
-procedure asyncSetDataAvailableCallback(
+function asyncSetDataAvailableCallback(
   Handle: TAsyncHandle;
   Handle: TAsyncHandle;
   IOHandle: LongInt;
   IOHandle: LongInt;
   Callback: TAsyncCallback;
   Callback: TAsyncCallback;
-  UserData: Pointer); cdecl;
+  UserData: Pointer): TAsyncResult; cdecl;
 
 
 procedure asyncClearDataAvailableCallback(
 procedure asyncClearDataAvailableCallback(
   Handle: TAsyncHandle;
   Handle: TAsyncHandle;
   IOHandle: LongInt); cdecl;
   IOHandle: LongInt); cdecl;
 
 
-procedure asyncSetCanWriteCallback(
+function asyncSetCanWriteCallback(
   Handle: TAsyncHandle;
   Handle: TAsyncHandle;
   IOHandle: LongInt;
   IOHandle: LongInt;
   Callback: TAsyncCallback;
   Callback: TAsyncCallback;
-  UserData: Pointer); cdecl;
+  UserData: Pointer): TAsyncResult; cdecl;
 
 
 procedure asyncClearCanWriteCallback(
 procedure asyncClearCanWriteCallback(
   Handle: TAsyncHandle;
   Handle: TAsyncHandle;
@@ -104,8 +110,8 @@ procedure asyncClearCanWriteCallback(
 
 
 {
 {
   $Log$
   $Log$
-  Revision 1.2  2002-09-07 15:42:52  peter
-    * old logs removed and tabs fixed
+  Revision 1.3  2002-09-15 15:43:30  sg
+  * Improved error reporting
 
 
   Revision 1.1  2002/01/29 17:54:53  peter
   Revision 1.1  2002/01/29 17:54:53  peter
     * splitted to base and extra
     * splitted to base and extra

+ 99 - 54
packages/base/libasync/unix/libasync.pp

@@ -2,7 +2,7 @@
     $Id$
     $Id$
 
 
     libasync: Asynchronous event management
     libasync: Asynchronous event management
-    Copyright (C) 2001 by
+    Copyright (C) 2001-2002 by
       Areca Systems GmbH / Sebastian Guenther, [email protected]
       Areca Systems GmbH / Sebastian Guenther, [email protected]
 
 
     Unix implementation
     Unix implementation
@@ -25,9 +25,11 @@ type
 
 
   TAsyncData = record
   TAsyncData = record
     IsRunning, DoBreak: Boolean;
     IsRunning, DoBreak: Boolean;
-    HasCallbacks: Boolean;      // True as long as callbacks are set
+    HasCallbacks: Boolean;	// True as long as callbacks are set
     FirstTimer: Pointer;
     FirstTimer: Pointer;
     FirstIOCallback: Pointer;
     FirstIOCallback: Pointer;
+    CurIOCallback: Pointer;	// current callback being processed within 'run'
+    NextIOCallback: Pointer;	// next callback to get processed within 'run'
     FDData: Pointer;
     FDData: Pointer;
     HighestHandle: LongInt;
     HighestHandle: LongInt;
   end;
   end;
@@ -69,16 +71,20 @@ type
 
 
 
 
 
 
-procedure InitIOCallback(Handle: TAsyncHandle; IOHandle: LongInt;
+function InitIOCallback(Handle: TAsyncHandle; IOHandle: LongInt;
   ARead: Boolean; ReadCallback: TAsyncCallback; ReadUserData: Pointer;
   ARead: Boolean; ReadCallback: TAsyncCallback; ReadUserData: Pointer;
-  AWrite: Boolean; WriteCallback: TAsyncCallback; WriteUserData: Pointer);
+  AWrite: Boolean; WriteCallback: TAsyncCallback; WriteUserData: Pointer):
+  TAsyncResult;
 var
 var
   Data: PIOCallbackData;
   Data: PIOCallbackData;
   i: LongInt;
   i: LongInt;
   NeedData: Boolean;
   NeedData: Boolean;
 begin
 begin
   if IOHandle > MaxHandle then
   if IOHandle > MaxHandle then
+  begin
+    Result := asyncInvalidFileHandle;
     exit;
     exit;
+  end;
 
 
   NeedData := True;
   NeedData := True;
   Data := Handle^.Data.FirstIOCallback;
   Data := Handle^.Data.FirstIOCallback;
@@ -88,13 +94,23 @@ begin
     begin
     begin
       if ARead then
       if ARead then
       begin
       begin
+        if Assigned(Data^.ReadCallback) then
+	begin
+	  Result := asyncHandlerAlreadySet;
+	  exit;
+	end;
         Data^.ReadCallback := ReadCallback;
         Data^.ReadCallback := ReadCallback;
-        Data^.ReadUserData := ReadUserData;
+	Data^.ReadUserData := ReadUserData;
       end;
       end;
       if AWrite then
       if AWrite then
       begin
       begin
+        if Assigned(Data^.WriteCallback) then
+	begin
+	  Result := asyncHandlerAlreadySet;
+	  exit;
+	end;
         Data^.WriteCallback := WriteCallback;
         Data^.WriteCallback := WriteCallback;
-        Data^.WriteUserData := WriteUserData;
+	Data^.WriteUserData := WriteUserData;
       end;
       end;
       NeedData := False;
       NeedData := False;
       break;
       break;
@@ -153,13 +169,14 @@ begin
     Open_RdWr:
     Open_RdWr:
       begin
       begin
         if ARead then
         if ARead then
-          FD_Set(IOHandle, PFDSet(Handle^.Data.FDData)[0]);
-        if AWrite then
-          FD_Set(IOHandle, PFDSet(Handle^.Data.FDData)[1]);
+	  FD_Set(IOHandle, PFDSet(Handle^.Data.FDData)[0]);
+	if AWrite then
+	  FD_Set(IOHandle, PFDSet(Handle^.Data.FDData)[1]);
       end;
       end;
   end;
   end;
 
 
   Handle^.Data.HasCallbacks := True;
   Handle^.Data.HasCallbacks := True;
+  Result := asyncOK;
 end;
 end;
 
 
 procedure CheckForCallbacks(Handle: TAsyncHandle);
 procedure CheckForCallbacks(Handle: TAsyncHandle);
@@ -202,6 +219,8 @@ begin
     IOCallback := NextIOCallback;
     IOCallback := NextIOCallback;
   end;
   end;
 
 
+  Handle^.Data.NextIOCallback := nil;
+
   if Assigned(Handle^.Data.FDData) then
   if Assigned(Handle^.Data.FDData) then
     FreeMem(Handle^.Data.FDData);
     FreeMem(Handle^.Data.FDData);
 end;
 end;
@@ -212,7 +231,7 @@ var
   TimeOut, AsyncResult: Integer;
   TimeOut, AsyncResult: Integer;
   CurTime, NextTick: Int64;
   CurTime, NextTick: Int64;
   CurReadFDSet, CurWriteFDSet: TFDSet;
   CurReadFDSet, CurWriteFDSet: TFDSet;
-  IOCallback: PIOCallbackData;
+  CurIOCallback: PIOCallbackData;
 begin
 begin
   if Handle^.Data.IsRunning then
   if Handle^.Data.IsRunning then
     exit;
     exit;
@@ -244,8 +263,8 @@ begin
       while Assigned(Timer) do
       while Assigned(Timer) do
       begin
       begin
         if Timer^.NextTick < NextTick then
         if Timer^.NextTick < NextTick then
-          NextTick := Timer^.NextTick;
-        Timer := Timer^.Next;
+	  NextTick := Timer^.NextTick;
+	Timer := Timer^.Next;
       end;
       end;
       TimeOut := NextTick - CurTime;
       TimeOut := NextTick - CurTime;
       if TimeOut < 0 then
       if TimeOut < 0 then
@@ -270,48 +289,60 @@ begin
       while Assigned(Timer) do
       while Assigned(Timer) do
       begin
       begin
         if Timer^.NextTick <= CurTime then
         if Timer^.NextTick <= CurTime then
-        begin
-          Timer^.Callback(Timer^.UserData);
-          NextTimer := Timer^.Next;
-          if Timer^.Periodic then
-            Inc(Timer^.NextTick, Timer^.MSec)
-          else
-            asyncRemoveTimer(Handle, Timer);
-          if Handle^.Data.DoBreak then
-            break;
-          Timer := NextTimer;
-        end else
-          Timer := Timer^.Next;
+	begin
+	  Timer^.Callback(Timer^.UserData);
+	  NextTimer := Timer^.Next;
+	  if Timer^.Periodic then
+	    Inc(Timer^.NextTick, Timer^.MSec)
+	  else
+	    asyncRemoveTimer(Handle, Timer);
+	  if Handle^.Data.DoBreak then
+	    break;
+	  Timer := NextTimer;
+	end else
+	  Timer := Timer^.Next;
       end;
       end;
     end;
     end;
 
 
     if (AsyncResult > 0) and not Handle^.Data.DoBreak then
     if (AsyncResult > 0) and not Handle^.Data.DoBreak then
     begin
     begin
       // Check for I/O events
       // Check for I/O events
-      IOCallback := Handle^.Data.FirstIOCallback;
-      while Assigned(IOCallback) do
+      Handle^.Data.CurIOCallback := Handle^.Data.FirstIOCallback;
+      while Assigned(Handle^.Data.CurIOCallback) do
       begin
       begin
-        if FD_IsSet(IOCallback^.IOHandle, CurReadFDSet) and
-          FD_IsSet(IOCallback^.IOHandle, PFDSet(Handle^.Data.FDData)[0]) then
-        begin
-          IOCallback^.ReadCallback(IOCallback^.ReadUserData);
-          if Handle^.Data.DoBreak then
-            break;
-        end;
-
-        if FD_IsSet(IOCallback^.IOHandle, CurWriteFDSet) and
-          FD_IsSet(IOCallback^.IOHandle, PFDSet(Handle^.Data.FDData)[1]) then
-        begin
-          IOCallback^.WriteCallback(IOCallback^.WriteUserData);
-          if Handle^.Data.DoBreak then
-            break;
-        end;
-
-        IOCallback := IOCallback^.Next;
+        CurIOCallback := PIOCallbackData(Handle^.Data.CurIOCallback);
+        Handle^.Data.NextIOCallback := CurIOCallback^.Next;
+	if FD_IsSet(CurIOCallback^.IOHandle, CurReadFDSet) and
+	  FD_IsSet(CurIOCallback^.IOHandle, PFDSet(Handle^.Data.FDData)[0]) and
+	  Assigned(CurIOCallback^.ReadCallback) then
+	begin
+	  CurIOCallback^.ReadCallback(CurIOCallback^.ReadUserData);
+	  if Handle^.Data.DoBreak then
+	    break;
+	end;
+
+	CurIOCallback := PIOCallbackData(Handle^.Data.CurIOCallback);
+	if Assigned(CurIOCallback) and
+	  FD_IsSet(CurIOCallback^.IOHandle, CurWriteFDSet) and
+	  FD_IsSet(CurIOCallback^.IOHandle, PFDSet(Handle^.Data.FDData)[1]) and
+	  Assigned(CurIOCallback^.WriteCallback) then
+	begin
+	  CurIOCallback^.WriteCallback(CurIOCallback^.WriteUserData);
+	  if Handle^.Data.DoBreak then
+	    break;
+	end;
+
+	Handle^.Data.CurIOCallback := Handle^.Data.NextIOCallback;
       end;
       end;
     end;
     end;
   end;
   end;
+  Handle^.Data.CurIOCallback := nil;
+  Handle^.Data.NextIOCallback := nil;
   Handle^.Data.IsRunning := False;
   Handle^.Data.IsRunning := False;
+
+  WriteLn('DoBreak: ', Handle^.Data.DoBreak);
+  Writeln('HasCallbacks: ', Handle^.Data.HasCallbacks);
+  WriteLn('FirstCallback: ', Integer(Handle^.Data.HasCallbacks));
 end;
 end;
 
 
 procedure asyncBreak(Handle: TAsyncHandle); cdecl;
 procedure asyncBreak(Handle: TAsyncHandle); cdecl;
@@ -386,13 +417,13 @@ begin
   CheckForCallbacks(Handle);
   CheckForCallbacks(Handle);
 end;
 end;
 
 
-procedure asyncSetIOCallback(
+function asyncSetIOCallback(
   Handle: TAsyncHandle;
   Handle: TAsyncHandle;
   IOHandle: LongInt;
   IOHandle: LongInt;
   Callback: TAsyncCallback;
   Callback: TAsyncCallback;
-  UserData: Pointer); cdecl;
+  UserData: Pointer): TAsyncResult; cdecl;
 begin
 begin
-  InitIOCallback(Handle, IOHandle, True, Callback, UserData,
+  Result := InitIOCallback(Handle, IOHandle, True, Callback, UserData,
     True, Callback, UserData);
     True, Callback, UserData);
 end;
 end;
 
 
@@ -408,6 +439,10 @@ begin
     NextData := CurData^.Next;
     NextData := CurData^.Next;
     if CurData^.IOHandle = IOHandle then
     if CurData^.IOHandle = IOHandle then
     begin
     begin
+      if Handle^.Data.CurIOCallback = CurData then
+        Handle^.Data.CurIOCallback := nil;
+      if Handle^.Data.NextIOCallback = CurData then
+        Handle^.Data.NextIOCallback := NextData;
       FD_Clr(IOHandle, PFDSet(Handle^.Data.FDData)[0]);
       FD_Clr(IOHandle, PFDSet(Handle^.Data.FDData)[0]);
       FD_Clr(IOHandle, PFDSet(Handle^.Data.FDData)[1]);
       FD_Clr(IOHandle, PFDSet(Handle^.Data.FDData)[1]);
       if Assigned(PrevData) then
       if Assigned(PrevData) then
@@ -423,13 +458,14 @@ begin
   CheckForCallbacks(Handle);
   CheckForCallbacks(Handle);
 end;
 end;
 
 
-procedure asyncSetDataAvailableCallback(
+function asyncSetDataAvailableCallback(
   Handle: TAsyncHandle;
   Handle: TAsyncHandle;
   IOHandle: LongInt;
   IOHandle: LongInt;
   Callback: TAsyncCallback;
   Callback: TAsyncCallback;
-  UserData: Pointer); cdecl;
+  UserData: Pointer): TAsyncResult; cdecl;
 begin
 begin
-  InitIOCallback(Handle, IOHandle, True, Callback, UserData, False, nil, nil);
+  Result := InitIOCallback(Handle, IOHandle, True, Callback, UserData, False,
+    nil, nil);
 end;
 end;
 
 
 procedure asyncClearDataAvailableCallback(Handle: TAsyncHandle;
 procedure asyncClearDataAvailableCallback(Handle: TAsyncHandle;
@@ -444,6 +480,10 @@ begin
     NextData := CurData^.Next;
     NextData := CurData^.Next;
     if CurData^.IOHandle = IOHandle then
     if CurData^.IOHandle = IOHandle then
     begin
     begin
+      if Handle^.Data.CurIOCallback = CurData then
+        Handle^.Data.CurIOCallback := nil;
+      if Handle^.Data.NextIOCallback = CurData then
+        Handle^.Data.NextIOCallback := NextData;
       FD_Clr(IOHandle, PFDSet(Handle^.Data.FDData)[0]);
       FD_Clr(IOHandle, PFDSet(Handle^.Data.FDData)[0]);
       if Assigned(CurData^.WriteCallback) then
       if Assigned(CurData^.WriteCallback) then
         CurData^.ReadCallback := nil
         CurData^.ReadCallback := nil
@@ -463,13 +503,14 @@ begin
   CheckForCallbacks(Handle);
   CheckForCallbacks(Handle);
 end;
 end;
 
 
-procedure asyncSetCanWriteCallback(
+function asyncSetCanWriteCallback(
   Handle: TAsyncHandle;
   Handle: TAsyncHandle;
   IOHandle: LongInt;
   IOHandle: LongInt;
   Callback: TAsyncCallback;
   Callback: TAsyncCallback;
-  UserData: Pointer); cdecl;
+  UserData: Pointer): TAsyncResult; cdecl;
 begin
 begin
-  InitIOCallback(Handle, IOHandle, False, nil, nil, True, Callback, UserData);
+  Result := InitIOCallback(Handle, IOHandle, False, nil, nil, True,
+    Callback, UserData);
 end;
 end;
 
 
 procedure asyncClearCanWriteCallback(Handle: TAsyncHandle;
 procedure asyncClearCanWriteCallback(Handle: TAsyncHandle;
@@ -484,6 +525,10 @@ begin
     NextData := CurData^.Next;
     NextData := CurData^.Next;
     if CurData^.IOHandle = IOHandle then
     if CurData^.IOHandle = IOHandle then
     begin
     begin
+      if Handle^.Data.CurIOCallback = CurData then
+        Handle^.Data.CurIOCallback := nil;
+      if Handle^.Data.NextIOCallback = CurData then
+        Handle^.Data.NextIOCallback := NextData;
       FD_Clr(IOHandle, PFDSet(Handle^.Data.FDData)[1]);
       FD_Clr(IOHandle, PFDSet(Handle^.Data.FDData)[1]);
       if Assigned(CurData^.ReadCallback) then
       if Assigned(CurData^.ReadCallback) then
         CurData^.WriteCallback := nil
         CurData^.WriteCallback := nil
@@ -509,8 +554,8 @@ end.
 
 
 {
 {
   $Log$
   $Log$
-  Revision 1.2  2002-09-07 15:42:52  peter
-    * old logs removed and tabs fixed
+  Revision 1.3  2002-09-15 15:43:30  sg
+  * Improved error reporting
 
 
   Revision 1.1  2002/01/29 17:54:53  peter
   Revision 1.1  2002/01/29 17:54:53  peter
     * splitted to base and extra
     * splitted to base and extra