VirtualBox

Changeset 25283 in vbox for trunk/src


Ignore:
Timestamp:
Dec 9, 2009 7:50:30 PM (15 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
55830
Message:

Main: preparation for deadlock detection: add handles vector to AutoLockBase in preparation for AutoMulti* conversion

Location:
trunk/src/VBox/Main
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Main/AutoLock.cpp

    r25282 r25283  
    2626#include <iprt/string.h>
    2727
     28#include <vector>
    2829
    2930namespace util
     
    9495////////////////////////////////////////////////////////////////////////////////
    9596
     97typedef std::vector<LockHandle*> HandlesVector;
     98
    9699struct AutoLockBase::Data
    97100{
    98     Data(LockHandle *argpHandle)
    99         : pHandle(argpHandle),
     101    Data(size_t cHandles)
     102        : aHandles(cHandles),       // size of array
    100103          fIsLocked(false),
    101104          cUnlockedInLeave(0)
    102105    { }
    103106
    104     LockHandle      *pHandle;
    105     bool            fIsLocked;
     107    HandlesVector   aHandles;           // array (vector) of LockHandle instances; in the case of AutoWriteLock
     108                                        // and AutoReadLock, there will only be one item on the list; with the
     109                                        // AutoMulti* derivatives, there will be multiple
     110    bool            fIsLocked;          // if true, then all items in aHandles are locked by this AutoLock and
     111                                        // need to be unlocked in the destructor
    106112    uint32_t        cUnlockedInLeave;   // how many times the handle was unlocked in leave(); otherwise 0
    107113};
     
    109115AutoLockBase::AutoLockBase(LockHandle *pHandle)
    110116{
    111     m = new Data(pHandle);
     117    m = new Data(1);
     118    m->aHandles[0] = pHandle;
    112119}
    113120
     
    119126/**
    120127 * Requests ownership of all contained lock handles by calling
    121  * the pure virtual acquireImpl() function on each of them,
     128 * the pure virtual callLockImpl() function on each of them,
    122129 * which must be implemented by the descendant class; in the
    123130 * implementation, AutoWriteLock will request a write lock
    124131 * whereas AutoReadLock will request a read lock.
    125  */
    126 void AutoLockBase::acquire()
    127 {
    128     if (m->pHandle)
    129     {
    130         AssertMsg(!m->fIsLocked, ("m->fIsLocked is true, attempting to lock twice!"));
    131         // call virtual function implemented in AutoWriteLock or AutoReadLock
    132         this->acquireImpl(*m->pHandle);
    133         m->fIsLocked = true;
     132 *
     133 * Does *not* modify the lock counts in the member variables.
     134 */
     135void AutoLockBase::callLockOnAllHandles()
     136{
     137    for (HandlesVector::iterator it = m->aHandles.begin();
     138         it != m->aHandles.end();
     139         ++it)
     140    {
     141        LockHandle *pHandle = *it;
     142        if (pHandle)
     143            // call virtual function implemented in AutoWriteLock or AutoReadLock
     144            this->callLockImpl(*pHandle);
    134145    }
    135146}
     
    137148/**
    138149 * Releases ownership of all contained lock handles by calling
    139  * the pure virtual releaseImpl() function on each of them,
     150 * the pure virtual callUnlockImpl() function on each of them,
    140151 * which must be implemented by the descendant class; in the
    141152 * implementation, AutoWriteLock will release a write lock
    142153 * whereas AutoReadLock will release a read lock.
     154 *
     155 * Does *not* modify the lock counts in the member variables.
     156 */
     157void AutoLockBase::callUnlockOnAllHandles()
     158{
     159    for (HandlesVector::iterator it = m->aHandles.begin();
     160         it != m->aHandles.end();
     161         ++it)
     162    {
     163        LockHandle *pHandle = *it;
     164        if (pHandle)
     165            // call virtual function implemented in AutoWriteLock or AutoReadLock
     166            this->callUnlockImpl(*pHandle);
     167    }
     168}
     169
     170/**
     171 * Destructor implementation that can also be called explicitly, if required.
     172 * Restores the exact state before the AutoLock was created; that is, unlocks
     173 * all contained semaphores and might actually lock them again if leave()
     174 * was called during the AutoLock's lifetime.
     175 */
     176void AutoLockBase::cleanup()
     177{
     178    if (m->cUnlockedInLeave)
     179    {
     180        // there was a leave() before the destruction: then restore the
     181        // lock level that might have been set by locks other than our own
     182        if (m->fIsLocked)
     183            --m->cUnlockedInLeave;       // no lock for our own
     184        m->fIsLocked = false;
     185        for (; m->cUnlockedInLeave; --m->cUnlockedInLeave)
     186            callLockOnAllHandles();
     187    }
     188
     189    if (m->fIsLocked)
     190        callUnlockOnAllHandles();
     191}
     192
     193/**
     194 * Requests ownership of all contained semaphores. Public method that can
     195 * only be called once and that also gets called by the AutoLock constructors.
     196 */
     197void AutoLockBase::acquire()
     198{
     199    AssertMsg(!m->fIsLocked, ("m->fIsLocked is true, attempting to lock twice!"));
     200    callLockOnAllHandles();
     201    m->fIsLocked = true;
     202}
     203
     204/**
     205 * Releases ownership of all contained semaphores. Public method.
    143206 */
    144207void AutoLockBase::release()
    145208{
    146     if (m->pHandle)
    147     {
    148         AssertMsg(m->fIsLocked, ("m->fIsLocked is false, cannot release!"));
    149         // call virtual function implemented in AutoWriteLock or AutoReadLock
    150         this->releaseImpl(*m->pHandle);
    151         m->fIsLocked = false;
    152     }
     209    AssertMsg(m->fIsLocked, ("m->fIsLocked is false, cannot release!"));
     210    callUnlockOnAllHandles();
     211    m->fIsLocked = false;
    153212}
    154213
     
    158217//
    159218////////////////////////////////////////////////////////////////////////////////
    160 
    161 void AutoWriteLock::cleanup()
    162 {
    163     if (m->pHandle)
    164     {
    165         if (m->cUnlockedInLeave)
    166         {
    167             // there was a leave() before the destruction: then restore the
    168             // lock level that might have been set by locks other than our own
    169             if (m->fIsLocked)
    170                 --m->cUnlockedInLeave;       // no lock for our own
    171             m->fIsLocked = false;
    172             for (; m->cUnlockedInLeave; --m->cUnlockedInLeave)
    173                 m->pHandle->lockWrite();
    174 
    175                 // @todo r=dj is this really desirable behavior? maybe leave/enter should go altogether?
    176         }
    177 
    178         if (m->fIsLocked)
    179             m->pHandle->unlockWrite();
    180     }
    181 }
    182219
    183220/**
     
    187224 * the semaphore in write mode.
    188225 */
    189 /*virtual*/ void AutoWriteLock::acquireImpl(LockHandle &l)
     226/*virtual*/ void AutoWriteLock::callLockImpl(LockHandle &l)
    190227{
    191228    l.lockWrite();
     
    198235 * the semaphore in write mode.
    199236 */
    200 /*virtual*/ void AutoWriteLock::releaseImpl(LockHandle &l)
     237/*virtual*/ void AutoWriteLock::callUnlockImpl(LockHandle &l)
    201238{
    202239    l.unlockWrite();
     
    226263void AutoWriteLock::leave()
    227264{
    228     if (m->pHandle)
     265    LockHandle *pHandle = m->aHandles[0];
     266
     267    if (pHandle)
    229268    {
    230269        AssertMsg(m->fIsLocked, ("m->fIsLocked is false, cannot leave()!"));
    231270        AssertMsg(m->cUnlockedInLeave == 0, ("m->cUnlockedInLeave is %d, must be 0! Called leave() twice?", m->cUnlockedInLeave));
    232271
    233         m->cUnlockedInLeave = m->pHandle->writeLockLevel();
     272        m->cUnlockedInLeave = pHandle->writeLockLevel();
    234273        AssertMsg(m->cUnlockedInLeave >= 1, ("m->cUnlockedInLeave is %d, must be >=1!", m->cUnlockedInLeave));
    235274
    236275        for (uint32_t left = m->cUnlockedInLeave;
    237                 left;
    238                 --left)
    239             m->pHandle->unlockWrite();
     276             left;
     277             --left)
     278            pHandle->unlockWrite();
    240279    }
    241280}
     
    249288void AutoWriteLock::enter()
    250289{
    251     if (m->pHandle)
     290    LockHandle *pHandle = m->aHandles[0];
     291
     292    if (pHandle)
    252293    {
    253294        AssertMsg(m->fIsLocked, ("m->fIsLocked is false, cannot enter()!"));
     
    255296
    256297        for (; m->cUnlockedInLeave; --m->cUnlockedInLeave)
    257             m->pHandle->lockWrite();
     298            pHandle->lockWrite();
    258299    }
    259300}
     
    271312void AutoWriteLock::attach(LockHandle *aHandle)
    272313{
     314    LockHandle *pHandle = m->aHandles[0];
     315
    273316    /* detect simple self-reattachment */
    274     if (m->pHandle != aHandle)
     317    if (pHandle != aHandle)
    275318    {
    276319        bool fWasLocked = m->fIsLocked;
     
    278321        cleanup();
    279322
    280         m->pHandle = aHandle;
     323        m->aHandles[0] = aHandle;
    281324        m->fIsLocked = fWasLocked;
    282325
    283         if (m->pHandle)
     326        if (aHandle)
    284327            if (fWasLocked)
    285                 m->pHandle->lockWrite();
     328                aHandle->lockWrite();
    286329    }
    287330}
     
    289332void AutoWriteLock::attachRaw(LockHandle *ph)
    290333{
    291     m->pHandle = ph;
     334    m->aHandles[0] = ph;
    292335}
    293336
     
    301344bool AutoWriteLock::isWriteLockOnCurrentThread() const
    302345{
    303     return m->pHandle ? m->pHandle->isWriteLockOnCurrentThread() : false;
     346    return m->aHandles[0] ? m->aHandles[0]->isWriteLockOnCurrentThread() : false;
    304347}
    305348
     
    317360uint32_t AutoWriteLock::writeLockLevel() const
    318361{
    319     return m->pHandle ? m->pHandle->writeLockLevel() : 0;
     362    return m->aHandles[0] ? m->aHandles[0]->writeLockLevel() : 0;
    320363}
    321364
     
    337380/*virtual*/ AutoReadLock::~AutoReadLock()
    338381{
    339     if (m->pHandle)
     382    LockHandle *pHandle = m->aHandles[0];
     383
     384    if (pHandle)
    340385    {
    341386        if (m->fIsLocked)
    342             m->pHandle->unlockRead();
     387            pHandle->unlockRead();
    343388    }
    344389}
     
    350395 * the semaphore in read mode.
    351396 */
    352 /*virtual*/ void AutoReadLock::acquireImpl(LockHandle &l)
     397/*virtual*/ void AutoReadLock::callLockImpl(LockHandle &l)
    353398{
    354399    l.lockRead();
     
    361406 * the semaphore in read mode.
    362407 */
    363 /*virtual*/ void AutoReadLock::releaseImpl(LockHandle &l)
     408/*virtual*/ void AutoReadLock::callUnlockImpl(LockHandle &l)
    364409{
    365410    l.unlockRead();
  • trunk/src/VBox/Main/include/AutoLock.h

    r25282 r25283  
    323323    Data *m;
    324324
    325     virtual void acquireImpl(LockHandle &l) = 0;
    326     virtual void releaseImpl(LockHandle &l) = 0;
     325    virtual void callLockImpl(LockHandle &l) = 0;
     326    virtual void callUnlockImpl(LockHandle &l) = 0;
     327
     328    void callLockOnAllHandles();
     329    void callUnlockOnAllHandles();
     330
     331    void cleanup();
    327332
    328333public:
     
    412417    }
    413418
    414     void cleanup();
    415 
    416     virtual void acquireImpl(LockHandle &l);
    417     virtual void releaseImpl(LockHandle &l);
     419    virtual void callLockImpl(LockHandle &l);
     420    virtual void callUnlockImpl(LockHandle &l);
    418421
    419422    void leave();
     
    532535    virtual ~AutoReadLock();
    533536
    534     virtual void acquireImpl(LockHandle &l);
    535     virtual void releaseImpl(LockHandle &l);
     537    virtual void callLockImpl(LockHandle &l);
     538    virtual void callUnlockImpl(LockHandle &l);
    536539};
    537540
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette