]> OCCT Git - occt.git/commitdiff
Coding - Migrate from exception to local status flag for dead loop handling (#817)
authorPasukhin Dmitry <dpasukhi@opencascade.com>
Mon, 10 Nov 2025 21:17:26 +0000 (21:17 +0000)
committerGitHub <noreply@github.com>
Mon, 10 Nov 2025 21:17:26 +0000 (21:17 +0000)
- Transfer_ProcessForFinder_0.cxx: Replace exception throw/catch with
  local status flag in Transferring() method
- Transfer_ProcessForTransient_0.cxx: Same changes for consistency
- Transfer_TransferDeadLoop.hxx: Mark exception class as deprecated with
  Standard_DEPRECATED attribute

The Transfer_TransferDeadLoop class is kept alive but marked as deprecated
for backward compatibility. Dead loop detection is now handled via local
status flags instead of exceptions, improving performance and code clarity.

src/DataExchange/TKXSBase/Transfer/Transfer_ProcessForFinder_0.cxx
src/DataExchange/TKXSBase/Transfer/Transfer_ProcessForTransient_0.cxx
src/DataExchange/TKXSBase/Transfer/Transfer_TransferDeadLoop.hxx

index baf8228ca863c8e82063c67189f02f54953569f7..c593d2a17ba66c0730b63977611f94372798fc43 100644 (file)
@@ -723,6 +723,7 @@ Handle(Transfer_Binder) Transfer_ProcessForFinder::Transferring(
 
   // We consider that this new Transfer request therefore corresponds to a
   // additional use: note "AlreadyUsed", therefore non-modifiable result
+  Standard_Boolean hasDeadLoop = Standard_False;
   if (!former.IsNull())
   {
     if (former->HasResult())
@@ -760,9 +761,11 @@ Handle(Transfer_Binder) Transfer_ProcessForFinder::Transferring(
         }
         else
           StartTrace(former, start, thelevel, 4);
-        throw Transfer_TransferDeadLoop("TransferProcess : Transfer at Head of a Dead Loop");
+        hasDeadLoop = Standard_True;
+        break;
     }
-    former->SetStatusExec(Transfer_StatusRun);
+    if (!hasDeadLoop)
+      former->SetStatusExec(Transfer_StatusRun);
   }
 #ifdef TRANSLOG
   std::cout << " GO .." << std::endl;
@@ -770,53 +773,36 @@ Handle(Transfer_Binder) Transfer_ProcessForFinder::Transferring(
 
   Handle(Transfer_Binder) binder;
   Standard_Boolean        newbind = Standard_False;
-  if (theerrh)
+
+  // Handle dead loop condition detected before calling TransferProduct
+  // When hasDeadLoop is true, we know:
+  // 1. former is NOT null (hasDeadLoop only set inside !former.IsNull() block)
+  // 2. former->StatusExec() == Transfer_StatusLoop (that's what triggered hasDeadLoop)
+  if (hasDeadLoop)
+  {
+    Message_Messenger::StreamBuffer aSender = themessenger->SendInfo();
+    if (thetrace)
+    {
+      aSender << "                  *** Dead Loop : Finding head of Loop :" << std::endl;
+      StartTrace(former, start, thelevel - 1, 0);
+    }
+    else
+      StartTrace(former, start, thelevel - 1, 4);
+    binder = former;
+    binder->AddFail("Transfer: Head of Dead Loop");
+    binder->AddFail("Transfer in dead Loop");
+  }
+  else if (theerrh)
   {
     Message_Messenger::StreamBuffer aSender = themessenger->SendInfo();
 
-    // Transfer under protection for exceptions (for notification in fact
+    // Transfer under protection for exceptions (for notification in fact)
     Standard_Integer oldlev = thelevel;
     try
     {
       OCC_CATCH_SIGNALS
       binder = TransferProduct(start, theProgress);
     }
-
-    // Exceptions to catch up on: they are not all the same
-    catch (Transfer_TransferDeadLoop const&)
-    {
-      if (binder.IsNull())
-      {
-        aSender << "                  *** Dead Loop with no Result" << std::endl;
-        if (thetrace)
-          StartTrace(binder, start, thelevel - 1, 0);
-        binder = new Transfer_VoidBinder;
-        Bind(start, binder);
-        newbind = Standard_True;
-      }
-      else if (binder->StatusExec() == Transfer_StatusLoop)
-      {
-        if (thetrace)
-        {
-          aSender << "                  *** Dead Loop : Finding head of Loop :" << std::endl;
-          StartTrace(binder, start, thelevel - 1, 0);
-        }
-        else
-          StartTrace(binder, start, thelevel - 1, 4);
-        throw Transfer_TransferFailure("TransferProcess : Head of Dead Loop");
-        // In other words, we change the exception (we exit the loop)
-      }
-      else
-      {
-        if (thetrace)
-        {
-          aSender << "                  *** Dead Loop : Actor in Loop :" << std::endl;
-          StartTrace(binder, start, thelevel - 1, 0);
-        }
-      }
-      binder->AddFail("Transfer in dead Loop");
-      thelevel = oldlev;
-    }
     catch (Standard_Failure const& anException)
     {
       if (binder.IsNull())
index 1597665aeada532b8e262de0dc945e1f83c1ea3b..1001b2253f905087c1fe742c056e68d8fb78537e 100644 (file)
@@ -731,6 +731,7 @@ Handle(Transfer_Binder) Transfer_ProcessForTransient::Transferring(
   Handle(Transfer_Binder) former = FindAndMask(start);
   // We consider that this new Transfer request therefore corresponds to a
   // additional use: note "AlreadyUsed", therefore non-modifiable result
+  Standard_Boolean hasDeadLoop = Standard_False;
   if (!former.IsNull())
   {
     if (former->HasResult())
@@ -768,14 +769,35 @@ Handle(Transfer_Binder) Transfer_ProcessForTransient::Transferring(
         }
         else
           StartTrace(former, start, thelevel, 4);
-        throw Transfer_TransferDeadLoop("TransferProcess : Transfer at Head of a Dead Loop");
+        hasDeadLoop = Standard_True;
+        break;
     }
-    former->SetStatusExec(Transfer_StatusRun);
+    if (!hasDeadLoop)
+      former->SetStatusExec(Transfer_StatusRun);
   }
 
   Handle(Transfer_Binder) binder;
   Standard_Boolean        newbind = Standard_False;
-  if (theerrh)
+
+  // Handle dead loop condition detected before calling TransferProduct
+  // When hasDeadLoop is true, we know:
+  // 1. former is NOT null (hasDeadLoop only set inside !former.IsNull() block)
+  // 2. former->StatusExec() == Transfer_StatusLoop (that's what triggered hasDeadLoop)
+  if (hasDeadLoop)
+  {
+    Message_Messenger::StreamBuffer aSender = themessenger->SendInfo();
+    if (thetrace)
+    {
+      aSender << "                  *** Dead Loop : Finding head of Loop :" << std::endl;
+      StartTrace(former, start, thelevel - 1, 0);
+    }
+    else
+      StartTrace(former, start, thelevel - 1, 4);
+    binder = former;
+    binder->AddFail("Transfer: Head of Dead Loop");
+    binder->AddFail("Transfer in dead Loop");
+  }
+  else if (theerrh)
   {
     Message_Messenger::StreamBuffer aSender = themessenger->SendInfo();
 
@@ -786,42 +808,6 @@ Handle(Transfer_Binder) Transfer_ProcessForTransient::Transferring(
       OCC_CATCH_SIGNALS
       binder = TransferProduct(start, theProgress);
     }
-
-    // Exceptions to catch up on: they are not all the same
-    catch (Transfer_TransferDeadLoop const&)
-    {
-      if (binder.IsNull())
-      {
-        aSender << "                  *** Dead Loop with no Result" << std::endl;
-        if (thetrace)
-          StartTrace(binder, start, thelevel - 1, 0);
-        binder = new Transfer_VoidBinder;
-        Bind(start, binder);
-        newbind = Standard_True;
-      }
-      else if (binder->StatusExec() == Transfer_StatusLoop)
-      {
-        if (thetrace)
-        {
-          aSender << "                  *** Dead Loop : Finding head of Loop :" << std::endl;
-          StartTrace(binder, start, thelevel - 1, 0);
-        }
-        else
-          StartTrace(binder, start, thelevel - 1, 4);
-        throw Transfer_TransferFailure("TransferProcess : Head of Dead Loop");
-        // In other words, we change the exception (we exit the loop)
-      }
-      else
-      {
-        if (thetrace)
-        {
-          aSender << "                  *** Dead Loop : Actor in Loop :" << std::endl;
-          StartTrace(binder, start, thelevel - 1, 0);
-        }
-      }
-      binder->AddFail("Transfer in dead Loop");
-      thelevel = oldlev;
-    }
     catch (Standard_Failure const& anException)
     {
       if (binder.IsNull())
index 84d8c37cf6b6eb2781b833c5055f02915636759a..339c9733cc900e0f2666c0adaacccc9b3383033b 100644 (file)
 #include <Standard_SStream.hxx>
 #include <Transfer_TransferFailure.hxx>
 
-class Transfer_TransferDeadLoop;
+//! @deprecated OCCT 7.9.0 - This exception is deprecated and no longer thrown.
+//! Dead loop detection is now handled via local status flags instead of exceptions.
+class Standard_DEPRECATED(
+  "This exception is no longer thrown; dead loop handling uses local status flags")
+  Transfer_TransferDeadLoop;
 DEFINE_STANDARD_HANDLE(Transfer_TransferDeadLoop, Transfer_TransferFailure)
 
 #if !defined No_Exception && !defined No_Transfer_TransferDeadLoop
+  //! @deprecated OCCT 7.9.0 - This macro is deprecated and does nothing.
   #define Transfer_TransferDeadLoop_Raise_if(CONDITION, MESSAGE)                                   \
     if (CONDITION)                                                                                 \
       throw Transfer_TransferDeadLoop(MESSAGE);