summaryrefslogtreecommitdiff
path: root/indra/llcommon
diff options
context:
space:
mode:
authorGraham Madarasz (Graham) <graham@lindenlab.com>2013-02-28 16:37:09 -0800
committerGraham Madarasz (Graham) <graham@lindenlab.com>2013-02-28 16:37:09 -0800
commitae1aa461ea3f96c092e2a50ae40f290b03b25356 (patch)
tree5ed6d3fcde98bd50a2486c321cde0db6dd1daf52 /indra/llcommon
parent93eaccae6fe6e8442a3c6e5a2d40a408aa44df77 (diff)
Attempt at a faster ThreadSafeRefCount class
Diffstat (limited to 'indra/llcommon')
-rw-r--r--indra/llcommon/llapr.h8
-rw-r--r--indra/llcommon/llthread.cpp8
-rw-r--r--indra/llcommon/llthread.h40
3 files changed, 25 insertions, 31 deletions
diff --git a/indra/llcommon/llapr.h b/indra/llcommon/llapr.h
index 034546c3f3..8042fe2502 100644
--- a/indra/llcommon/llapr.h
+++ b/indra/llcommon/llapr.h
@@ -164,14 +164,20 @@ public:
~LLAtomic32<Type>() {};
operator const Type() { apr_uint32_t data = apr_atomic_read32(&mData); return Type(data); }
+
+ Type CurrentValue() const { apr_uint32_t data = apr_atomic_read32(const_cast< volatile apr_uint32_t* >(&mData)); return Type(data); }
+
Type operator =(const Type& x) { apr_atomic_set32(&mData, apr_uint32_t(x)); return Type(mData); }
void operator -=(Type x) { apr_atomic_sub32(&mData, apr_uint32_t(x)); }
void operator +=(Type x) { apr_atomic_add32(&mData, apr_uint32_t(x)); }
Type operator ++(int) { return apr_atomic_inc32(&mData); } // Type++
Type operator --(int) { return apr_atomic_dec32(&mData); } // approximately --Type (0 if final is 0, non-zero otherwise)
+
+ Type operator ++() { return apr_atomic_inc32(&mData); } // Type++
+ Type operator --() { return apr_atomic_dec32(&mData); } // approximately --Type (0 if final is 0, non-zero otherwise)
private:
- apr_uint32_t mData;
+ volatile apr_uint32_t mData;
};
typedef LLAtomic32<U32> LLAtomicU32;
diff --git a/indra/llcommon/llthread.cpp b/indra/llcommon/llthread.cpp
index 1d56a52c32..6c117f7daf 100644
--- a/indra/llcommon/llthread.cpp
+++ b/indra/llcommon/llthread.cpp
@@ -495,15 +495,7 @@ LLThreadSafeRefCount::LLThreadSafeRefCount() :
LLThreadSafeRefCount::LLThreadSafeRefCount(const LLThreadSafeRefCount& src)
{
- if (sMutex)
- {
- sMutex->lock();
- }
mRef = 0;
- if (sMutex)
- {
- sMutex->unlock();
- }
}
LLThreadSafeRefCount::~LLThreadSafeRefCount()
diff --git a/indra/llcommon/llthread.h b/indra/llcommon/llthread.h
index 5c8bbca2ca..c2f4184a8a 100644
--- a/indra/llcommon/llthread.h
+++ b/indra/llcommon/llthread.h
@@ -241,47 +241,43 @@ public:
LLThreadSafeRefCount(const LLThreadSafeRefCount&);
LLThreadSafeRefCount& operator=(const LLThreadSafeRefCount& ref)
{
- if (sMutex)
- {
- sMutex->lock();
- }
mRef = 0;
- if (sMutex)
- {
- sMutex->unlock();
- }
return *this;
}
-
-
void ref()
{
- if (sMutex) sMutex->lock();
mRef++;
- if (sMutex) sMutex->unlock();
}
S32 unref()
{
- llassert(mRef >= 1);
- if (sMutex) sMutex->lock();
- S32 res = --mRef;
- if (sMutex) sMutex->unlock();
- if (0 == res)
+ llassert(mRef >= 1);
+ bool time_to_die = (mRef == 1);
+ if (time_to_die)
{
- delete this;
+ if (sMutex) sMutex->lock();
+ // Looks redundant, but is very much not
+ // We need to check again once we've acquired the lock
+ // so that two threads who get into the if in parallel
+ // don't both attempt to the delete.
+ //
+ if (mRef == 1)
+ delete this;
+ mRef--;
+ if (sMutex) sMutex->unlock();
return 0;
}
- return res;
- }
+ return --mRef;
+ }
S32 getNumRefs() const
{
- return mRef;
+ const S32 currentVal = mRef.CurrentValue();
+ return currentVal;
}
private:
- S32 mRef;
+ LLAtomic32< S32 > mRef;
};
//============================================================================