diff options
Diffstat (limited to 'cpp')
-rw-r--r-- | cpp/include/Ice/MetricsObserverI.h | 16 | ||||
-rw-r--r-- | cpp/include/Ice/SlicedData.h | 5 | ||||
-rw-r--r-- | cpp/include/IceUtil/Atomic.h | 178 | ||||
-rw-r--r-- | cpp/include/IceUtil/Shared.h | 38 | ||||
-rw-r--r-- | cpp/src/IceUtil/Shared.cpp | 61 |
5 files changed, 193 insertions, 105 deletions
diff --git a/cpp/include/Ice/MetricsObserverI.h b/cpp/include/Ice/MetricsObserverI.h index 66e20afc2f4..8ae7afd5e93 100644 --- a/cpp/include/Ice/MetricsObserverI.h +++ b/cpp/include/Ice/MetricsObserverI.h @@ -11,6 +11,7 @@ #define ICEMX_METRICSOBSERVER_I_H #include <IceUtil/StopWatch.h> +#include <IceUtil/Atomic.h> #include <Ice/Instrumentation.h> #include <Ice/Endpoint.h> @@ -430,7 +431,7 @@ public: typedef std::vector<IceUtil::Handle<IceInternal::MetricsMapT<MetricsType> > > MetricsMapSeqType; ObserverFactoryT(const IceInternal::MetricsAdminIPtr& metrics, const std::string& name) : - _metrics(metrics), _name(name), _enabled(false) + _metrics(metrics), _name(name), _enabled(0) { _metrics->registerMap<MetricsType>(name, this); } @@ -517,12 +518,13 @@ public: bool isEnabled() const { - return _enabled; + return _enabled != 0; } virtual void update() { UpdaterPtr updater; + bool enabled = false; { IceUtil::Mutex::Lock sync(*this); if(!_metrics) @@ -537,10 +539,10 @@ public: _maps.push_back(IceUtil::Handle<IceInternal::MetricsMapT<MetricsType> >::dynamicCast(*p)); assert(_maps.back()); } - _enabled = !_maps.empty(); + enabled = !_maps.empty(); updater = _updater; } - + _enabled.exchange(enabled ? 1 : 0); if(updater) { updater->update(); @@ -565,7 +567,11 @@ private: IceInternal::MetricsAdminIPtr _metrics; const std::string _name; MetricsMapSeqType _maps; - volatile bool _enabled; + // + // TODO: Replace by std::atomic<bool> when it becomes widely + // available. + // + IceUtilInternal::Atomic _enabled; UpdaterPtr _updater; }; diff --git a/cpp/include/Ice/SlicedData.h b/cpp/include/Ice/SlicedData.h index 10e88900cdb..96ec59fd24c 100644 --- a/cpp/include/Ice/SlicedData.h +++ b/cpp/include/Ice/SlicedData.h @@ -64,11 +64,6 @@ public: const SliceInfoSeq slices; void __gcVisitMembers(IceInternal::GCVisitor&); - - void __decRefUnsafe() - { - --_ref; - } }; // diff --git a/cpp/include/IceUtil/Atomic.h b/cpp/include/IceUtil/Atomic.h new file mode 100644 index 00000000000..23d2577b404 --- /dev/null +++ b/cpp/include/IceUtil/Atomic.h @@ -0,0 +1,178 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2015 ZeroC, Inc. All rights reserved. +// +// This copy of Ice is licensed to you under the terms described in the +// ICE_LICENSE file included in this distribution. +// +// ********************************************************************** + +#ifndef ICE_UTIL_ATOMIC_H +#define ICE_UTIL_ATOMIC_H + +#if ((defined(ICE_CPP11) && defined(_MSC_VER) && (_MSC_VER > 1600)) || \ + (defined(ICE_CPP11) && !defined(_MSC_VER))) +# define ICE_CPP11_HAS_ATOMIC +#endif + +#if defined(ICE_CPP11_HAS_ATOMIC) +# include <atomic> +#elif defined(ICE_USE_MUTEX_SHARED) + +# include <IceUtil/Mutex.h> + +// Using the gcc builtins requires gcc 4.1 or better. For Linux, i386 +// doesn't work. Apple is supported for all architectures. Sun only +// supports sparc (32 and 64 bit). + +#elif ((defined(__GNUC__) && (((__GNUC__* 100) + __GNUC_MINOR__) >= 401)) || __clang__) && \ + ((defined(__sun) && (defined(__sparc) || defined(__sparcv9))) || \ + defined(__APPLE__) || \ + (defined(__linux) && \ + (defined(__i486) || defined(__i586) || \ + defined(__i686) || defined(__x86_64)))) + +# define ICE_HAS_GCC_BUILTINS + +#elif defined(_WIN32) +// Nothing to include +#else +// Use a simple mutex +# include <IceUtil/Mutex.h> +#endif + + +namespace IceUtilInternal +{ + +#ifdef ICE_CPP11_HAS_ATOMIC +typedef std::atomic<int> Atomic; +#else + +#if defined(_WIN32) +// +// volatile here is required by InterlockedExchangeXXX +// family functions. +// +typedef volatile unsigned int ATOMIC_T; +#else +typedef int ATOMIC_T; +#endif + + +// +// This is temporary and very partial placeholder for std::atomic, +// which is not yet widely available. +// +class Atomic : public IceUtil::noncopyable +{ +public: + + Atomic() : + _ref(0) + { + } + + Atomic(int desired) : + _ref(desired) + { + } + + inline int fetch_add(int value) + { +#if defined(_WIN32) + return InterlockedExchangeAdd(&_ref, value); +#elif defined(ICE_HAS_GCC_BUILTINS) + return __sync_fetch_and_add(&_ref, value); +#else + IceUtil::Mutex::Lock sync(_mutex); + int tmp = _ref; + _ref += value; + return tmp; +#endif + } + + inline int fetch_sub(int value) + { +#if defined(_WIN32) + return InterlockedExchangeSubtract(&_ref, value); +#elif defined(ICE_HAS_GCC_BUILTINS) + return __sync_fetch_and_sub(&_ref, value); +#else + IceUtil::Mutex::Lock sync(_mutex); + ATOMIC_T tmp = _ref; + _ref -= value; + return tmp; +#endif + } + + inline int load() const + { +#if defined(_WIN32) + return InterlockedExchangeAdd(const_cast<ATOMIC_T*>(&_ref), 0); +#elif defined(ICE_HAS_GCC_BUILTINS) + return __sync_fetch_and_add(const_cast<ATOMIC_T*>(&_ref), 0); +#else + IceUtil::Mutex::Lock sync(_mutex); + return _ref; +#endif + } + + inline int exchange(int value) + { +#if defined(_WIN32) + return InterlockedExchange(&_ref, value); +#elif defined(ICE_HAS_GCC_BUILTINS) + __sync_synchronize(); + return __sync_lock_test_and_set(&_ref, value); +#else + IceUtil::Mutex::Lock sync(_mutex); + int tmp = _ref; + _ref = value; + return _ref; +#endif + } + + inline int operator++() + { + return fetch_add(1) + 1; + } + + inline int operator--() + { + return fetch_sub(1) - 1; + } + + inline int operator++(int) + { + return fetch_add(1); + } + + inline int operator--(int) + { + return fetch_sub(1); + } + + inline operator int() + { + return load(); + } + + inline operator int() const + { + return load(); + } + +private: + + ATOMIC_T _ref; +#if !defined(_WIN32) && !defined(ICE_HAS_GCC_BUILTINS) + Mutex _mutex; +#endif +}; + +#endif + +} + +#endif diff --git a/cpp/include/IceUtil/Shared.h b/cpp/include/IceUtil/Shared.h index fdcbd5b29ad..1a7fe8d884e 100644 --- a/cpp/include/IceUtil/Shared.h +++ b/cpp/include/IceUtil/Shared.h @@ -11,32 +11,7 @@ #define ICE_UTIL_SHARED_H #include <IceUtil/Config.h> - -#if defined(ICE_CPP11) -# include <atomic> -#elif defined(ICE_USE_MUTEX_SHARED) - -# include <IceUtil/Mutex.h> - -// Using the gcc builtins requires gcc 4.1 or better. For Linux, i386 -// doesn't work. Apple is supported for all architectures. Sun only -// supports sparc (32 and 64 bit). - -#elif ((defined(__GNUC__) && (((__GNUC__* 100) + __GNUC_MINOR__) >= 401)) || __clang__) && \ - ((defined(__sun) && (defined(__sparc) || defined(__sparcv9))) || \ - defined(__APPLE__) || \ - (defined(__linux) && \ - (defined(__i486) || defined(__i586) || \ - defined(__i686) || defined(__x86_64)))) - -# define ICE_HAS_GCC_BUILTINS - -#elif defined(_WIN32) -// Nothing to include -#else -// Use a simple mutex -# include <IceUtil/Mutex.h> -#endif +#include <IceUtil/Atomic.h> // // Base classes for reference counted types. The IceUtil::Handle @@ -150,16 +125,7 @@ public: protected: -#if defined(ICE_CPP11) - std::atomic<int> _ref; -#elif defined(_WIN32) - LONG _ref; -#elif defined(ICE_HAS_GCC_BUILTINS) - int _ref; -#else - int _ref; - Mutex _mutex; -#endif + IceUtilInternal::Atomic _ref; unsigned char _flags; }; diff --git a/cpp/src/IceUtil/Shared.cpp b/cpp/src/IceUtil/Shared.cpp index f242ee8d986..f88068569e0 100644 --- a/cpp/src/IceUtil/Shared.cpp +++ b/cpp/src/IceUtil/Shared.cpp @@ -44,81 +44,24 @@ IceUtil::Shared::Shared(const Shared&) : void IceUtil::Shared::__incRef() { -#if defined(ICE_CPP11) - assert(_ref.fetch_add(0, std::memory_order_relaxed) >= 0); - ++_ref; -#elif defined(_WIN32) - assert(InterlockedExchangeAdd(&_ref, 0) >= 0); - InterlockedIncrement(&_ref); -#elif defined(ICE_HAS_GCC_BUILTINS) - -# ifndef NDEBUG - int c = -# endif - __sync_fetch_and_add(&_ref, 1); - assert(c >= 0); -#else - _mutex.lock(); assert(_ref >= 0); ++_ref; - _mutex.unlock(); -#endif } void IceUtil::Shared::__decRef() { -#if defined(ICE_CPP11) - assert(_ref.fetch_add(0, std::memory_order_relaxed) > 0); - if(--_ref == 0 && !(_flags & NoDelete)) - { - delete this; - } -#elif defined(_WIN32) - assert(InterlockedExchangeAdd(&_ref, 0) > 0); - if(InterlockedDecrement(&_ref) == 0 && !(_flags & NoDelete)) - { - delete this; - } -#elif defined(ICE_HAS_GCC_BUILTINS) - int c = __sync_fetch_and_sub(&_ref, 1); - assert(c > 0); - if(c == 1 && !(_flags & NoDelete)) - { - delete this; - } -#else - bool doDelete = false; - _mutex.lock(); assert(_ref > 0); - if(--_ref == 0) - { - doDelete = !(_flags & NoDelete); - _flags |= NoDelete; - } - _mutex.unlock(); - if(doDelete) + if(--_ref == 0 && !(_flags & NoDelete)) { delete this; } -#endif } int IceUtil::Shared::__getRef() const { -#if defined(ICE_CPP11) - return _ref.load(std::memory_order_relaxed); -#elif defined(_WIN32) - return InterlockedExchangeAdd(const_cast<LONG*>(&_ref), 0); -#elif defined(ICE_HAS_GCC_BUILTINS) - return __sync_fetch_and_sub(const_cast<volatile int*>(&_ref), 0); -#else - _mutex.lock(); - int ref = _ref; - _mutex.unlock(); - return ref; -#endif + return _ref; } void |