Changeset 25285 in vbox for trunk/src/VBox/Main/include
- Timestamp:
- Dec 9, 2009 11:38:58 PM (15 years ago)
- svn:sync-xref-src-repo-rev:
- 55832
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Main/include/AutoLock.h
r25284 r25285 318 318 { 319 319 protected: 320 AutoLockBase(LockHandle *pHandle); 320 AutoLockBase(uint32_t cHandles); 321 AutoLockBase(uint32_t cHandles, LockHandle *pHandle); 321 322 virtual ~AutoLockBase(); 322 323 … … 361 362 */ 362 363 AutoReadLock() 363 : AutoLockBase( NULL)364 : AutoLockBase(1, NULL) 364 365 { } 365 366 … … 369 370 */ 370 371 AutoReadLock(LockHandle *aHandle) 371 : AutoLockBase( aHandle)372 : AutoLockBase(1, aHandle) 372 373 { 373 374 acquire(); … … 379 380 */ 380 381 AutoReadLock(LockHandle &aHandle) 381 : AutoLockBase( &aHandle)382 : AutoLockBase(1, &aHandle) 382 383 { 383 384 acquire(); … … 389 390 */ 390 391 AutoReadLock(const Lockable &aLockable) 391 : AutoLockBase( aLockable.lockHandle())392 : AutoLockBase(1, aLockable.lockHandle()) 392 393 { 393 394 acquire(); … … 399 400 */ 400 401 AutoReadLock(const Lockable *aLockable) 401 : AutoLockBase( aLockable ? aLockable->lockHandle() : NULL)402 : AutoLockBase(1, aLockable ? aLockable->lockHandle() : NULL) 402 403 { 403 404 acquire(); … … 419 420 { 420 421 protected: 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) 423 428 { } 424 429 … … 430 435 431 436 public: 432 bool isWriteLockOnCurrentThread() const;433 uint32_t writeLockLevel() const;434 435 437 void leave(); 436 438 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(); 460 441 }; 461 442 … … 479 460 */ 480 461 AutoWriteLock() 481 : AutoWriteLockBase( NULL)462 : AutoWriteLockBase(1, NULL) 482 463 { } 483 464 … … 487 468 */ 488 469 AutoWriteLock(LockHandle *aHandle) 489 : AutoWriteLockBase( aHandle)470 : AutoWriteLockBase(1, aHandle) 490 471 { 491 472 acquire(); … … 497 478 */ 498 479 AutoWriteLock(LockHandle &aHandle) 499 : AutoWriteLockBase( &aHandle)480 : AutoWriteLockBase(1, &aHandle) 500 481 { 501 482 acquire(); … … 507 488 */ 508 489 AutoWriteLock(const Lockable &aLockable) 509 : AutoWriteLockBase( aLockable.lockHandle())490 : AutoWriteLockBase(1, aLockable.lockHandle()) 510 491 { 511 492 acquire(); … … 517 498 */ 518 499 AutoWriteLock(const Lockable *aLockable) 519 : AutoWriteLockBase( aLockable ? aLockable->lockHandle() : NULL)500 : AutoWriteLockBase(1, aLockable ? aLockable->lockHandle() : NULL) 520 501 { 521 502 acquire(); … … 557 538 558 539 void attachRaw(LockHandle *ph); 559 }; 540 541 bool isWriteLockOnCurrentThread() const; 542 uint32_t writeLockLevel() const; 543 }; 544 545 //////////////////////////////////////////////////////////////////////////////// 546 // 547 // AutoMultiWriteLock* 548 // 549 //////////////////////////////////////////////////////////////////////////////// 550 551 class AutoMultiWriteLock2 : public AutoWriteLockBase 552 { 553 public: 554 AutoMultiWriteLock2(Lockable *pl1, Lockable *pl2); 555 AutoMultiWriteLock2(LockHandle *pl1, LockHandle *pl2); 556 557 virtual ~AutoMultiWriteLock2() 558 { 559 cleanup(); 560 } 561 }; 562 563 class AutoMultiWriteLock3 : public AutoWriteLockBase 564 { 565 public: 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 560 575 561 576 //////////////////////////////////////////////////////////////////////////////// … … 710 725 #undef A 711 726 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 AutoMultiWriteLockBase721 {722 723 public:724 /**725 * Calls AutoWriteLock::acquire() methods for all managed semaphore handles in726 * 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 handles737 * 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 do744 mLocks[--i].release();745 while (i != 0);746 }747 748 /**749 * Calls AutoWriteLock::leave() methods for all managed semaphore handles in750 * 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 do757 mLocks[--i].leave();758 while (i != 0);759 }760 761 /**762 * Calls AutoWriteLock::maybeLeave() methods for all managed semaphore763 * 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 do770 mLocks [-- i].maybeLeave();771 while (i != 0);772 }773 774 /**775 * Calls AutoWriteLock::maybeEnter() methods for all managed semaphore776 * 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 in787 * 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##n826 #define B(n) setLockHandle (n, l##n)827 828 #define C(n) Lockable *l##n829 #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 manage835 * several read/write semaphores at once. This is handy if all managed836 * semaphores need to be locked and unlocked synchronously and will also help to837 * avoid locking order errors.838 *839 * The functionality of the AutoMultiWriteLockN class family is similar to the840 * functionality of the AutoMultiLockN class family (see the AutoMultiLock2841 * class for details) with two important differences:842 * <ol>843 * <li>Instances of AutoMultiWriteLockN classes are constructed from a list844 * of LockHandle or Lockable arguments directly instead of getting845 * 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, bulk850 * AutoMultiWriteLockBase::leave() and AutoMultiWriteLockBase::enter()851 * operations are also available, that will leave and enter all managed852 * semaphores at once in the proper order (similarly to853 * 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 here865 * }866 * // both locks are released here867 * </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 D899 #undef C900 #undef B901 #undef A902 903 727 } /* namespace util */ 904 728
Note:
See TracChangeset
for help on using the changeset viewer.