summaryrefslogtreecommitdiff
path: root/indra/llcommon/llmutex.cpp
diff options
context:
space:
mode:
authorRichard Linden <none@none>2014-02-24 18:45:59 -0800
committerRichard Linden <none@none>2014-02-24 18:45:59 -0800
commit80b4a4a1f54dccb814b5486423bf6492b3ae58a7 (patch)
treef17c7a9b433e443b2f30251dd15b1bf50d4f803c /indra/llcommon/llmutex.cpp
parentde8fea13627cc5978b8a6135802a52864a11c39a (diff)
parentef591d280eb3c5bae7da20540ad4cbb30858d0aa (diff)
merge with release
Diffstat (limited to 'indra/llcommon/llmutex.cpp')
-rw-r--r--indra/llcommon/llmutex.cpp205
1 files changed, 205 insertions, 0 deletions
diff --git a/indra/llcommon/llmutex.cpp b/indra/llcommon/llmutex.cpp
new file mode 100644
index 0000000000..9c13ef9e30
--- /dev/null
+++ b/indra/llcommon/llmutex.cpp
@@ -0,0 +1,205 @@
+/**
+ * @file llmutex.cpp
+ *
+ * $LicenseInfo:firstyear=2004&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "linden_common.h"
+#include "llapr.h"
+
+#include "apr_portable.h"
+
+#include "llmutex.h"
+#include "llthread.h"
+
+//============================================================================
+
+LLMutex::LLMutex(apr_pool_t *poolp) :
+ mAPRMutexp(NULL), mCount(0), mLockingThread(NO_THREAD)
+{
+ //if (poolp)
+ //{
+ // mIsLocalPool = FALSE;
+ // mAPRPoolp = poolp;
+ //}
+ //else
+ {
+ mIsLocalPool = TRUE;
+ apr_pool_create(&mAPRPoolp, NULL); // Create a subpool for this thread
+ }
+ apr_thread_mutex_create(&mAPRMutexp, APR_THREAD_MUTEX_UNNESTED, mAPRPoolp);
+}
+
+
+LLMutex::~LLMutex()
+{
+#if MUTEX_DEBUG
+ //bad assertion, the subclass LLSignal might be "locked", and that's OK
+ //llassert_always(!isLocked()); // better not be locked!
+#endif
+ if (ll_apr_is_initialized())
+ {
+ apr_thread_mutex_destroy(mAPRMutexp);
+ if (mIsLocalPool)
+ {
+ apr_pool_destroy(mAPRPoolp);
+ }
+ }
+ mAPRMutexp = NULL;
+}
+
+
+void LLMutex::lock()
+{
+ if(isSelfLocked())
+ { //redundant lock
+ mCount++;
+ return;
+ }
+
+ apr_thread_mutex_lock(mAPRMutexp);
+
+#if MUTEX_DEBUG
+ // Have to have the lock before we can access the debug info
+ U32 id = LLThread::currentID();
+ if (mIsLocked[id] != FALSE)
+ LL_ERRS() << "Already locked in Thread: " << id << LL_ENDL;
+ mIsLocked[id] = TRUE;
+#endif
+
+ mLockingThread = LLThread::currentID();
+}
+
+void LLMutex::unlock()
+{
+ if (mCount > 0)
+ { //not the root unlock
+ mCount--;
+ return;
+ }
+
+#if MUTEX_DEBUG
+ // Access the debug info while we have the lock
+ U32 id = LLThread::currentID();
+ if (mIsLocked[id] != TRUE)
+ LL_ERRS() << "Not locked in Thread: " << id << LL_ENDL;
+ mIsLocked[id] = FALSE;
+#endif
+
+ mLockingThread = NO_THREAD;
+ apr_thread_mutex_unlock(mAPRMutexp);
+}
+
+bool LLMutex::isLocked()
+{
+ apr_status_t status = apr_thread_mutex_trylock(mAPRMutexp);
+ if (APR_STATUS_IS_EBUSY(status))
+ {
+ return true;
+ }
+ else
+ {
+ apr_thread_mutex_unlock(mAPRMutexp);
+ return false;
+ }
+}
+
+bool LLMutex::isSelfLocked()
+{
+ return mLockingThread == LLThread::currentID();
+}
+
+U32 LLMutex::lockingThread() const
+{
+ return mLockingThread;
+}
+
+bool LLMutex::trylock()
+{
+ if(isSelfLocked())
+ { //redundant lock
+ mCount++;
+ return true;
+ }
+
+ apr_status_t status(apr_thread_mutex_trylock(mAPRMutexp));
+ if (APR_STATUS_IS_EBUSY(status))
+ {
+ return false;
+ }
+
+#if MUTEX_DEBUG
+ // Have to have the lock before we can access the debug info
+ U32 id = LLThread::currentID();
+ if (mIsLocked[id] != FALSE)
+ LL_ERRS() << "Already locked in Thread: " << id << LL_ENDL;
+ mIsLocked[id] = TRUE;
+#endif
+
+ mLockingThread = LLThread::currentID();
+ return true;
+}
+
+//============================================================================
+
+LLCondition::LLCondition(apr_pool_t *poolp) :
+ LLMutex(poolp)
+{
+ // base class (LLMutex) has already ensured that mAPRPoolp is set up.
+
+ apr_thread_cond_create(&mAPRCondp, mAPRPoolp);
+}
+
+
+LLCondition::~LLCondition()
+{
+ apr_thread_cond_destroy(mAPRCondp);
+ mAPRCondp = NULL;
+}
+
+
+void LLCondition::wait()
+{
+ if (!isLocked())
+ { //mAPRMutexp MUST be locked before calling apr_thread_cond_wait
+ apr_thread_mutex_lock(mAPRMutexp);
+#if MUTEX_DEBUG
+ // avoid asserts on destruction in non-release builds
+ U32 id = LLThread::currentID();
+ mIsLocked[id] = TRUE;
+#endif
+ }
+ apr_thread_cond_wait(mAPRCondp, mAPRMutexp);
+}
+
+void LLCondition::signal()
+{
+ apr_thread_cond_signal(mAPRCondp);
+}
+
+void LLCondition::broadcast()
+{
+ apr_thread_cond_broadcast(mAPRCondp);
+}
+
+
+//============================================================================