From c6eb41e2c63e2536f51ea6ac600dd3882983a522 Mon Sep 17 00:00:00 2001 From: prascle Date: Tue, 5 Oct 2004 18:36:46 +0000 Subject: [PATCH] PR: thread safe singleton --- src/SALOMELocalTrace/LocalTraceBufferPool.cxx | 16 ++++++++--- src/SALOMELocalTrace/LocalTraceBufferPool.hxx | 1 + src/SALOMELocalTrace/LocalTraceCollector.cxx | 28 ++++++++++--------- src/SALOMELocalTrace/LocalTraceCollector.hxx | 1 + 4 files changed, 29 insertions(+), 17 deletions(-) diff --git a/src/SALOMELocalTrace/LocalTraceBufferPool.cxx b/src/SALOMELocalTrace/LocalTraceBufferPool.cxx index 67791553f..49b6d32e6 100644 --- a/src/SALOMELocalTrace/LocalTraceBufferPool.cxx +++ b/src/SALOMELocalTrace/LocalTraceBufferPool.cxx @@ -33,18 +33,26 @@ using namespace std; LocalTraceBufferPool* LocalTraceBufferPool::_singleton = 0; +pthread_mutex_t LocalTraceBufferPool::_singletonMutex; // ============================================================================ /*! - * guarantees a unique object instance of the class (singleton) - * Must be done at first because not thread safe: - * _singleton is not protected by a mutex + * guarantees a unique object instance of the class (singleton thread safe) */ // ============================================================================ LocalTraceBufferPool* LocalTraceBufferPool::instance() { - if (_singleton == 0) _singleton = new LocalTraceBufferPool(); + if (_singleton == 0) // no need of lock when singleton already exists + { + int ret; + ret = pthread_mutex_lock(&_singletonMutex); // acquire lock to be alone + if (_singleton == 0) // another thread may have got + { // the lock after the first test + _singleton = new LocalTraceBufferPool(); + } + ret = pthread_mutex_unlock(&_singletonMutex); // release lock + } return _singleton; } diff --git a/src/SALOMELocalTrace/LocalTraceBufferPool.hxx b/src/SALOMELocalTrace/LocalTraceBufferPool.hxx index 847478005..597b218e8 100644 --- a/src/SALOMELocalTrace/LocalTraceBufferPool.hxx +++ b/src/SALOMELocalTrace/LocalTraceBufferPool.hxx @@ -57,6 +57,7 @@ class LocalTraceBufferPool private: static LocalTraceBufferPool* _singleton; + static pthread_mutex_t _singletonMutex; LocalTrace_TraceInfo _myBuffer[TRACE_BUFFER_SIZE]; sem_t _freeBufferSemaphore; // to wait until there is a free buffer sem_t _fullBufferSemaphore; // to wait until there is a buffer to print diff --git a/src/SALOMELocalTrace/LocalTraceCollector.cxx b/src/SALOMELocalTrace/LocalTraceCollector.cxx index 119722643..1bf05248e 100644 --- a/src/SALOMELocalTrace/LocalTraceCollector.cxx +++ b/src/SALOMELocalTrace/LocalTraceCollector.cxx @@ -32,31 +32,33 @@ using namespace std; LocalTraceCollector* LocalTraceCollector::_singleton = 0; +pthread_mutex_t LocalTraceCollector::_singletonMutex; int LocalTraceCollector::_threadToClose = 0; pthread_t LocalTraceCollector::_threadId = 0; int LocalTraceCollector::_toFile = 0; // public, set by user // ============================================================================ /*! - * guarantees a unique object instance of the class (singleton) - * Must be done at first because not thread safe: - * _singleton is not protected by a mutex - * LocalTraceCollector instance is created, then LocalTraceBufferPool - * instance is created immediately in the same thread (not thread safe, too). - * After thet, a separate thread for loop to print traces is launched. + * guarantees a unique object instance of the class (singleton thread safe) + * a separate thread for loop to print traces is launched. */ // ============================================================================ LocalTraceCollector* LocalTraceCollector::instance() { - if (_singleton == 0) + if (_singleton == 0) // no need of lock when singleton already exists { - _singleton = new LocalTraceCollector(); - LocalTraceBufferPool* initTraceBuffer = LocalTraceBufferPool::instance(); - pthread_t traceThread; - int bid; - int ret = pthread_create(&traceThread, NULL, - LocalTraceCollector::run, (void *)bid); + int ret; + ret = pthread_mutex_lock(&_singletonMutex); // acquire lock to be alone + if (_singleton == 0) // another thread may have got + { // the lock after the first test + _singleton = new LocalTraceCollector(); + pthread_t traceThread; + int bid; + int ret = pthread_create(&traceThread, NULL, + LocalTraceCollector::run, (void *)bid); + } + ret = pthread_mutex_unlock(&_singletonMutex); // release lock } return _singleton; } diff --git a/src/SALOMELocalTrace/LocalTraceCollector.hxx b/src/SALOMELocalTrace/LocalTraceCollector.hxx index 5bcd75139..0b0e56ff5 100644 --- a/src/SALOMELocalTrace/LocalTraceCollector.hxx +++ b/src/SALOMELocalTrace/LocalTraceCollector.hxx @@ -43,6 +43,7 @@ class LocalTraceCollector private: static LocalTraceCollector* _singleton; + static pthread_mutex_t _singletonMutex; static pthread_t _threadId; }; -- 2.39.2