Index: trunk/src/VBox/Main/AutoLock.cpp
===================================================================
--- trunk/src/VBox/Main/AutoLock.cpp	(revision 25282)
+++ trunk/src/VBox/Main/AutoLock.cpp	(revision 25283)
@@ -26,4 +26,5 @@
 #include <iprt/string.h>
 
+#include <vector>
 
 namespace util
@@ -94,14 +95,19 @@
 ////////////////////////////////////////////////////////////////////////////////
 
+typedef std::vector<LockHandle*> HandlesVector;
+
 struct AutoLockBase::Data
 {
-    Data(LockHandle *argpHandle)
-        : pHandle(argpHandle),
+    Data(size_t cHandles)
+        : aHandles(cHandles),       // size of array
           fIsLocked(false),
           cUnlockedInLeave(0)
     { }
 
-    LockHandle      *pHandle;
-    bool            fIsLocked;
+    HandlesVector   aHandles;           // array (vector) of LockHandle instances; in the case of AutoWriteLock
+                                        // and AutoReadLock, there will only be one item on the list; with the
+                                        // AutoMulti* derivatives, there will be multiple
+    bool            fIsLocked;          // if true, then all items in aHandles are locked by this AutoLock and
+                                        // need to be unlocked in the destructor
     uint32_t        cUnlockedInLeave;   // how many times the handle was unlocked in leave(); otherwise 0
 };
@@ -109,5 +115,6 @@
 AutoLockBase::AutoLockBase(LockHandle *pHandle)
 {
-    m = new Data(pHandle);
+    m = new Data(1);
+    m->aHandles[0] = pHandle;
 }
 
@@ -119,17 +126,21 @@
 /**
  * Requests ownership of all contained lock handles by calling
- * the pure virtual acquireImpl() function on each of them,
+ * the pure virtual callLockImpl() function on each of them,
  * which must be implemented by the descendant class; in the
  * implementation, AutoWriteLock will request a write lock
  * whereas AutoReadLock will request a read lock.
- */
-void AutoLockBase::acquire()
-{
-    if (m->pHandle)
-    {
-        AssertMsg(!m->fIsLocked, ("m->fIsLocked is true, attempting to lock twice!"));
-        // call virtual function implemented in AutoWriteLock or AutoReadLock
-        this->acquireImpl(*m->pHandle);
-        m->fIsLocked = true;
+ *
+ * Does *not* modify the lock counts in the member variables.
+ */
+void AutoLockBase::callLockOnAllHandles()
+{
+    for (HandlesVector::iterator it = m->aHandles.begin();
+         it != m->aHandles.end();
+         ++it)
+    {
+        LockHandle *pHandle = *it;
+        if (pHandle)
+            // call virtual function implemented in AutoWriteLock or AutoReadLock
+            this->callLockImpl(*pHandle);
     }
 }
@@ -137,18 +148,66 @@
 /**
  * Releases ownership of all contained lock handles by calling
- * the pure virtual releaseImpl() function on each of them,
+ * the pure virtual callUnlockImpl() function on each of them,
  * which must be implemented by the descendant class; in the
  * implementation, AutoWriteLock will release a write lock
  * whereas AutoReadLock will release a read lock.
+ *
+ * Does *not* modify the lock counts in the member variables.
+ */
+void AutoLockBase::callUnlockOnAllHandles()
+{
+    for (HandlesVector::iterator it = m->aHandles.begin();
+         it != m->aHandles.end();
+         ++it)
+    {
+        LockHandle *pHandle = *it;
+        if (pHandle)
+            // call virtual function implemented in AutoWriteLock or AutoReadLock
+            this->callUnlockImpl(*pHandle);
+    }
+}
+
+/**
+ * Destructor implementation that can also be called explicitly, if required.
+ * Restores the exact state before the AutoLock was created; that is, unlocks
+ * all contained semaphores and might actually lock them again if leave()
+ * was called during the AutoLock's lifetime.
+ */
+void AutoLockBase::cleanup()
+{
+    if (m->cUnlockedInLeave)
+    {
+        // there was a leave() before the destruction: then restore the
+        // lock level that might have been set by locks other than our own
+        if (m->fIsLocked)
+            --m->cUnlockedInLeave;       // no lock for our own
+        m->fIsLocked = false;
+        for (; m->cUnlockedInLeave; --m->cUnlockedInLeave)
+            callLockOnAllHandles();
+    }
+
+    if (m->fIsLocked)
+        callUnlockOnAllHandles();
+}
+
+/**
+ * Requests ownership of all contained semaphores. Public method that can
+ * only be called once and that also gets called by the AutoLock constructors.
+ */
+void AutoLockBase::acquire()
+{
+    AssertMsg(!m->fIsLocked, ("m->fIsLocked is true, attempting to lock twice!"));
+    callLockOnAllHandles();
+    m->fIsLocked = true;
+}
+
+/**
+ * Releases ownership of all contained semaphores. Public method.
  */
 void AutoLockBase::release()
 {
-    if (m->pHandle)
-    {
-        AssertMsg(m->fIsLocked, ("m->fIsLocked is false, cannot release!"));
-        // call virtual function implemented in AutoWriteLock or AutoReadLock
-        this->releaseImpl(*m->pHandle);
-        m->fIsLocked = false;
-    }
+    AssertMsg(m->fIsLocked, ("m->fIsLocked is false, cannot release!"));
+    callUnlockOnAllHandles();
+    m->fIsLocked = false;
 }
 
@@ -158,26 +217,4 @@
 //
 ////////////////////////////////////////////////////////////////////////////////
-
-void AutoWriteLock::cleanup()
-{
-    if (m->pHandle)
-    {
-        if (m->cUnlockedInLeave)
-        {
-            // there was a leave() before the destruction: then restore the
-            // lock level that might have been set by locks other than our own
-            if (m->fIsLocked)
-                --m->cUnlockedInLeave;       // no lock for our own
-            m->fIsLocked = false;
-            for (; m->cUnlockedInLeave; --m->cUnlockedInLeave)
-                m->pHandle->lockWrite();
-
-                // @todo r=dj is this really desirable behavior? maybe leave/enter should go altogether?
-        }
-
-        if (m->fIsLocked)
-            m->pHandle->unlockWrite();
-    }
-}
 
 /**
@@ -187,5 +224,5 @@
  * the semaphore in write mode.
  */
-/*virtual*/ void AutoWriteLock::acquireImpl(LockHandle &l)
+/*virtual*/ void AutoWriteLock::callLockImpl(LockHandle &l)
 {
     l.lockWrite();
@@ -198,5 +235,5 @@
  * the semaphore in write mode.
  */
-/*virtual*/ void AutoWriteLock::releaseImpl(LockHandle &l)
+/*virtual*/ void AutoWriteLock::callUnlockImpl(LockHandle &l)
 {
     l.unlockWrite();
@@ -226,16 +263,18 @@
 void AutoWriteLock::leave()
 {
-    if (m->pHandle)
+    LockHandle *pHandle = m->aHandles[0];
+
+    if (pHandle)
     {
         AssertMsg(m->fIsLocked, ("m->fIsLocked is false, cannot leave()!"));
         AssertMsg(m->cUnlockedInLeave == 0, ("m->cUnlockedInLeave is %d, must be 0! Called leave() twice?", m->cUnlockedInLeave));
 
-        m->cUnlockedInLeave = m->pHandle->writeLockLevel();
+        m->cUnlockedInLeave = pHandle->writeLockLevel();
         AssertMsg(m->cUnlockedInLeave >= 1, ("m->cUnlockedInLeave is %d, must be >=1!", m->cUnlockedInLeave));
 
         for (uint32_t left = m->cUnlockedInLeave;
-                left;
-                --left)
-            m->pHandle->unlockWrite();
+             left;
+             --left)
+            pHandle->unlockWrite();
     }
 }
@@ -249,5 +288,7 @@
 void AutoWriteLock::enter()
 {
-    if (m->pHandle)
+    LockHandle *pHandle = m->aHandles[0];
+
+    if (pHandle)
     {
         AssertMsg(m->fIsLocked, ("m->fIsLocked is false, cannot enter()!"));
@@ -255,5 +296,5 @@
 
         for (; m->cUnlockedInLeave; --m->cUnlockedInLeave)
-            m->pHandle->lockWrite();
+            pHandle->lockWrite();
     }
 }
@@ -271,6 +312,8 @@
 void AutoWriteLock::attach(LockHandle *aHandle)
 {
+    LockHandle *pHandle = m->aHandles[0];
+
     /* detect simple self-reattachment */
-    if (m->pHandle != aHandle)
+    if (pHandle != aHandle)
     {
         bool fWasLocked = m->fIsLocked;
@@ -278,10 +321,10 @@
         cleanup();
 
-        m->pHandle = aHandle;
+        m->aHandles[0] = aHandle;
         m->fIsLocked = fWasLocked;
 
-        if (m->pHandle)
+        if (aHandle)
             if (fWasLocked)
-                m->pHandle->lockWrite();
+                aHandle->lockWrite();
     }
 }
@@ -289,5 +332,5 @@
 void AutoWriteLock::attachRaw(LockHandle *ph)
 {
-    m->pHandle = ph;
+    m->aHandles[0] = ph;
 }
 
@@ -301,5 +344,5 @@
 bool AutoWriteLock::isWriteLockOnCurrentThread() const
 {
-    return m->pHandle ? m->pHandle->isWriteLockOnCurrentThread() : false;
+    return m->aHandles[0] ? m->aHandles[0]->isWriteLockOnCurrentThread() : false;
 }
 
@@ -317,5 +360,5 @@
 uint32_t AutoWriteLock::writeLockLevel() const
 {
-    return m->pHandle ? m->pHandle->writeLockLevel() : 0;
+    return m->aHandles[0] ? m->aHandles[0]->writeLockLevel() : 0;
 }
 
@@ -337,8 +380,10 @@
 /*virtual*/ AutoReadLock::~AutoReadLock()
 {
-    if (m->pHandle)
+    LockHandle *pHandle = m->aHandles[0];
+
+    if (pHandle)
     {
         if (m->fIsLocked)
-            m->pHandle->unlockRead();
+            pHandle->unlockRead();
     }
 }
@@ -350,5 +395,5 @@
  * the semaphore in read mode.
  */
-/*virtual*/ void AutoReadLock::acquireImpl(LockHandle &l)
+/*virtual*/ void AutoReadLock::callLockImpl(LockHandle &l)
 {
     l.lockRead();
@@ -361,5 +406,5 @@
  * the semaphore in read mode.
  */
-/*virtual*/ void AutoReadLock::releaseImpl(LockHandle &l)
+/*virtual*/ void AutoReadLock::callUnlockImpl(LockHandle &l)
 {
     l.unlockRead();
Index: trunk/src/VBox/Main/include/AutoLock.h
===================================================================
--- trunk/src/VBox/Main/include/AutoLock.h	(revision 25282)
+++ trunk/src/VBox/Main/include/AutoLock.h	(revision 25283)
@@ -323,6 +323,11 @@
     Data *m;
 
-    virtual void acquireImpl(LockHandle &l) = 0;
-    virtual void releaseImpl(LockHandle &l) = 0;
+    virtual void callLockImpl(LockHandle &l) = 0;
+    virtual void callUnlockImpl(LockHandle &l) = 0;
+
+    void callLockOnAllHandles();
+    void callUnlockOnAllHandles();
+
+    void cleanup();
 
 public:
@@ -412,8 +417,6 @@
     }
 
-    void cleanup();
-
-    virtual void acquireImpl(LockHandle &l);
-    virtual void releaseImpl(LockHandle &l);
+    virtual void callLockImpl(LockHandle &l);
+    virtual void callUnlockImpl(LockHandle &l);
 
     void leave();
@@ -532,6 +535,6 @@
     virtual ~AutoReadLock();
 
-    virtual void acquireImpl(LockHandle &l);
-    virtual void releaseImpl(LockHandle &l);
+    virtual void callLockImpl(LockHandle &l);
+    virtual void callUnlockImpl(LockHandle &l);
 };
 
