autolock-request
author Benjamin Smedberg <benjamin@smedbergs.us>
Sat, 26 Jul 2008 22:49:39 -0400
changeset 167 a4da40849f5436e629c5732f4368c6c48189637f
parent 75 aa1b133fd1616ee46ee56e3d4cbeea19da6c6650
permissions -rw-r--r--
State as of now

* * *
* * *

diff --git a/xpcom/glue/nsAutoLock.cpp b/xpcom/glue/nsAutoLock.cpp
--- a/xpcom/glue/nsAutoLock.cpp
+++ b/xpcom/glue/nsAutoLock.cpp
@@ -435,7 +435,7 @@ void nsAutoMonitor::Enter()
     mDown = stackTop;
     (void) PR_SetThreadPrivate(LockStackTPI, this);
 #endif
-    PR_EnterMonitor(mMonitor);
+    RequestSafeEnterMonitor(mMonitor);
     mLockCount += 1;
 }
 
@@ -466,7 +466,7 @@ void nsAutoCMonitor::Enter()
     mDown = stackTop;
     (void) PR_SetThreadPrivate(LockStackTPI, this);
 #endif
-    PR_CEnterMonitor(mLockObject);
+    RequestSafeEnterCMonitor(mLockObject);
     mLockCount += 1;
 }
 
diff --git a/xpcom/glue/nsAutoLock.h b/xpcom/glue/nsAutoLock.h
--- a/xpcom/glue/nsAutoLock.h
+++ b/xpcom/glue/nsAutoLock.h
@@ -107,8 +107,42 @@
 #define nsAutoLock_h__
 
 #include "nscore.h"
+#include "nsError.h"
+#include "nsDebug.h"
+#include "nsXPCOMRequests.h"
+
 #include "prlock.h"
 #include "prlog.h"
+#include "prcvar.h"
+#include "prcmon.h"
+
+inline void RequestSafeLock(PRLock *lock)
+{
+#if HAVE_TRYLOCK
+    if (PR_TryLock(lock) == PR_SUCCESS)
+        return;
+#endif
+
+    nsAutoSuspendRequest suspended;
+    PR_Lock(lock);
+}
+
+inline void RequestSafeEnterMonitor(PRMonitor *monitor)
+{
+#if HAVE_TRYMONITOR
+    if (PR_TryEnterMonitor(monitor) == PR_SUCCESS)
+        return;
+#endif
+
+    nsAutoSuspendRequest suspended;
+    PR_EnterMonitor(monitor);
+}
+
+inline void RequestSafeEnterCMonitor(void *object)
+{
+    nsAutoSuspendRequest suspended;
+    PR_CEnterMonitor(object);
+}
 
 /**
  * nsAutoLockBase
@@ -172,18 +206,14 @@ private:
 
     // Not meant to be implemented. This makes it a compiler error to
     // construct or assign an nsAutoLock object incorrectly.
-    nsAutoLock(void) {}
-    nsAutoLock(nsAutoLock& /*aLock*/) {}
-    nsAutoLock& operator =(nsAutoLock& /*aLock*/) {
-        return *this;
-    }
+    nsAutoLock(void);
+    nsAutoLock(nsAutoLock& /*aLock*/);
+    nsAutoLock& operator =(nsAutoLock& /*aLock*/);
 
     // Not meant to be implemented. This makes it a compiler error to
     // attempt to create an nsAutoLock object on the heap.
-    static void* operator new(size_t /*size*/) CPP_THROW_NEW {
-        return nsnull;
-    }
-    static void operator delete(void* /*memory*/) {}
+    static void* operator new(size_t /*size*/) CPP_THROW_NEW;
+    static void operator delete(void* /*memory*/);
 
 public:
 
@@ -232,7 +262,7 @@ public:
     void lock() {
         Show();
         PR_ASSERT(!mLocked);
-        PR_Lock(mLock);
+        RequestSafeLock(mLock);
         mLocked = PR_TRUE;
     }
 
@@ -248,6 +278,13 @@ public:
         mLocked = PR_FALSE;
         Hide();
     }
+
+     void waitCondVar(PRCondVar *cvar, PRIntervalTime interval)
+     {
+         PR_ASSERT(mLocked);
+         nsAutoSuspendRequest suspended;
+         PR_WaitCondVar(cvar, interval);
+     }
 };
 
 class nsAutoUnlock : nsAutoUnlockBase
@@ -264,13 +301,9 @@ public:
     }
 
     ~nsAutoUnlock() {
-        PR_Lock(mLock);
+        RequestSafeLock(mLock);
     }
 };
-
-#include "prcmon.h"
-#include "nsError.h"
-#include "nsDebug.h"
 
 class NS_COM_GLUE nsAutoMonitor : public nsAutoLockBase {
 public:
@@ -300,15 +333,15 @@ public:
           mMonitor(mon), mLockCount(0)
     {
         NS_ASSERTION(mMonitor, "null monitor");
-        if (mMonitor) {
-            PR_EnterMonitor(mMonitor);
-            mLockCount = 1;
-        }
+
+        RequestSafeEnterMonitor(mMonitor);
+        mLockCount = 1;
     }
 
     ~nsAutoMonitor() {
         NS_ASSERTION(mMonitor, "null monitor");
-        if (mMonitor && mLockCount) {
+
+        if (mLockCount) {
 #ifdef DEBUG
             PRStatus status = 
 #endif
@@ -336,6 +369,8 @@ public:
      * @see prmon.h 
      **/      
     nsresult Wait(PRIntervalTime interval = PR_INTERVAL_NO_TIMEOUT) {
+        nsAutoSuspendRequest suspended;
+
         return PR_Wait(mMonitor, interval) == PR_SUCCESS
             ? NS_OK : NS_ERROR_FAILURE;
     }
@@ -364,27 +399,20 @@ private:
 
     // Not meant to be implemented. This makes it a compiler error to
     // construct or assign an nsAutoLock object incorrectly.
-    nsAutoMonitor(void) {}
-    nsAutoMonitor(nsAutoMonitor& /*aMon*/) {}
-    nsAutoMonitor& operator =(nsAutoMonitor& /*aMon*/) {
-        return *this;
-    }
+    nsAutoMonitor(void);
+    nsAutoMonitor(nsAutoMonitor& /*aMon*/);
+    nsAutoMonitor& operator =(nsAutoMonitor& /*aMon*/);
 
     // Not meant to be implemented. This makes it a compiler error to
     // attempt to create an nsAutoLock object on the heap.
-    static void* operator new(size_t /*size*/) CPP_THROW_NEW {
-        return nsnull;
-    }
-    static void operator delete(void* /*memory*/) {}
+    static void* operator new(size_t /*size*/) CPP_THROW_NEW;
+    static void operator delete(void* /*memory*/);
 };
 
 ////////////////////////////////////////////////////////////////////////////////
 // Once again, this time with a cache...
 // (Using this avoids the need to allocate a PRMonitor, which may be useful when
 // a large number of objects of the same class need associated monitors.)
-
-#include "prcmon.h"
-#include "nsError.h"
 
 class NS_COM_GLUE nsAutoCMonitor : public nsAutoLockBase {
 public:
@@ -393,6 +421,7 @@ public:
           mLockObject(lockObject), mLockCount(0)
     {
         NS_ASSERTION(lockObject, "null lock object");
+        RequestSafeEnterCMonitor(mLockObject);
         PR_CEnterMonitor(mLockObject);
         mLockCount = 1;
     }
@@ -402,7 +431,7 @@ public:
 #ifdef DEBUG
             PRStatus status =
 #endif
-            PR_CExitMonitor(mLockObject);
+                PR_CExitMonitor(mLockObject);
             NS_ASSERTION(status == PR_SUCCESS, "PR_CExitMonitor failed");
         }
     }
@@ -411,6 +440,8 @@ public:
     void Exit();
 
     nsresult Wait(PRIntervalTime interval = PR_INTERVAL_NO_TIMEOUT) {
+        nsAutoSuspendRequest suspended;
+
         return PR_CWait(mLockObject, interval) == PR_SUCCESS
             ? NS_OK : NS_ERROR_FAILURE;
     }
@@ -431,18 +462,14 @@ private:
 
     // Not meant to be implemented. This makes it a compiler error to
     // construct or assign an nsAutoLock object incorrectly.
-    nsAutoCMonitor(void) {}
-    nsAutoCMonitor(nsAutoCMonitor& /*aMon*/) {}
-    nsAutoCMonitor& operator =(nsAutoCMonitor& /*aMon*/) {
-        return *this;
-    }
+    nsAutoCMonitor(void);
+    nsAutoCMonitor(nsAutoCMonitor& /*aMon*/);
+    nsAutoCMonitor& operator =(nsAutoCMonitor& /*aMon*/);
 
     // Not meant to be implemented. This makes it a compiler error to
     // attempt to create an nsAutoLock object on the heap.
-    static void* operator new(size_t /*size*/) CPP_THROW_NEW {
-        return nsnull;
-    }
-    static void operator delete(void* /*memory*/) {}
+    static void* operator new(size_t /*size*/) CPP_THROW_NEW;
+    static void operator delete(void* /*memory*/);
 };
 
 #endif // nsAutoLock_h__
diff --git a/xpcom/threads/TimerThread.cpp b/xpcom/threads/TimerThread.cpp
--- a/xpcom/threads/TimerThread.cpp
+++ b/xpcom/threads/TimerThread.cpp
@@ -314,7 +314,7 @@ NS_IMETHODIMP TimerThread::Run()
     }
 
     mWaiting = PR_TRUE;
-    PR_WaitCondVar(mCondVar, waitFor);
+    lock.waitCondVar(mCondVar, waitFor);
     mWaiting = PR_FALSE;
   }