VirtualBox

Changeset 25285 in vbox for trunk/src/VBox/Main/include


Ignore:
Timestamp:
Dec 9, 2009 11:38:58 PM (15 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
55832
Message:

Main: preparation for deadlock detection: convert AutoMultiWriteLock*: inheritance instead of template

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Main/include/AutoLock.h

    r25284 r25285  
    318318{
    319319protected:
    320     AutoLockBase(LockHandle *pHandle);
     320    AutoLockBase(uint32_t cHandles);
     321    AutoLockBase(uint32_t cHandles, LockHandle *pHandle);
    321322    virtual ~AutoLockBase();
    322323
     
    361362     */
    362363    AutoReadLock()
    363         : AutoLockBase(NULL)
     364        : AutoLockBase(1, NULL)
    364365    { }
    365366
     
    369370     */
    370371    AutoReadLock(LockHandle *aHandle)
    371         : AutoLockBase(aHandle)
     372        : AutoLockBase(1, aHandle)
    372373    {
    373374        acquire();
     
    379380     */
    380381    AutoReadLock(LockHandle &aHandle)
    381         : AutoLockBase(&aHandle)
     382        : AutoLockBase(1, &aHandle)
    382383    {
    383384        acquire();
     
    389390     */
    390391    AutoReadLock(const Lockable &aLockable)
    391         : AutoLockBase(aLockable.lockHandle())
     392        : AutoLockBase(1, aLockable.lockHandle())
    392393    {
    393394        acquire();
     
    399400     */
    400401    AutoReadLock(const Lockable *aLockable)
    401         : AutoLockBase(aLockable ? aLockable->lockHandle() : NULL)
     402        : AutoLockBase(1, aLockable ? aLockable->lockHandle() : NULL)
    402403    {
    403404        acquire();
     
    419420{
    420421protected:
    421     AutoWriteLockBase(LockHandle *pHandle)
    422         : AutoLockBase(pHandle)
     422    AutoWriteLockBase(uint32_t cHandles)
     423        : AutoLockBase(cHandles)
     424    { }
     425
     426    AutoWriteLockBase(uint32_t cHandles, LockHandle *pHandle)
     427        : AutoLockBase(cHandles, pHandle)
    423428    { }
    424429
     
    430435
    431436public:
    432     bool isWriteLockOnCurrentThread() const;
    433     uint32_t writeLockLevel() const;
    434 
    435437    void leave();
    436438    void enter();
    437 
    438     /**
    439      * Same as #leave() but checks if the current thread actally owns the lock
    440      * and only proceeds in this case. As a result, as opposed to #leave(),
    441      * doesn't assert when called with no lock being held.
    442      */
    443     void maybeLeave()
    444     {
    445         if (isWriteLockOnCurrentThread())
    446             leave();
    447     }
    448 
    449     /**
    450      * Same as #enter() but checks if the current thread actally owns the lock
    451      * and only proceeds if not. As a result, as opposed to #enter(), doesn't
    452      * assert when called with the lock already being held.
    453      */
    454     void maybeEnter()
    455     {
    456         if (!isWriteLockOnCurrentThread())
    457             enter();
    458     }
    459 
     439    void maybeLeave();
     440    void maybeEnter();
    460441};
    461442
     
    479460     */
    480461    AutoWriteLock()
    481         : AutoWriteLockBase(NULL)
     462        : AutoWriteLockBase(1, NULL)
    482463    { }
    483464
     
    487468     */
    488469    AutoWriteLock(LockHandle *aHandle)
    489         : AutoWriteLockBase(aHandle)
     470        : AutoWriteLockBase(1, aHandle)
    490471    {
    491472        acquire();
     
    497478     */
    498479    AutoWriteLock(LockHandle &aHandle)
    499         : AutoWriteLockBase(&aHandle)
     480        : AutoWriteLockBase(1, &aHandle)
    500481    {
    501482        acquire();
     
    507488     */
    508489    AutoWriteLock(const Lockable &aLockable)
    509         : AutoWriteLockBase(aLockable.lockHandle())
     490        : AutoWriteLockBase(1, aLockable.lockHandle())
    510491    {
    511492        acquire();
     
    517498     */
    518499    AutoWriteLock(const Lockable *aLockable)
    519         : AutoWriteLockBase(aLockable ? aLockable->lockHandle() : NULL)
     500        : AutoWriteLockBase(1, aLockable ? aLockable->lockHandle() : NULL)
    520501    {
    521502        acquire();
     
    557538
    558539    void attachRaw(LockHandle *ph);
    559 };
     540
     541    bool isWriteLockOnCurrentThread() const;
     542    uint32_t writeLockLevel() const;
     543};
     544
     545////////////////////////////////////////////////////////////////////////////////
     546//
     547// AutoMultiWriteLock*
     548//
     549////////////////////////////////////////////////////////////////////////////////
     550
     551class AutoMultiWriteLock2 : public AutoWriteLockBase
     552{
     553public:
     554    AutoMultiWriteLock2(Lockable *pl1, Lockable *pl2);
     555    AutoMultiWriteLock2(LockHandle *pl1, LockHandle *pl2);
     556
     557    virtual ~AutoMultiWriteLock2()
     558    {
     559        cleanup();
     560    }
     561};
     562
     563class AutoMultiWriteLock3 : public AutoWriteLockBase
     564{
     565public:
     566    AutoMultiWriteLock3(Lockable *pl1, Lockable *pl2, Lockable *pl3);
     567    AutoMultiWriteLock3(LockHandle *pl1, LockHandle *pl2, LockHandle *pl3);
     568
     569    virtual ~AutoMultiWriteLock3()
     570    {
     571        cleanup();
     572    }
     573};
     574
    560575
    561576////////////////////////////////////////////////////////////////////////////////
     
    710725#undef A
    711726
    712 ////////////////////////////////////////////////////////////////////////////////
    713 
    714 /**
    715  * Helper template class for AutoMultiWriteLockN classes.
    716  *
    717  * @param Cnt number of write semaphores to manage.
    718  */
    719 template <size_t Cnt>
    720 class AutoMultiWriteLockBase
    721 {
    722 
    723 public:
    724     /**
    725      * Calls AutoWriteLock::acquire() methods for all managed semaphore handles in
    726      * order they were passed to the constructor.
    727      */
    728     void acquire()
    729     {
    730         size_t i = 0;
    731         while (i < RT_ELEMENTS(mLocks))
    732             mLocks[i++].acquire();
    733     }
    734 
    735     /**
    736      * Calls AutoWriteLock::unlock() methods for all managed semaphore handles
    737      * in reverse to the order they were passed to the constructor.
    738      */
    739     void release()
    740     {
    741         AssertReturnVoid(RT_ELEMENTS(mLocks) > 0);
    742         size_t i = RT_ELEMENTS(mLocks);
    743         do
    744             mLocks[--i].release();
    745         while (i != 0);
    746     }
    747 
    748     /**
    749      * Calls AutoWriteLock::leave() methods for all managed semaphore handles in
    750      * reverse to the order they were passed to the constructor.
    751      */
    752     void leave()
    753     {
    754         AssertReturnVoid(RT_ELEMENTS(mLocks) > 0);
    755         size_t i = RT_ELEMENTS(mLocks);
    756         do
    757             mLocks[--i].leave();
    758         while (i != 0);
    759     }
    760 
    761     /**
    762     * Calls AutoWriteLock::maybeLeave() methods for all managed semaphore
    763     * handles in reverse to the order they were passed to the constructor.
    764      */
    765     void maybeLeave()
    766     {
    767         AssertReturnVoid(RT_ELEMENTS(mLocks) > 0);
    768         size_t i = RT_ELEMENTS(mLocks);
    769         do
    770             mLocks [-- i].maybeLeave();
    771         while (i != 0);
    772     }
    773 
    774     /**
    775      * Calls AutoWriteLock::maybeEnter() methods for all managed semaphore
    776      * handles in order they were passed to the constructor.
    777      */
    778     void maybeEnter()
    779     {
    780         size_t i = 0;
    781         while (i < RT_ELEMENTS(mLocks))
    782             mLocks[i++].maybeEnter();
    783     }
    784 
    785     /**
    786      * Calls AutoWriteLock::enter() methods for all managed semaphore handles in
    787      * order they were passed to the constructor.
    788      */
    789     void enter()
    790     {
    791         size_t i = 0;
    792         while (i < RT_ELEMENTS(mLocks))
    793             mLocks[i++].enter();
    794     }
    795 
    796 protected:
    797 
    798     AutoMultiWriteLockBase() {}
    799 
    800     void setLockHandle(size_t aIdx, LockHandle *aHandle)
    801     {
    802         mLocks[aIdx].attachRaw(aHandle);
    803     }
    804 
    805 private:
    806 
    807     AutoWriteLock mLocks[Cnt];
    808 
    809     DECLARE_CLS_COPY_CTOR_ASSIGN_NOOP (AutoMultiWriteLockBase)
    810     DECLARE_CLS_NEW_DELETE_NOOP (AutoMultiWriteLockBase)
    811 };
    812 
    813 /** AutoMultiWriteLockBase <0> is meaningless and forbidden. */
    814 template<>
    815 class AutoMultiWriteLockBase <0> { private : AutoMultiWriteLockBase(); };
    816 
    817 /** AutoMultiWriteLockBase <1> is meaningless and forbidden. */
    818 template<>
    819 class AutoMultiWriteLockBase <1> { private : AutoMultiWriteLockBase(); };
    820 
    821 ////////////////////////////////////////////////////////////////////////////////
    822 
    823 /* AutoMultiLockN class definitions */
    824 
    825 #define A(n) LockHandle *l##n
    826 #define B(n) setLockHandle (n, l##n)
    827 
    828 #define C(n) Lockable *l##n
    829 #define D(n) setLockHandle (n, l##n ? l##n->lockHandle() : NULL)
    830 
    831 /**
    832  * AutoMultiWriteLock for 2 locks.
    833  *
    834  * The AutoMultiWriteLockN family of classes provides a possibility to manage
    835  * several read/write semaphores at once. This is handy if all managed
    836  * semaphores need to be locked and unlocked synchronously and will also help to
    837  * avoid locking order errors.
    838  *
    839  * The functionality of the AutoMultiWriteLockN class family is similar to the
    840  * functionality of the AutoMultiLockN class family (see the AutoMultiLock2
    841  * class for details) with two important differences:
    842  * <ol>
    843  *     <li>Instances of AutoMultiWriteLockN classes are constructed from a list
    844  *     of LockHandle or Lockable arguments directly instead of getting
    845  *     intermediate LockOps interface pointers.
    846  *     </li>
    847  *     <li>All locks are requested in <b>write</b> mode.
    848  *     </li>
    849  *     <li>Since all locks are requested in write mode, bulk
    850  *     AutoMultiWriteLockBase::leave() and AutoMultiWriteLockBase::enter()
    851  *     operations are also available, that will leave and enter all managed
    852  *     semaphores at once in the proper order (similarly to
    853  *     AutoMultiWriteLockBase::lock() and AutoMultiWriteLockBase::unlock()).
    854  *     </li>
    855  * </ol>
    856  *
    857  * Here is a typical usage pattern:
    858  * <code>
    859  *  ...
    860  *  LockHandle data1, data2;
    861  *  ...
    862  *  {
    863  *      AutoMultiWriteLock2 multiLock (&data1, &data2);
    864  *      // both locks are held in write mode here
    865  *  }
    866  *  // both locks are released here
    867  * </code>
    868  */
    869 class AutoMultiWriteLock2 : public AutoMultiWriteLockBase <2>
    870 {
    871 public:
    872     AutoMultiWriteLock2 (A(0), A(1))
    873     { B(0); B(1); acquire(); }
    874     AutoMultiWriteLock2 (C(0), C(1))
    875     { D(0); D(1); acquire(); }
    876 };
    877 
    878 /** AutoMultiWriteLock for 3 locks. See AutoMultiWriteLock2 for more details. */
    879 class AutoMultiWriteLock3 : public AutoMultiWriteLockBase <3>
    880 {
    881 public:
    882     AutoMultiWriteLock3 (A(0), A(1), A(2))
    883     { B(0); B(1); B(2); acquire(); }
    884     AutoMultiWriteLock3 (C(0), C(1), C(2))
    885     { D(0); D(1); D(2); acquire(); }
    886 };
    887 
    888 /** AutoMultiWriteLock for 4 locks. See AutoMultiWriteLock2 for more details. */
    889 class AutoMultiWriteLock4 : public AutoMultiWriteLockBase <4>
    890 {
    891 public:
    892     AutoMultiWriteLock4 (A(0), A(1), A(2), A(3))
    893     { B(0); B(1); B(2); B(3); acquire(); }
    894     AutoMultiWriteLock4 (C(0), C(1), C(2), C(3))
    895     { D(0); D(1); D(2); D(3); acquire(); }
    896 };
    897 
    898 #undef D
    899 #undef C
    900 #undef B
    901 #undef A
    902 
    903727} /* namespace util */
    904728
Note: See TracChangeset for help on using the changeset viewer.

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