Coding - Migrate from exception to local status flag for dead loop handling (#817)

- 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.
This commit is contained in:
Pasukhin Dmitry
2025-11-10 21:17:26 +00:00
committed by GitHub
parent f9f94b6e36
commit 49cf4baea6
3 changed files with 57 additions and 80 deletions
@@ -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())
@@ -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())
@@ -21,10 +21,15 @@
#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);