From 8653f9512dce5a20db791f25c2e3ca1e26ceea39 Mon Sep 17 00:00:00 2001 From: Slava Monich Date: Wed, 27 May 2015 00:07:48 +0300 Subject: [PATCH] Made shared_ptr thread-safe if compiled by gcc --- .../zlibrary/core/src/util/shared_ptr.h | 67 ++++++++++++++++--- 1 file changed, 57 insertions(+), 10 deletions(-) diff --git a/fbreader/fbreader/zlibrary/core/src/util/shared_ptr.h b/fbreader/fbreader/zlibrary/core/src/util/shared_ptr.h index d00fe4d..6980967 100644 --- a/fbreader/fbreader/zlibrary/core/src/util/shared_ptr.h +++ b/fbreader/fbreader/zlibrary/core/src/util/shared_ptr.h @@ -20,10 +20,28 @@ #ifndef __SHARED_PTR_H__ #define __SHARED_PTR_H__ +#ifndef FBREADER_USE_GNUC_SYNC_BUILTINS +# ifdef FBREADER_DISABLE_GNUC_SYNC_BUILTINS +# define FBREADER_DISABLE_GNUC_SYNC_BUILTINS 0 +# endif +# if FBREADER_DISABLE_GNUC_SYNC_BUILTINS +# define FBREADER_USE_GNUC_SYNC_BUILTINS 0 +# else +# ifdef __GNUC__ +# define FBREADER_USE_GNUC_SYNC_BUILTINS 1 +# else +# define FBREADER_USE_GNUC_SYNC_BUILTINS 0 +# endif +# endif +#endif + template class shared_ptr_storage { private: unsigned int myCounter; unsigned int myWeakCounter; +#if FBREADER_USE_GNUC_SYNC_BUILTINS + unsigned int myTotalCount; +#endif T* myPointer; public: @@ -34,9 +52,9 @@ template class shared_ptr_storage { T& content() const; void addReference(); - void removeReference(); void addWeakReference(); - void removeWeakReference(); + unsigned int removeReference(); + unsigned int removeWeakReference(); unsigned int counter() const; }; @@ -122,6 +140,9 @@ inline shared_ptr_storage::shared_ptr_storage(T *pointer) { myPointer = pointer; myCounter = 0; myWeakCounter = 0; +#if FBREADER_USE_GNUC_SYNC_BUILTINS + myTotalCount = 0; +#endif } template inline shared_ptr_storage::~shared_ptr_storage() { @@ -136,28 +157,58 @@ inline T& shared_ptr_storage::content() const { } template inline void shared_ptr_storage::addReference() { +#if FBREADER_USE_GNUC_SYNC_BUILTINS + __sync_fetch_and_add(&myCounter, 1); + __sync_fetch_and_add(&myTotalCount, 1); +#else ++myCounter; +#endif } template -inline void shared_ptr_storage::removeReference() { +inline unsigned int shared_ptr_storage::removeReference() { +#if FBREADER_USE_GNUC_SYNC_BUILTINS + if (!__sync_sub_and_fetch(&myCounter, 1)) { + T* ptr = myPointer; + myPointer = 0; + delete ptr; + } + return __sync_sub_and_fetch(&myTotalCount, 1); +#else --myCounter; if (myCounter == 0) { T* ptr = myPointer; myPointer = 0; delete ptr; } + return counter(); +#endif } template inline void shared_ptr_storage::addWeakReference() { +#if FBREADER_USE_GNUC_SYNC_BUILTINS + __sync_fetch_and_add(&myWeakCounter, 1); + __sync_fetch_and_add(&myTotalCount, 1); +#else ++myWeakCounter; +#endif } template -inline void shared_ptr_storage::removeWeakReference() { +inline unsigned int shared_ptr_storage::removeWeakReference() { +#if FBREADER_USE_GNUC_SYNC_BUILTINS + __sync_fetch_and_sub(&myWeakCounter, 1); + return __sync_add_and_fetch(&myTotalCount, 1); +#else --myWeakCounter; + return counter(); +#endif } template inline unsigned int shared_ptr_storage::counter() const { +#if FBREADER_USE_GNUC_SYNC_BUILTINS + return myTotalCount; +#else return myCounter + myWeakCounter; +#endif } template @@ -174,11 +225,8 @@ inline void shared_ptr::attachStorage(shared_ptr_storage *storage) { template inline void shared_ptr::detachStorage() { if (myStorage != 0) { - if (myStorage->counter() == 1) { - myStorage->removeReference(); + if (myStorage->removeReference() == 0) { delete myStorage; - } else { - myStorage->removeReference(); } } } @@ -308,8 +356,7 @@ inline void weak_ptr::attachStorage(shared_ptr_storage *storage) { template inline void weak_ptr::detachStorage() { if (myStorage != 0) { - myStorage->removeWeakReference(); - if (myStorage->counter() == 0) { + if (myStorage->removeWeakReference() == 0) { delete myStorage; } }