From: Gunnar Beutner Date: Tue, 19 Jan 2016 14:25:44 +0000 (+0100) Subject: Decrease memory usage for the Object class X-Git-Tag: v2.5.0~613 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=b1aa6cc98aae4aaf52f625e6511b69f9a52223e0;p=icinga2 Decrease memory usage for the Object class refs #10963 --- diff --git a/lib/base/object.cpp b/lib/base/object.cpp index 1a6d1c9ab..2d2779a38 100644 --- a/lib/base/object.cpp +++ b/lib/base/object.cpp @@ -40,7 +40,7 @@ static Timer::Ptr l_ObjectCountTimer; * Default constructor for the Object class. */ Object::Object(void) - : m_References(0) + : m_References(0), m_Mutex(0) #ifdef I2_DEBUG , m_LockOwner(0) #endif /* I2_DEBUG */ @@ -50,7 +50,9 @@ Object::Object(void) * Destructor for the Object class. */ Object::~Object(void) -{ } +{ + delete reinterpret_cast(m_Mutex); +} /** * Returns a string representation for the object. diff --git a/lib/base/object.hpp b/lib/base/object.hpp index a01ed9b36..6eae786b9 100644 --- a/lib/base/object.hpp +++ b/lib/base/object.hpp @@ -117,8 +117,8 @@ private: Object(const Object& other); Object& operator=(const Object& rhs); - uintptr_t m_References; - mutable boost::recursive_mutex m_Mutex; + intptr_t m_References; + mutable uintptr_t m_Mutex; #ifdef I2_DEBUG # ifndef _WIN32 @@ -153,13 +153,15 @@ inline void intrusive_ptr_add_ref(Object *object) inline void intrusive_ptr_release(Object *object) { - uintptr_t refs; + intptr_t refs; #ifdef _WIN32 refs = InterlockedDecrement(&object->m_References); #else /* _WIN32 */ refs = __sync_sub_and_fetch(&object->m_References, 1); #endif /* _WIN32 */ + ASSERT(refs >= 0); + if (refs == 0) { #ifdef I2_DEBUG TypeRemoveObject(object); diff --git a/lib/base/objectlock.hpp b/lib/base/objectlock.hpp index 87d108fea..2ef73ecf6 100644 --- a/lib/base/objectlock.hpp +++ b/lib/base/objectlock.hpp @@ -22,6 +22,9 @@ #include "base/object.hpp" +#define I2MUTEX_UNLOCKED 0 +#define I2MUTEX_LOCKED 1 + namespace icinga { @@ -53,11 +56,49 @@ public: Lock(); } + inline static void LockMutex(const Object *object) + { + unsigned int it = 0; + +#ifdef _WIN32 +# ifdef _WIN64 + while (InterlockedCompareExchange64(&object->m_Mutex, I2MUTEX_LOCKED, I2MUTEX_UNLOCKED) != I2MUTEX_UNLOCKED) { +# else /* _WIN64 */ + while (InterlockedCompareExchange(&object->m_Mutex, I2MUTEX_LOCKED, I2MUTEX_UNLOCKED) != I2MUTEX_UNLOCKED) { +# endif /* _WIN64 */ +#else /* _WIN32 */ + while (!__sync_bool_compare_and_swap(&object->m_Mutex, I2MUTEX_UNLOCKED, I2MUTEX_LOCKED)) { +#endif /* _WIN32 */ + if (object->m_Mutex > I2MUTEX_LOCKED) { + boost::recursive_mutex *mtx = reinterpret_cast(object->m_Mutex); + mtx->lock(); + + return; + } + + Spin(it); + it++; + } + + boost::recursive_mutex *mtx = new boost::recursive_mutex(); + mtx->lock(); +#ifdef _WIN32 +# ifdef _WIN64 + InterlockedCompareExchange64(&object->m_Mutex, reinterpret_cast(mtx), I2MUTEX_LOCKED); +# else /* _WIN64 */ + InterlockedCompareExchange(&object->m_Mutex, reinterpret_cast(mtx), I2MUTEX_LOCKED); +# endif /* _WIN64 */ +#else /* _WIN32 */ + __sync_bool_compare_and_swap(&object->m_Mutex, I2MUTEX_LOCKED, reinterpret_cast(mtx)); +#endif /* _WIN32 */ + } + inline void Lock(void) { ASSERT(!m_Locked && m_Object != NULL); - m_Object->m_Mutex.lock(); + LockMutex(m_Object); + m_Locked = true; #ifdef I2_DEBUG @@ -69,6 +110,25 @@ public: #endif /* I2_DEBUG */ } + inline static void Spin(unsigned int it) + { + if (it < 8) { + /* Do nothing. */ + } +#ifdef SPIN_PAUSE + else if (it < 16) { + SPIN_PAUSE(); + } +#endif /* SPIN_PAUSE */ + else { +#ifdef _WIN32 + Sleep(0); +#else /* _WIN32 */ + sched_yield(); +#endif /* _WIN32 */ + } + } + inline void Unlock(void) { #ifdef I2_DEBUG @@ -82,7 +142,7 @@ public: #endif /* I2_DEBUG */ if (m_Locked) { - m_Object->m_Mutex.unlock(); + reinterpret_cast(m_Object->m_Mutex)->unlock(); m_Locked = false; } }