0023286: Standard_Mutex behavior depends on platform
authoromy <omy@opencascade.com>
Fri, 16 Nov 2012 09:14:25 +0000 (13:14 +0400)
committeromy <omy@opencascade.com>
Fri, 23 Nov 2012 11:38:27 +0000 (15:38 +0400)
Implemented recursive POSIX mutex instead of non-recursive,
Removed SentryNested class, implemented it's features into Sentry class
Added second constructor to Sentry class

src/BRepMesh/BRepMesh_FastDiscretFace.cxx
src/Standard/Standard_MMgrOpt.cxx
src/Standard/Standard_Mutex.cxx
src/Standard/Standard_Mutex.hxx

index 943e278..f02445e 100755 (executable)
@@ -57,8 +57,6 @@
 
 #define UVDEFLECTION 1.e-05
 
-static Standard_Mutex DummyMutex;
-
 static Standard_Real FUN_CalcAverageDUV(TColStd_Array1OfReal& P, const Standard_Integer PLen)
 {
   Standard_Integer i, j, n = 0;
@@ -363,8 +361,7 @@ Standard_Boolean BRepMesh_FastDiscretFace::RestoreStructureFromTriangulation
   {
     // lock mutex during querying data from edge curves to prevent parallel change of the same data
     Standard_Mutex* aMutex = theMutexProvider.GetMutex(theEdge);
-    Standard_Mutex::SentryNested aSentry(aMutex == NULL ? DummyMutex : *aMutex,
-                                  aMutex != NULL);
+    Standard_Mutex::Sentry aSentry (aMutex);
 
     Poly = BRep_Tool::PolygonOnTriangulation(theEdge, theTrigu, theLoc);
     if (Poly.IsNull() || !Poly->HasParameters())
@@ -1636,8 +1633,7 @@ void BRepMesh_FastDiscretFace::AddInShape(const TopoDS_Face&  theFace,
 
       // lock mutex to prevent parallel change of the same data
       Standard_Mutex* aMutex = theMutexProvider.GetMutex(It.Key());
-      Standard_Mutex::SentryNested aSentry(aMutex == NULL ? DummyMutex : *aMutex,
-                                    aMutex != NULL);
+      Standard_Mutex::Sentry aSentry (aMutex);
 
       if ( NOD1 == NOD2 ) {
         B.UpdateEdge(TopoDS::Edge(It.Key()), NullPoly, TOld,loc);
index ce8751a..13f246c 100755 (executable)
@@ -394,7 +394,7 @@ Standard_Address Standard_MMgrOpt::Allocate(const Standard_Size aSize)
       // and lock the specific mutex used to protect access to small blocks pools;
       // note that this is done by sentry class so as to ensure unlocking in case of 
       // possible exception that may be thrown from AllocMemory()
-      Standard_Mutex::SentryNested aSentry ( myMutexPools, myReentrant );
+      Standard_Mutex::Sentry aSentry (myReentrant ? &myMutexPools : NULL); 
 
       // check for availability of requested space in the current pool
       Standard_Size *aBlock = myNextAddr;
@@ -533,7 +533,7 @@ void Standard_MMgrOpt::Free(Standard_Address& theStorage)
 Standard_Integer Standard_MMgrOpt::Purge(Standard_Boolean )//isDeleted)
 {
   // Lock access to critical data by mutex
-  Standard_Mutex::SentryNested aSentry (myMutex, myReentrant);
+  Standard_Mutex::Sentry aSentry (myReentrant ? &myMutex : NULL);
 
   // TODO: implement support for isDeleted = True
   
@@ -553,7 +553,7 @@ Standard_Integer Standard_MMgrOpt::Purge(Standard_Boolean )//isDeleted)
   }
 
   // Lock access to critical data by mutex
-  Standard_Mutex::SentryNested aSentry1 ( myMutexPools, myReentrant );
+  Standard_Mutex::Sentry aSentry1 (myReentrant ? &myMutexPools : NULL);
 
   // release memory pools containing no busy memory;
   // for that for each pool count the summary size of blocks
@@ -696,7 +696,7 @@ Standard_Integer Standard_MMgrOpt::Purge(Standard_Boolean )//isDeleted)
 void Standard_MMgrOpt::FreePools()
 {
   // Lock access to critical data by mutex
-  Standard_Mutex::SentryNested aSentry ( myMutexPools, myReentrant );
+  Standard_Mutex::Sentry aSentry (myReentrant ? &myMutexPools : NULL);
     
   // last pool is remembered in myAllocList
   Standard_Size * aFree = myAllocList;
index 84ec10e..ea890d2 100755 (executable)
@@ -22,8 +22,8 @@
 // and is surrounded by #ifdef in MS VC++ 7.1 headers.
 // Thus to use it we need to define appropriate macro saying that we wil
 // run on Windows NT 4.0 at least
-#if defined(WNT) && ! defined(_WIN32_WINNT)
-#define _WIN32_WINNT 0x0400
+#if ((defined(_WIN32) || defined(__WIN32__)) && !defined(_WIN32_WINNT))
+  #define _WIN32_WINNT 0x0400
 #endif
 
 #include <Standard_Mutex.hxx>
 
 Standard_Mutex::Standard_Mutex () 
 {
-#ifdef WNT
-  InitializeCriticalSection( &myMutex );
+#if (defined(_WIN32) || defined(__WIN32__))
+  InitializeCriticalSection (&myMutex);
 #else
-  pthread_mutex_init( &myMutex, 0 );
+  pthread_mutexattr_t anAttr;
+  pthread_mutexattr_init (&anAttr);
+  pthread_mutexattr_settype (&anAttr, PTHREAD_MUTEX_RECURSIVE);
+  pthread_mutex_init (&myMutex, &anAttr);
+  pthread_mutexattr_destroy (&anAttr);
 #endif
 }
 
@@ -48,10 +52,10 @@ Standard_Mutex::Standard_Mutex ()
 
 Standard_Mutex::~Standard_Mutex () 
 {
-#ifdef WNT
-  DeleteCriticalSection( &myMutex );
+#if (defined(_WIN32) || defined(__WIN32__))
+  DeleteCriticalSection (&myMutex);
 #else
-  pthread_mutex_destroy( &myMutex );
+  pthread_mutex_destroy (&myMutex);
 #endif
 }
 
@@ -61,10 +65,10 @@ Standard_Mutex::~Standard_Mutex ()
 
 void Standard_Mutex::Lock ()
 {
-#ifdef WNT
-  EnterCriticalSection( &myMutex );
+#if (defined(_WIN32) || defined(__WIN32__))
+  EnterCriticalSection (&myMutex);
 #else
-  pthread_mutex_lock( &myMutex );
+  pthread_mutex_lock (&myMutex);
 #endif
 }
 
@@ -74,10 +78,10 @@ void Standard_Mutex::Lock ()
 
 Standard_Boolean Standard_Mutex::TryLock ()
 {
-#ifdef WNT
-  return ( TryEnterCriticalSection( &myMutex ) != 0 );
+#if (defined(_WIN32) || defined(__WIN32__))
+  return (TryEnterCriticalSection (&myMutex) != 0);
 #else
-  return ( pthread_mutex_trylock( &myMutex ) != EBUSY );
+  return (pthread_mutex_trylock (&myMutex) != EBUSY);
 #endif
 }
 
index 1411c06..f3195ae 100755 (executable)
 #include <Standard_Boolean.hxx>
 #include <Standard_ErrorHandlerCallback.hxx>
 
-#ifdef WNT
-#include <windows.h>
+#if (defined(_WIN32) || defined(__WIN32__))
+  #include <windows.h>
 #else
-#include <pthread.h>
-#include <sys/errno.h>
-#include <unistd.h>
-#include <time.h>
+  #include <pthread.h>
+  #include <sys/errno.h>
+  #include <unistd.h>
+  #include <time.h>
 #endif
 
 /** 
@@ -85,92 +85,56 @@ public:
 
     //! Constructor - initializes the sentry object by reference to a
     //! mutex (which must be initialized) and locks the mutex immediately
-    Sentry (Standard_Mutex &theMutex)
-      : myMutex(theMutex)
+    Sentry (Standard_Mutex& theMutex)
+    : myMutex (&theMutex)
     {
-      myMutex.Lock();
-      myMutex.RegisterCallback();
+      Lock();
     }
     
+    //! Constructor - initializes the sentry object by pointer to a
+    //! mutex and locks the mutex if its pointer is not NULL
+    Sentry (Standard_Mutex* theMutex)
+    : myMutex (theMutex)
+    {
+      if (myMutex != NULL)
+      {
+        Lock();
+      }
+    }
     //! Destructor - unlocks the mutex if already locked.
-    ~Sentry () { 
-      myMutex.UnregisterCallback();
-      myMutex.Unlock(); 
+    ~Sentry()
+    {
+      if (myMutex != NULL)
+      {
+        Unlock();
+      }
     }
 
-
   private:
-    //! This method should not be called (prohibited).
-    Sentry (const Sentry &);
-    //! This method should not be called (prohibited).
-    Sentry& operator = (const Sentry &);
-
-  private:
-    Standard_Mutex &myMutex;
-  };
-  
-  /**
-    * @brief Advanced Sentry class providing convenient interface to 
-    *        manipulate a mutex from one thread.
-    * 
-    * As compared with simple Sentry class, provides possibility to 
-    * lock and unlock mutex at any moment, and perform nested lock/unlock 
-    * actions (using lock counter). However all calls must be from within
-    * the same thread; this is to be ensured by the code using this class.
-    */
-  class SentryNested
-  {
-  public:
 
-    //! Constructor - initializes the sentry object by reference to a
-    //! mutex (which must be initialized). Locks the mutex immediately
-    //! unless Standard_False is given as second argument.
-    SentryNested (Standard_Mutex &theMutex, Standard_Boolean doLock = Standard_True)
-      : myMutex(theMutex), nbLocked(0)
-    {
-      if ( doLock ) Lock();
-    }
-    
-    //! Destructor - unlocks the mutex if already locked.
-    ~SentryNested () 
-    { 
-      if ( nbLocked >0 ) { 
-       nbLocked = 1; 
-       Unlock(); 
-      } 
-    }
-    
     //! Lock the mutex
-    void Lock () { 
-      if ( ! nbLocked ) {
-       myMutex.Lock(); 
-       myMutex.RegisterCallback();
-      }
-      nbLocked++; 
+    void Lock()
+    {
+      myMutex->Lock();
+      myMutex->RegisterCallback();
     }
-    
+
     //! Unlock the mutex
-    void Unlock () { 
-      if ( nbLocked == 1 ) {
-       myMutex.UnregisterCallback();
-       myMutex.Unlock(); 
-      }
-      nbLocked--; 
+    void Unlock()
+    {
+      myMutex->UnregisterCallback();
+      myMutex->Unlock();
     }
-    
-  private:
+
     //! This method should not be called (prohibited).
-    SentryNested (const SentryNested &);
+    Sentry (const Sentry &);
     //! This method should not be called (prohibited).
-    SentryNested& operator = (const SentryNested &);
+    Sentry& operator = (const Sentry &);
 
   private:
-    Standard_Mutex &myMutex;
-    Standard_Boolean nbLocked; //!< Note that we do not protect this field from 
-                               //!< concurrent access, as it should always be accessed
-                               //!< from within one thread, i.e. synchronously
+    Standard_Mutex* myMutex;
   };
-  
+   
 public:
   
   //! Constructor: creates a mutex object and initializes it.
@@ -204,7 +168,7 @@ private:
   Standard_Mutex& operator = (const Standard_Mutex &);
   
 private:
-#ifdef WNT
+#if (defined(_WIN32) || defined(__WIN32__))
   CRITICAL_SECTION myMutex;
 #else
   pthread_mutex_t myMutex;
@@ -215,10 +179,10 @@ private:
 // just a shortcut to system function
 inline void Standard_Mutex::Unlock ()
 {
-#ifdef WNT
-  LeaveCriticalSection( &myMutex );
+#if (defined(_WIN32) || defined(__WIN32__))
+  LeaveCriticalSection (&myMutex);
 #else
-  pthread_mutex_unlock( &myMutex );
+  pthread_mutex_unlock (&myMutex);
 #endif
 }