From 49f38e37fcab4ace24b9ef5a8101e3a476a77205 Mon Sep 17 00:00:00 2001 From: omy Date: Fri, 16 Nov 2012 13:14:25 +0400 Subject: [PATCH] 0023286: Standard_Mutex behavior depends on platform 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 | 8 +- src/Standard/Standard_MMgrOpt.cxx | 8 +- src/Standard/Standard_Mutex.cxx | 32 +++--- src/Standard/Standard_Mutex.hxx | 128 ++++++++-------------- 4 files changed, 70 insertions(+), 106 deletions(-) diff --git a/src/BRepMesh/BRepMesh_FastDiscretFace.cxx b/src/BRepMesh/BRepMesh_FastDiscretFace.cxx index 943e278a9e..f02445eec1 100755 --- a/src/BRepMesh/BRepMesh_FastDiscretFace.cxx +++ b/src/BRepMesh/BRepMesh_FastDiscretFace.cxx @@ -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); diff --git a/src/Standard/Standard_MMgrOpt.cxx b/src/Standard/Standard_MMgrOpt.cxx index ce8751a611..13f246c8a3 100755 --- a/src/Standard/Standard_MMgrOpt.cxx +++ b/src/Standard/Standard_MMgrOpt.cxx @@ -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; diff --git a/src/Standard/Standard_Mutex.cxx b/src/Standard/Standard_Mutex.cxx index 84ec10e6fd..ea890d2451 100755 --- a/src/Standard/Standard_Mutex.cxx +++ b/src/Standard/Standard_Mutex.cxx @@ -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 @@ -35,10 +35,14 @@ 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 } diff --git a/src/Standard/Standard_Mutex.hxx b/src/Standard/Standard_Mutex.hxx index 1411c064f6..f3195aea27 100755 --- a/src/Standard/Standard_Mutex.hxx +++ b/src/Standard/Standard_Mutex.hxx @@ -25,13 +25,13 @@ #include #include -#ifdef WNT -#include +#if (defined(_WIN32) || defined(__WIN32__)) + #include #else -#include -#include -#include -#include + #include + #include + #include + #include #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: + + //! Lock the mutex + void Lock() + { + myMutex->Lock(); + myMutex->RegisterCallback(); + } + + //! Unlock the mutex + void Unlock() + { + myMutex->UnregisterCallback(); + myMutex->Unlock(); + } + //! 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; + 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++; - } - - //! Unlock the mutex - void Unlock () { - if ( nbLocked == 1 ) { - myMutex.UnregisterCallback(); - myMutex.Unlock(); - } - nbLocked--; - } - - private: - //! This method should not be called (prohibited). - SentryNested (const SentryNested &); - //! This method should not be called (prohibited). - SentryNested& operator = (const SentryNested &); - - 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 - }; - + 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 }