OCC22577 Thread-safety/re-entrability improvements
authorRLN and KGV <>
Wed, 20 Jul 2011 15:21:54 +0000 (15:21 +0000)
committerbugmaster <bugmaster@opencascade.com>
Mon, 5 Mar 2012 15:29:28 +0000 (19:29 +0400)
src/AIS/AIS_GlobalStatus.cxx
src/AIS/AIS_InteractiveContext.cxx
src/Standard/Handle_Standard_Transient.cxx
src/Standard/Standard_Atomic.hxx
src/Standard/Standard_Transient_proto.hxx

index 22e8297..bcf2c6a 100755 (executable)
@@ -3,15 +3,9 @@
 // Author:     Robert COUBLANC
 //             <rob@robox.paris1.matra-dtv.fr>
 
-
 #include <AIS_GlobalStatus.ixx>
 #include <TColStd_ListIteratorOfListOfInteger.hxx>
 
-
-
-static TColStd_ListIteratorOfListOfInteger It;
-
-
 AIS_GlobalStatus::AIS_GlobalStatus():
 myStatus(AIS_DS_None),
 myLayerIndex(0),
@@ -37,22 +31,32 @@ mySubInt(Standard_False)
   mySelModes.Append(SMode);
 }
 
-
 void AIS_GlobalStatus::RemoveDisplayMode(const Standard_Integer aMode)
 {
-  for(It.Initialize(myDispModes);It.More();It.Next()){
-    if(It.Value()==aMode){ myDispModes.Remove(It);
-                          return;}
+  TColStd_ListIteratorOfListOfInteger anIt (myDispModes);
+  for (; anIt.More(); anIt.Next())
+  {
+    if (anIt.Value() == aMode)
+    {
+      myDispModes.Remove (anIt);
+      return;
+    }
   }
 }
 
 void AIS_GlobalStatus::RemoveSelectionMode(const Standard_Integer aMode)
 {
-  for(It.Initialize(mySelModes);It.More();It.Next()){
-    if(It.Value()==aMode){ mySelModes.Remove(It);
-                          return;}
+  TColStd_ListIteratorOfListOfInteger anIt (mySelModes);
+  for (; anIt.More(); anIt.Next())
+  {
+    if (anIt.Value() == aMode)
+    {
+      mySelModes.Remove (anIt);
+      return;
+    }
   }
 }
+
 void AIS_GlobalStatus::ClearSelectionModes()
 {
   mySelModes.Clear();
@@ -60,16 +64,26 @@ void AIS_GlobalStatus::ClearSelectionModes()
 
 Standard_Boolean AIS_GlobalStatus::IsDModeIn(const Standard_Integer aMode) const 
 {
-  for(It.Initialize(myDispModes);It.More();It.Next())
-    if(It.Value()==aMode) return Standard_True;
+  TColStd_ListIteratorOfListOfInteger anIt (myDispModes);
+  for (; anIt.More(); anIt.Next())
+  {
+    if (anIt.Value() == aMode)
+    {
+      return Standard_True;
+    }
+  }
   return Standard_False;
-  
 }
 
 Standard_Boolean AIS_GlobalStatus::IsSModeIn(const Standard_Integer aMode) const 
 {
-  for(It.Initialize(mySelModes);It.More();It.Next())
-    if(It.Value()==aMode) return Standard_True;
+  TColStd_ListIteratorOfListOfInteger anIt (mySelModes);
+  for (; anIt.More(); anIt.Next())
+  {
+    if (anIt.Value() == aMode)
+    {
+      return Standard_True;
+    }
+  }
   return Standard_False;
 }
-
index 53c278b..577102c 100755 (executable)
@@ -57,6 +57,7 @@
 #include <Prs3d_DatumAspect.hxx>
 #include <Prs3d_PlaneAspect.hxx>
 #include <PrsMgr_PresentableObject.hxx>
+#include <Standard_Atomic.hxx>
 #include <UnitsAPI.hxx>
 
 #include <AIS_Trihedron.hxx>
@@ -91,28 +92,23 @@ static Standard_Boolean AISDebugModeOn()
   return (isDebugMode != 0);
 }
 
-static TCollection_AsciiString AIS_Context_NewSelName()
+namespace
 {
-  static Standard_Integer index_sel = 1;
-  TCollection_AsciiString name("AIS_SelContext_");
-  TCollection_AsciiString theind(index_sel);
-  name += theind;
-  index_sel++;
-  return name;
-}
-
-static TCollection_AsciiString AIS_Context_NewCurName()
-{
-  static Standard_Integer index_cur = 1;
-  TCollection_AsciiString name("AIS_CurContext_");
-  TCollection_AsciiString theind(index_cur);
-  name += theind;
-  index_cur++;
-  return name;
-}
+  static volatile Standard_Integer THE_AIS_INDEX_SEL = 0;
+  static volatile Standard_Integer THE_AIS_INDEX_CUR = 0;
 
-static TColStd_ListIteratorOfListOfInteger ItL;
+  static TCollection_AsciiString AIS_Context_NewSelName()
+  {
+    return TCollection_AsciiString ("AIS_SelContext_")
+         + TCollection_AsciiString (Standard_Atomic_Increment (&THE_AIS_INDEX_SEL));
+  }
 
+  static TCollection_AsciiString AIS_Context_NewCurName()
+  {
+    return TCollection_AsciiString ("AIS_CurContext_")
+         + TCollection_AsciiString (Standard_Atomic_Increment (&THE_AIS_INDEX_CUR));
+  }
+};
 
 //=======================================================================
 //function : AIS_InteractiveContext
@@ -504,7 +500,8 @@ void AIS_InteractiveContext::Display(const Handle(AIS_InteractiveObject)& anIObj
         updcol = updateviewer;
                          }// attention on fait expres de ne pas mettre de break..
       case AIS_DS_FullErased:{
-        for (ItL.Initialize(STATUS->DisplayedModes());ItL.More();ItL.Next()){
+        TColStd_ListIteratorOfListOfInteger ItL (STATUS->DisplayedModes());
+        for (;ItL.More();ItL.Next()){
           myMainPM->Display(anIObj,ItL.Value());
           if(STATUS->IsSubIntensityOn())
             myMainPM->Color(anIObj,mySubIntensity,ItL.Value());
@@ -523,7 +520,8 @@ void AIS_InteractiveContext::Display(const Handle(AIS_InteractiveObject)& anIObj
       //       Finally, activate selection mode <SelMode> if not yet activated.
       case AIS_DS_Displayed:{
         TColStd_ListOfInteger aModesToRemove;
-        for(ItL.Initialize(STATUS->DisplayedModes());ItL.More();ItL.Next()){
+        TColStd_ListIteratorOfListOfInteger ItL (STATUS->DisplayedModes());
+        for(;ItL.More();ItL.Next()){
 
           Standard_Integer OldMode = ItL.Value();
 
@@ -1817,7 +1815,8 @@ void AIS_InteractiveContext::SetDisplayMode(const Handle(AIS_InteractiveObject)&
       // SAN : erase presentations for all display modes different from <aMode>
       if(STATUS->GraphicStatus()==AIS_DS_Displayed){
         TColStd_ListOfInteger aModesToRemove;
-        for(ItL.Initialize(STATUS->DisplayedModes());ItL.More();ItL.Next()){
+        TColStd_ListIteratorOfListOfInteger ItL (STATUS->DisplayedModes());
+        for(;ItL.More();ItL.Next()){
 
           Standard_Integer OldMode = ItL.Value();
 
@@ -2092,7 +2091,7 @@ void AIS_InteractiveContext::SetDeviationAngle(
  
   if(!anIObj->HasInteractiveContext())
     anIObj->SetContext(this);
-// To be modified after the related methods of AIS_Shape are passed to InteractiveObject
+  // To be modified after the related methods of AIS_Shape are passed to InteractiveObject
   if(anIObj->Type()!=AIS_KOI_Shape) return;
   if(anIObj->Signature()!=0) return;
   (*((Handle(AIS_Shape)*)&anIObj))->SetOwnDeviationAngle(anAngle);
@@ -2134,7 +2133,7 @@ void AIS_InteractiveContext::SetAngleAndDeviation(
   if(!anIObj->HasInteractiveContext())
     anIObj->SetContext(this);
 
-// To be modified after the related methods of AIS_Shape are passed to InteractiveObject
+  // To be modified after the related methods of AIS_Shape are passed to InteractiveObject
   if(anIObj->Type()!=AIS_KOI_Shape) return;
   if(anIObj->Signature()!=0) return;
   (*((Handle(AIS_Shape)*)&anIObj))->SetAngleAndDeviation(anAngle);
@@ -2162,7 +2161,7 @@ void AIS_InteractiveContext::SetHLRAngleAndDeviation(
    if(!anIObj->HasInteractiveContext())
     anIObj->SetContext(this);
 
-// To be modified after the related methods of AIS_Shape are passed to InteractiveObject
+  // To be modified after the related methods of AIS_Shape are passed to InteractiveObject
   if(anIObj->Type()!=AIS_KOI_Shape) return;
   if(anIObj->Signature()!=0) return;
   (*((Handle(AIS_Shape)*)&anIObj))->SetHLRAngleAndDeviation(anAngle);
@@ -2205,7 +2204,7 @@ void AIS_InteractiveContext::SetHLRDeviationAngle(
  
   if(!anIObj->HasInteractiveContext())
     anIObj->SetContext(this);
-// To be modified after the related methods of AIS_Shape are passed to InteractiveObject
+  // To be modified after the related methods of AIS_Shape are passed to InteractiveObject
   if( anIObj->Type()!=AIS_KOI_Shape) return;
   if(anIObj->Signature()!=0) return;
   (*((Handle(AIS_Shape)*)&anIObj))->SetOwnHLRDeviationAngle(anAngle);
@@ -2626,7 +2625,8 @@ void AIS_InteractiveContext::Status(const Handle(AIS_InteractiveObject)& anIObj,
       break;
     }
     astatus += "\t| Active Display Modes in the MainViewer :\n";
-    for(ItL.Initialize(ST->DisplayedModes());ItL.More();ItL.Next()){
+    TColStd_ListIteratorOfListOfInteger ItL (ST->DisplayedModes());
+    for(;ItL.More();ItL.Next()){
       astatus += "\t|\t Mode ";
       astatus += TCollection_AsciiString(ItL.Value());
       astatus+="\n";
@@ -2688,7 +2688,8 @@ void AIS_InteractiveContext::EraseGlobal(const Handle(AIS_InteractiveObject)& an
   Standard_Integer Dmode = anIObj->HasHilightMode() ? anIObj->HilightMode() : 0;
   if(STATUS->GraphicStatus()==AIS_DS_Displayed){
     
-    for(ItL.Initialize(STATUS->DisplayedModes());ItL.More();ItL.Next()){
+    TColStd_ListIteratorOfListOfInteger ItL (STATUS->DisplayedModes());
+    for(;ItL.More();ItL.Next()){
       if(myMainPM->IsHighlighted(anIObj,ItL.Value()))
         myMainPM->Unhighlight(anIObj,ItL.Value());
       myMainPM->Erase(anIObj,ItL.Value());
@@ -2732,7 +2733,8 @@ void AIS_InteractiveContext::ClearGlobal(const Handle(AIS_InteractiveObject)& an
   // const Handle(AIS_GlobalStatus)& STATUS = myObjects(anIObj);
   Handle(AIS_GlobalStatus) STATUS = myObjects(anIObj);
   // ENDCLE
-   for(ItL.Initialize(STATUS->DisplayedModes());ItL.More();ItL.Next()){
+   TColStd_ListIteratorOfListOfInteger ItL (STATUS->DisplayedModes());
+   for(;ItL.More();ItL.Next()){
      if(STATUS->IsHilighted()){
        if(IsCurrent(anIObj))
 #ifdef OCC204
index 2344241..bad55c3 100755 (executable)
@@ -23,12 +23,9 @@ void Handle(Standard_Transient)::Assign (const Standard_Transient *anItem)
 
 void Handle(Standard_Transient)::BeginScope()
 {
-  if (entity != UndefinedHandleAddress) 
+  if (entity != UndefinedHandleAddress)
   {
-    if ( Standard::IsReentrant() ) 
-      Standard_Atomic_Increment (&entity->count);
-    else 
-      entity->count++;
+    Standard_Atomic_Increment (&entity->count);
   }
 }
 
@@ -36,11 +33,9 @@ void Handle(Standard_Transient)::BeginScope()
 
 void Handle(Standard_Transient)::EndScope()
 {
-  if (entity == UndefinedHandleAddress) 
+  if (entity == UndefinedHandleAddress)
     return;
-  if ( Standard::IsReentrant() ? 
-       Standard_Atomic_DecrementTest (&entity->count) : 
-       (--entity->count == 0) )
+  if (Standard_Atomic_Decrement (&entity->count) == 0)
     entity->Delete();
   entity = UndefinedHandleAddress;
 }
index 93f80ec..4208ae2 100755 (executable)
 //! By the moment, only operations necessary for reference counter 
 //! in Standard_Transient objects are implemented.
 //! 
-//! Currently only two x86-based configurations (Windows NT with 
-//! MS VC++ compiler and Linix with GCC) are really supported.
-//! Other configurations use non-atomic C equivalent.
+//! This is preffered to use fixed size types "int32_t" / "int64_t" for
+//! correct function declarations however we leave "int" assuming it is 32bits for now.
 
-//! @fn     void Standard_Atomic_Increment (int volatile* var)
-//! @brief  Increments atomically integer variable pointed by var
+#ifndef _Standard_Atomic_HeaderFile
+#define _Standard_Atomic_HeaderFile
 
-//! @fn     int Standard_Atomic_DecrementTest (int volatile* var)
-//! @brief  Decrements atomically integer variable pointed by var;
-//!         returns 1 if result is zero, 0 otherwise
-
-//===================================================
-// Windows NT, MSVC++ compiler
-//===================================================
-#if defined(WNT)
+#include <Standard_Macro.hxx>
 
+#if (defined(_WIN32) || defined(__WIN32__))
 extern "C" {
-long _InterlockedIncrement(long volatile* lpAddend);
-long _InterlockedDecrement(long volatile* lpAddend);
+  long _InterlockedIncrement(long volatile* lpAddend);
+  long _InterlockedDecrement(long volatile* lpAddend);
 }
+#endif
 
-#pragma intrinsic (_InterlockedIncrement)
-#pragma intrinsic (_InterlockedDecrement)
-
-inline void Standard_Atomic_Increment (int volatile* var)
-{
-  _InterlockedIncrement (reinterpret_cast<long volatile*>(var));
-}
+#if defined(_MSC_VER)
+  // force intrinsic instead of WinAPI calls
+  #pragma intrinsic (_InterlockedIncrement)
+  #pragma intrinsic (_InterlockedDecrement)
+#endif
 
-inline int Standard_Atomic_DecrementTest (int volatile* var)
+//! Increments atomically integer variable pointed by theValue
+//! and returns resulting incremented value.
+static int Standard_Atomic_Increment (volatile int* theValue)
 {
-  return _InterlockedDecrement (reinterpret_cast<long volatile*>(var)) == 0;
-}
-
-//===================================================
-// Linux, GCC compiler
-// Note: Linux kernel 2.6x provides definitions for atomic operators
-//       in the header file /usr/include/asm/atomic.h,
-//       however these definitions involve specific type atomic_t
-// Note: The same code probably would work for Intel compiler
-//===================================================
+#ifdef __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4
+  // mordern g++ compiler (gcc4.4+)
+  // built-in functions available for appropriate CPUs (at least -march=i486 should be specified on x86 platform)
+  return __sync_add_and_fetch (theValue, 1);
+#elif (defined(_WIN32) || defined(__WIN32__))
+  // WinAPI function or MSVC intrinsic
+  return _InterlockedIncrement(reinterpret_cast<long volatile*>(theValue));
 #elif defined(LIN)
-
-inline void Standard_Atomic_Increment (int volatile* var)
-{
-  // C equivalent:
-  // ++(*var);
-
-  __asm__ __volatile__
-  (
-    "lock incl %0"
-  : "=m"(*var) // out
-  : "m" (*var) // in 
-  );
-}
-
-inline int Standard_Atomic_DecrementTest (int volatile* var)
-{
-  // C equivalent:
-  // return --(*var) == 0;
-
-  unsigned char c;
-  __asm__ __volatile__
-  (
-    "lock decl %0; sete %1"
-  : "=m"(*var), "=qm"(c) // out
-  : "m" (*var)           // in
-  : "memory"
-  );
-  return c != 0;
-}
-
-//===================================================
-// Default stub implementation, not atomic actually
-//===================================================
+  // use x86 / x86_64 inline assembly (compatibility with alien compilers / old GCC)
+  int anIncResult;
+  __asm__ __volatile__ (
+  #if defined(_OCC64)
+    "lock xaddl %%ebx, (%%rax) \n\t"
+    "incl %%ebx                \n\t"
+    : "=b" (anIncResult)
+    : "a" (theValue), "b" (1)
+    : "cc", "memory");
+  #else
+    "lock xaddl %%eax, (%%ecx) \n\t"
+    "incl %%eax                \n\t"
+    : "=a" (anIncResult)
+    : "c" (theValue), "a" (1)
+    : "memory");
+  #endif
+  return anIncResult;
 #else
-
-inline void Standard_Atomic_Increment (int volatile* var)
-{
-  ++(*var);
+  //#error "Atomic operation doesn't implemented for current platform!"
+  return ++(*theValue);
+#endif
 }
 
-inline int Standard_Atomic_DecrementTest (int volatile* var)
+//! Decrements atomically integer variable pointed by theValue
+//! and returns resulting decremented value.
+static int Standard_Atomic_Decrement (volatile int* theValue)
 {
-  return --(*var) == 0;
+#ifdef __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4
+  // mordern g++ compiler (gcc4.4+)
+  // built-in functions available for appropriate CPUs (at least -march=i486 should be specified on x86 platform)
+  return __sync_sub_and_fetch (theValue, 1);
+#elif (defined(_WIN32) || defined(__WIN32__))
+  // WinAPI function or MSVC intrinsic
+  return _InterlockedDecrement(reinterpret_cast<long volatile*>(theValue));
+#elif defined(LIN)
+  // use x86 / x86_64 inline assembly (compatibility with alien compilers / old GCC)
+  int aDecResult;
+  __asm__ __volatile__ (
+  #if defined(_OCC64)
+    "lock xaddl %%ebx, (%%rax) \n\t"
+    "decl %%ebx                \n\t"
+    : "=b" (aDecResult)
+    : "a" (theValue), "b" (-1)
+    : "cc", "memory");
+  #else
+    "lock xaddl %%eax, (%%ecx) \n\t"
+    "decl %%eax                \n\t"
+    : "=a" (aDecResult)
+    : "c" (theValue), "a" (-1)
+    : "memory");
+  #endif
+  return aDecResult;
+#else
+  //#error "Atomic operation doesn't implemented for current platform!"
+  return --(*theValue);
+#endif
 }
 
-#endif
+#endif //_Standard_Atomic_HeaderFile
index f771a6e..aedc3d0 100755 (executable)
@@ -86,7 +86,7 @@ class Standard_Transient
 
  private:
 
-   Standard_Integer count;
+   volatile Standard_Integer count;
 };
 
 Standard_EXPORT const Handle(Standard_Type)& STANDARD_TYPE(Standard_Transient);