- Timestamp:
- Dec 9, 2009 6:15:54 PM (15 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Main/include/AutoLock.h
r25279 r25280 319 319 AutoLockBase(LockHandle *pHandle) 320 320 : mHandle(pHandle), 321 m LockLevel(0),322 m GlobalLockLevel(0)321 m_fIsLocked(false), 322 m_cUnlockedInLeave(0) 323 323 { } 324 324 325 LockHandle *mHandle;326 uint32_t mLockLevel;327 uint32_t mGlobalLockLevel;325 LockHandle *mHandle; 326 bool m_fIsLocked; 327 uint32_t m_cUnlockedInLeave; // how many times the handle was unlocked in leave(); otherwise 0 328 328 }; 329 329 … … 401 401 ~AutoWriteLock() 402 402 { 403 cleanup(); 404 } 405 406 void cleanup() 407 { 403 408 if (mHandle) 404 409 { 405 if (m GlobalLockLevel)410 if (m_cUnlockedInLeave) 406 411 { 407 mGlobalLockLevel -= mLockLevel; 408 mLockLevel = 0; 409 for (; mGlobalLockLevel; --mGlobalLockLevel) 412 // there was a leave() before the destruction: then restore the 413 // lock level that might have been set by locks other than our own 414 if (m_fIsLocked) 415 --m_cUnlockedInLeave; // no lock for our own 416 m_fIsLocked = false; 417 for (; m_cUnlockedInLeave; --m_cUnlockedInLeave) 410 418 mHandle->lockWrite(); 419 420 // @todo r=dj is this really desirable behavior? maybe leave/enter should go altogether? 411 421 } 412 422 413 AssertMsg(mLockLevel <= 1, ("Lock level > 1: %d\n", mLockLevel)); 414 for (; mLockLevel; --mLockLevel) 423 if (m_fIsLocked) 415 424 mHandle->unlockWrite(); 416 425 } … … 428 437 if (mHandle) 429 438 { 439 AssertMsg(!m_fIsLocked, ("m_fIsLocked is true, attempting to lock twice!")); 430 440 mHandle->lockWrite(); 431 ++mLockLevel; 432 Assert(mLockLevel != 0 /* overflow? */); 441 m_fIsLocked = true; 433 442 } 434 443 } … … 444 453 if (mHandle) 445 454 { 446 Assert ReturnVoid(mLockLevel != 0 /* unlock() w/o preceding lock()? */);455 AssertMsg(m_fIsLocked, ("m_fIsLocked is false, cannot release!")); 447 456 mHandle->unlockWrite(); 448 --mLockLevel;457 m_fIsLocked = false; 449 458 } 450 459 } … … 475 484 if (mHandle) 476 485 { 477 AssertReturnVoid(mLockLevel != 0 /* leave() w/o preceding lock()? */); 478 AssertReturnVoid(mGlobalLockLevel == 0 /* second leave() in a row? */); 479 480 mGlobalLockLevel = mHandle->writeLockLevel(); 481 AssertReturnVoid(mGlobalLockLevel >= mLockLevel /* logic error! */); 482 483 for (uint32_t left = mGlobalLockLevel; left; --left) 486 AssertMsg(m_fIsLocked, ("m_fIsLocked is false, cannot leave()!")); 487 AssertMsg(m_cUnlockedInLeave == 0, ("m_cUnlockedInLeave is %d, must be 0! Called leave() twice?", m_cUnlockedInLeave)); 488 489 m_cUnlockedInLeave = mHandle->writeLockLevel(); 490 AssertMsg(m_cUnlockedInLeave >= 1, ("m_cUnlockedInLeave is %d, must be >=1!", m_cUnlockedInLeave)); 491 492 for (uint32_t left = m_cUnlockedInLeave; 493 left; 494 --left) 484 495 mHandle->unlockWrite(); 485 496 } … … 518 529 if (mHandle) 519 530 { 520 Assert ReturnVoid(mLockLevel != 0 /* enter() w/o preceding lock()+leave()? */);521 Assert ReturnVoid(mGlobalLockLevel != 0 /* enter() w/o preceding leave()? */);522 523 for (; m GlobalLockLevel; --mGlobalLockLevel)531 AssertMsg(m_fIsLocked, ("m_fIsLocked is false, cannot enter()!")); 532 AssertMsg(m_cUnlockedInLeave != 0, ("m_cUnlockedInLeave is 0! enter() without leave()?")); 533 534 for (; m_cUnlockedInLeave; --m_cUnlockedInLeave) 524 535 mHandle->lockWrite(); 525 536 } … … 541 552 if (mHandle != aHandle) 542 553 { 543 uint32_t lockLevel = mLockLevel; 544 545 /* perform the destructor part */ 554 bool fWasLocked = m_fIsLocked; 555 556 cleanup(); 557 558 mHandle = aHandle; 559 m_fIsLocked = fWasLocked; 560 546 561 if (mHandle) 547 { 548 if (mGlobalLockLevel) 549 { 550 mGlobalLockLevel -= mLockLevel; 551 mLockLevel = 0; 552 for (; mGlobalLockLevel; --mGlobalLockLevel) 553 mHandle->lockWrite(); 554 } 555 556 AssertMsg(mLockLevel <= 1, ("Lock level > 1: %d\n", mLockLevel)); 557 for (; mLockLevel; --mLockLevel) 558 mHandle->unlockWrite(); 559 } 560 561 mHandle = aHandle; 562 mLockLevel = lockLevel; 563 564 if (mHandle) 565 for (; lockLevel; --lockLevel) 562 if (fWasLocked) 566 563 mHandle->lockWrite(); 567 564 } … … 697 694 if (mHandle) 698 695 { 699 AssertMsg(mLockLevel <= 1, ("Lock level > 1: %d\n", mLockLevel)); 700 for (; mLockLevel; --mLockLevel) 696 if (m_fIsLocked) 701 697 mHandle->unlockRead(); 702 698 } … … 719 715 if (mHandle) 720 716 { 717 AssertMsg(!m_fIsLocked, ("m_fIsLocked is true, attempting to lock twice!")); 721 718 mHandle->lockRead(); 722 ++mLockLevel; 723 Assert(mLockLevel != 0 /* overflow? */); 719 m_fIsLocked = true; 724 720 } 725 721 } … … 735 731 if (mHandle) 736 732 { 737 Assert ReturnVoid(mLockLevel != 0 /* unlock() w/o preceding lock()? */);733 AssertMsg(m_fIsLocked, ("m_fIsLocked is false, cannot release!")); 738 734 mHandle->unlockRead(); 739 --mLockLevel;735 m_fIsLocked = false; 740 736 } 741 }742 743 /**744 * Attaches another handle to this auto lock instance.745 *746 * The previous object's lock is completely released before the new one is747 * acquired. The lock level of the new handle will be the same. This also748 * means that if the lock was not acquired at all before #attach(), it will749 * not be acquired on the new handle too.750 *751 * @param aHandle New handle to attach.752 */753 void attach(LockHandle *aHandle)754 {755 /* detect simple self-reattachment */756 if (mHandle != aHandle)757 {758 uint32_t lockLevel = mLockLevel;759 if (mHandle)760 for (; mLockLevel; --mLockLevel)761 mHandle->unlockRead();762 mHandle = aHandle;763 mLockLevel = lockLevel;764 if (mHandle)765 for (; lockLevel; --lockLevel)766 mHandle->lockRead();767 }768 }769 770 /** @see attach (LockHandle *) */771 void attach(LockHandle &aHandle)772 {773 attach(&aHandle);774 }775 776 /** @see attach (LockHandle *) */777 void attach(const Lockable &aLockable)778 {779 attach(aLockable.lockHandle());780 }781 782 /** @see attach (LockHandle *) */783 void attach(const Lockable *aLockable)784 {785 attach(aLockable ? aLockable->lockHandle() : NULL);786 737 } 787 738
Note:
See TracChangeset
for help on using the changeset viewer.