- Timestamp:
- Dec 9, 2009 9:26:28 PM (15 years ago)
- Location:
- trunk/src/VBox/Main
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Main/AutoLock.cpp
r25283 r25284 214 214 //////////////////////////////////////////////////////////////////////////////// 215 215 // 216 // AutoWriteLock 216 // AutoReadLock 217 // 218 //////////////////////////////////////////////////////////////////////////////// 219 220 /** 221 * Release all read locks acquired by this instance through the #lock() 222 * call and destroys the instance. 223 * 224 * Note that if there there are nested #lock() calls without the 225 * corresponding number of #unlock() calls when the destructor is called, it 226 * will assert. This is because having an unbalanced number of nested locks 227 * is a program logic error which must be fixed. 228 */ 229 /*virtual*/ AutoReadLock::~AutoReadLock() 230 { 231 LockHandle *pHandle = m->aHandles[0]; 232 233 if (pHandle) 234 { 235 if (m->fIsLocked) 236 pHandle->unlockRead(); 237 } 238 } 239 240 /** 241 * Implementation of the pure virtual declared in AutoLockBase. 242 * This gets called by AutoLockBase.acquire() to actually request 243 * the semaphore; in the AutoReadLock implementation, we request 244 * the semaphore in read mode. 245 */ 246 /*virtual*/ void AutoReadLock::callLockImpl(LockHandle &l) 247 { 248 l.lockRead(); 249 } 250 251 /** 252 * Implementation of the pure virtual declared in AutoLockBase. 253 * This gets called by AutoLockBase.release() to actually release 254 * the semaphore; in the AutoReadLock implementation, we release 255 * the semaphore in read mode. 256 */ 257 /*virtual*/ void AutoReadLock::callUnlockImpl(LockHandle &l) 258 { 259 l.unlockRead(); 260 } 261 262 //////////////////////////////////////////////////////////////////////////////// 263 // 264 // AutoWriteLockBase 217 265 // 218 266 //////////////////////////////////////////////////////////////////////////////// … … 224 272 * the semaphore in write mode. 225 273 */ 226 /*virtual*/ void AutoWriteLock ::callLockImpl(LockHandle &l)274 /*virtual*/ void AutoWriteLockBase::callLockImpl(LockHandle &l) 227 275 { 228 276 l.lockWrite(); … … 235 283 * the semaphore in write mode. 236 284 */ 237 /*virtual*/ void AutoWriteLock ::callUnlockImpl(LockHandle &l)285 /*virtual*/ void AutoWriteLockBase::callUnlockImpl(LockHandle &l) 238 286 { 239 287 l.unlockWrite(); 288 } 289 290 /** 291 * Returns @c true if the current thread holds a write lock on the managed 292 * read/write semaphore. Returns @c false if the managed semaphore is @c 293 * NULL. 294 * 295 * @note Intended for debugging only. 296 */ 297 bool AutoWriteLockBase::isWriteLockOnCurrentThread() const 298 { 299 return m->aHandles[0] ? m->aHandles[0]->isWriteLockOnCurrentThread() : false; 300 } 301 302 /** 303 * Returns the current write lock level of the managed smaphore. The lock 304 * level determines the number of nested #lock() calls on the given 305 * semaphore handle. Returns @c 0 if the managed semaphore is @c 306 * NULL. 307 * 308 * Note that this call is valid only when the current thread owns a write 309 * lock on the given semaphore handle and will assert otherwise. 310 * 311 * @note Intended for debugging only. 312 */ 313 uint32_t AutoWriteLockBase::writeLockLevel() const 314 { 315 return m->aHandles[0] ? m->aHandles[0]->writeLockLevel() : 0; 240 316 } 241 317 … … 261 337 * write or a read lock is owned by some other thread by that time. 262 338 */ 263 void AutoWriteLock::leave() 264 { 265 LockHandle *pHandle = m->aHandles[0]; 266 267 if (pHandle) 268 { 269 AssertMsg(m->fIsLocked, ("m->fIsLocked is false, cannot leave()!")); 270 AssertMsg(m->cUnlockedInLeave == 0, ("m->cUnlockedInLeave is %d, must be 0! Called leave() twice?", m->cUnlockedInLeave)); 271 272 m->cUnlockedInLeave = pHandle->writeLockLevel(); 273 AssertMsg(m->cUnlockedInLeave >= 1, ("m->cUnlockedInLeave is %d, must be >=1!", m->cUnlockedInLeave)); 274 275 for (uint32_t left = m->cUnlockedInLeave; 276 left; 277 --left) 278 pHandle->unlockWrite(); 339 void AutoWriteLockBase::leave() 340 { 341 AssertMsg(m->fIsLocked, ("m->fIsLocked is false, cannot leave()!")); 342 AssertMsg(m->cUnlockedInLeave == 0, ("m->cUnlockedInLeave is %d, must be 0! Called leave() twice?", m->cUnlockedInLeave)); 343 344 for (HandlesVector::iterator it = m->aHandles.begin(); 345 it != m->aHandles.end(); 346 ++it) 347 { 348 LockHandle *pHandle = *it; 349 if (pHandle) 350 { 351 m->cUnlockedInLeave = pHandle->writeLockLevel(); 352 AssertMsg(m->cUnlockedInLeave >= 1, ("m->cUnlockedInLeave is %d, must be >=1!", m->cUnlockedInLeave)); 353 354 for (uint32_t left = m->cUnlockedInLeave; 355 left; 356 --left) 357 pHandle->unlockWrite(); 358 } 279 359 } 280 360 } … … 286 366 * between. 287 367 */ 288 void AutoWriteLock::enter() 289 { 290 LockHandle *pHandle = m->aHandles[0]; 291 292 if (pHandle) 293 { 294 AssertMsg(m->fIsLocked, ("m->fIsLocked is false, cannot enter()!")); 295 AssertMsg(m->cUnlockedInLeave != 0, ("m->cUnlockedInLeave is 0! enter() without leave()?")); 296 297 for (; m->cUnlockedInLeave; --m->cUnlockedInLeave) 298 pHandle->lockWrite(); 299 } 300 } 368 void AutoWriteLockBase::enter() 369 { 370 AssertMsg(m->fIsLocked, ("m->fIsLocked is false, cannot enter()!")); 371 AssertMsg(m->cUnlockedInLeave != 0, ("m->cUnlockedInLeave is 0! enter() without leave()?")); 372 373 for (HandlesVector::iterator it = m->aHandles.begin(); 374 it != m->aHandles.end(); 375 ++it) 376 { 377 LockHandle *pHandle = *it; 378 if (pHandle) 379 { 380 for (; m->cUnlockedInLeave; --m->cUnlockedInLeave) 381 pHandle->lockWrite(); 382 } 383 } 384 } 385 386 //////////////////////////////////////////////////////////////////////////////// 387 // 388 // AutoWriteLock 389 // 390 //////////////////////////////////////////////////////////////////////////////// 301 391 302 392 /** … … 335 425 } 336 426 337 /**338 * Returns @c true if the current thread holds a write lock on the managed339 * read/write semaphore. Returns @c false if the managed semaphore is @c340 * NULL.341 *342 * @note Intended for debugging only.343 */344 bool AutoWriteLock::isWriteLockOnCurrentThread() const345 {346 return m->aHandles[0] ? m->aHandles[0]->isWriteLockOnCurrentThread() : false;347 }348 349 /**350 * Returns the current write lock level of the managed smaphore. The lock351 * level determines the number of nested #lock() calls on the given352 * semaphore handle. Returns @c 0 if the managed semaphore is @c353 * NULL.354 *355 * Note that this call is valid only when the current thread owns a write356 * lock on the given semaphore handle and will assert otherwise.357 *358 * @note Intended for debugging only.359 */360 uint32_t AutoWriteLock::writeLockLevel() const361 {362 return m->aHandles[0] ? m->aHandles[0]->writeLockLevel() : 0;363 }364 365 ////////////////////////////////////////////////////////////////////////////////366 //367 // AutoReadLock368 //369 ////////////////////////////////////////////////////////////////////////////////370 371 /**372 * Release all read locks acquired by this instance through the #lock()373 * call and destroys the instance.374 *375 * Note that if there there are nested #lock() calls without the376 * corresponding number of #unlock() calls when the destructor is called, it377 * will assert. This is because having an unbalanced number of nested locks378 * is a program logic error which must be fixed.379 */380 /*virtual*/ AutoReadLock::~AutoReadLock()381 {382 LockHandle *pHandle = m->aHandles[0];383 384 if (pHandle)385 {386 if (m->fIsLocked)387 pHandle->unlockRead();388 }389 }390 391 /**392 * Implementation of the pure virtual declared in AutoLockBase.393 * This gets called by AutoLockBase.acquire() to actually request394 * the semaphore; in the AutoReadLock implementation, we request395 * the semaphore in read mode.396 */397 /*virtual*/ void AutoReadLock::callLockImpl(LockHandle &l)398 {399 l.lockRead();400 }401 402 /**403 * Implementation of the pure virtual declared in AutoLockBase.404 * This gets called by AutoLockBase.release() to actually release405 * the semaphore; in the AutoReadLock implementation, we release406 * the semaphore in read mode.407 */408 /*virtual*/ void AutoReadLock::callUnlockImpl(LockHandle &l)409 {410 l.unlockRead();411 }412 413 427 } /* namespace util */ 414 428 /* vi: set tabstop=4 shiftwidth=4 expandtab: */ -
trunk/src/VBox/Main/include/AutoLock.h
r25283 r25284 153 153 DECLARE_CLS_COPY_CTOR_ASSIGN_NOOP (LockHandle) 154 154 155 friend class AutoWriteLockBase; 155 156 friend class AutoWriteLock; 156 157 friend class AutoReadLock; … … 343 344 //////////////////////////////////////////////////////////////////////////////// 344 345 // 345 // Auto WriteLock346 // 347 //////////////////////////////////////////////////////////////////////////////// 348 349 class Auto WriteLock : public AutoLockBase346 // AutoReadLock 347 // 348 //////////////////////////////////////////////////////////////////////////////// 349 350 class AutoReadLock : public AutoLockBase 350 351 { 351 352 public: … … 359 360 * runtime. 360 361 */ 361 Auto WriteLock()362 AutoReadLock() 362 363 : AutoLockBase(NULL) 363 364 { } … … 365 366 /** 366 367 * Constructs a new instance that will start managing the given read/write 367 * semaphore by requesting a writelock.368 */ 369 Auto WriteLock(LockHandle *aHandle)368 * semaphore by requesting a read lock. 369 */ 370 AutoReadLock(LockHandle *aHandle) 370 371 : AutoLockBase(aHandle) 371 372 { 372 373 acquire(); 373 374 } 375 376 /** 377 * Constructs a new instance that will start managing the given read/write 378 * semaphore by requesting a read lock. 379 */ 380 AutoReadLock(LockHandle &aHandle) 381 : AutoLockBase(&aHandle) 382 { 383 acquire(); 384 } 385 386 /** 387 * Constructs a new instance that will start managing the given read/write 388 * semaphore by requesting a read lock. 389 */ 390 AutoReadLock(const Lockable &aLockable) 391 : AutoLockBase(aLockable.lockHandle()) 392 { 393 acquire(); 394 } 395 396 /** 397 * Constructs a new instance that will start managing the given read/write 398 * semaphore by requesting a read lock. 399 */ 400 AutoReadLock(const Lockable *aLockable) 401 : AutoLockBase(aLockable ? aLockable->lockHandle() : NULL) 402 { 403 acquire(); 404 } 405 406 virtual ~AutoReadLock(); 407 408 virtual void callLockImpl(LockHandle &l); 409 virtual void callUnlockImpl(LockHandle &l); 410 }; 411 412 //////////////////////////////////////////////////////////////////////////////// 413 // 414 // AutoWriteLockBase 415 // 416 //////////////////////////////////////////////////////////////////////////////// 417 418 class AutoWriteLockBase : public AutoLockBase 419 { 420 protected: 421 AutoWriteLockBase(LockHandle *pHandle) 422 : AutoLockBase(pHandle) 423 { } 424 425 virtual ~AutoWriteLockBase() 426 { } 427 428 virtual void callLockImpl(LockHandle &l); 429 virtual void callUnlockImpl(LockHandle &l); 430 431 public: 432 bool isWriteLockOnCurrentThread() const; 433 uint32_t writeLockLevel() const; 434 435 void leave(); 436 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 460 }; 461 462 //////////////////////////////////////////////////////////////////////////////// 463 // 464 // AutoWriteLock 465 // 466 //////////////////////////////////////////////////////////////////////////////// 467 468 class AutoWriteLock : public AutoWriteLockBase 469 { 470 public: 471 472 /** 473 * Constructs a null instance that does not manage any read/write 474 * semaphore. 475 * 476 * Note that all method calls on a null instance are no-ops. This allows to 477 * have the code where lock protection can be selected (or omitted) at 478 * runtime. 479 */ 480 AutoWriteLock() 481 : AutoWriteLockBase(NULL) 482 { } 374 483 375 484 /** … … 377 486 * semaphore by requesting a write lock. 378 487 */ 379 AutoWriteLock(LockHandle &aHandle)380 : Auto LockBase(&aHandle)488 AutoWriteLock(LockHandle *aHandle) 489 : AutoWriteLockBase(aHandle) 381 490 { 382 491 acquire(); … … 387 496 * semaphore by requesting a write lock. 388 497 */ 389 AutoWriteLock( const Lockable &aLockable)390 : Auto LockBase(aLockable.lockHandle())498 AutoWriteLock(LockHandle &aHandle) 499 : AutoWriteLockBase(&aHandle) 391 500 { 392 501 acquire(); … … 397 506 * semaphore by requesting a write lock. 398 507 */ 508 AutoWriteLock(const Lockable &aLockable) 509 : AutoWriteLockBase(aLockable.lockHandle()) 510 { 511 acquire(); 512 } 513 514 /** 515 * Constructs a new instance that will start managing the given read/write 516 * semaphore by requesting a write lock. 517 */ 399 518 AutoWriteLock(const Lockable *aLockable) 400 : Auto LockBase(aLockable ? aLockable->lockHandle() : NULL)519 : AutoWriteLockBase(aLockable ? aLockable->lockHandle() : NULL) 401 520 { 402 521 acquire(); … … 417 536 } 418 537 419 virtual void callLockImpl(LockHandle &l);420 virtual void callUnlockImpl(LockHandle &l);421 422 void leave();423 void enter();424 425 /**426 * Same as #leave() but checks if the current thread actally owns the lock427 * and only proceeds in this case. As a result, as opposed to #leave(),428 * doesn't assert when called with no lock being held.429 */430 void maybeLeave()431 {432 if (isWriteLockOnCurrentThread())433 leave();434 }435 436 /**437 * Same as #enter() but checks if the current thread actally owns the lock438 * and only proceeds if not. As a result, as opposed to #enter(), doesn't439 * assert when called with the lock already being held.440 */441 void maybeEnter()442 {443 if (!isWriteLockOnCurrentThread())444 enter();445 }446 447 538 void attach(LockHandle *aHandle); 448 539 … … 466 557 467 558 void attachRaw(LockHandle *ph); 468 469 bool isWriteLockOnCurrentThread() const;470 uint32_t writeLockLevel() const;471 };472 473 ////////////////////////////////////////////////////////////////////////////////474 //475 // AutoReadLock476 //477 ////////////////////////////////////////////////////////////////////////////////478 479 class AutoReadLock : public AutoLockBase480 {481 public:482 483 /**484 * Constructs a null instance that does not manage any read/write485 * semaphore.486 *487 * Note that all method calls on a null instance are no-ops. This allows to488 * have the code where lock protection can be selected (or omitted) at489 * runtime.490 */491 AutoReadLock()492 : AutoLockBase(NULL)493 { }494 495 /**496 * Constructs a new instance that will start managing the given read/write497 * semaphore by requesting a read lock.498 */499 AutoReadLock(LockHandle *aHandle)500 : AutoLockBase(aHandle)501 {502 acquire();503 }504 505 /**506 * Constructs a new instance that will start managing the given read/write507 * semaphore by requesting a read lock.508 */509 AutoReadLock(LockHandle &aHandle)510 : AutoLockBase(&aHandle)511 {512 acquire();513 }514 515 /**516 * Constructs a new instance that will start managing the given read/write517 * semaphore by requesting a read lock.518 */519 AutoReadLock(const Lockable &aLockable)520 : AutoLockBase(aLockable.lockHandle())521 {522 acquire();523 }524 525 /**526 * Constructs a new instance that will start managing the given read/write527 * semaphore by requesting a read lock.528 */529 AutoReadLock(const Lockable *aLockable)530 : AutoLockBase(aLockable ? aLockable->lockHandle() : NULL)531 {532 acquire();533 }534 535 virtual ~AutoReadLock();536 537 virtual void callLockImpl(LockHandle &l);538 virtual void callUnlockImpl(LockHandle &l);539 559 }; 540 560
Note:
See TracChangeset
for help on using the changeset viewer.