Changeset 25285 in vbox for trunk/src/VBox/Main/AutoLock.cpp
- Timestamp:
- Dec 9, 2009 11:38:58 PM (15 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Main/AutoLock.cpp
r25284 r25285 96 96 97 97 typedef std::vector<LockHandle*> HandlesVector; 98 typedef std::vector<uint32_t> CountsVector; 98 99 99 100 struct AutoLockBase::Data 100 101 { 101 102 Data(size_t cHandles) 102 : aHandles(cHandles), // size of array 103 fIsLocked(false), 104 cUnlockedInLeave(0) 105 { } 106 103 : fIsLocked(false), 104 aHandles(cHandles), // size of array 105 acUnlockedInLeave(cHandles) 106 { 107 for (uint32_t i = 0; i < cHandles; ++i) 108 { 109 acUnlockedInLeave[i] = 0; 110 aHandles[i] = NULL; 111 } 112 } 113 114 bool fIsLocked; // if true, then all items in aHandles are locked by this AutoLock and 115 // need to be unlocked in the destructor 107 116 HandlesVector aHandles; // array (vector) of LockHandle instances; in the case of AutoWriteLock 108 117 // and AutoReadLock, there will only be one item on the list; with the 109 118 // 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 112 uint32_t cUnlockedInLeave; // how many times the handle was unlocked in leave(); otherwise 0 119 CountsVector acUnlockedInLeave; // for each lock handle, how many times the handle was unlocked in leave(); otherwise 0 113 120 }; 114 121 115 AutoLockBase::AutoLockBase(LockHandle *pHandle) 116 { 122 AutoLockBase::AutoLockBase(uint32_t cHandles) 123 { 124 m = new Data(cHandles); 125 } 126 127 AutoLockBase::AutoLockBase(uint32_t cHandles, LockHandle *pHandle) 128 { 129 Assert(cHandles == 1); 117 130 m = new Data(1); 118 131 m->aHandles[0] = pHandle; … … 176 189 void AutoLockBase::cleanup() 177 190 { 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) 191 bool fAnyUnlockedInLeave = false; 192 193 uint32_t i = 0; 194 for (HandlesVector::iterator it = m->aHandles.begin(); 195 it != m->aHandles.end(); 196 ++it) 197 { 198 LockHandle *pHandle = *it; 199 if (pHandle) 200 { 201 if (m->acUnlockedInLeave[i]) 202 { 203 // there was a leave() before the destruction: then restore the 204 // lock level that might have been set by locks other than our own 205 if (m->fIsLocked) 206 { 207 --m->acUnlockedInLeave[i]; 208 fAnyUnlockedInLeave = true; 209 } 210 for (; m->acUnlockedInLeave[i]; --m->acUnlockedInLeave[i]) 211 callLockImpl(*pHandle); 212 } 213 } 214 ++i; 215 } 216 217 if (m->fIsLocked && !fAnyUnlockedInLeave) 190 218 callUnlockOnAllHandles(); 191 219 } … … 286 314 { 287 315 l.unlockWrite(); 288 }289 290 /**291 * Returns @c true if the current thread holds a write lock on the managed292 * read/write semaphore. Returns @c false if the managed semaphore is @c293 * NULL.294 *295 * @note Intended for debugging only.296 */297 bool AutoWriteLockBase::isWriteLockOnCurrentThread() const298 {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 lock304 * level determines the number of nested #lock() calls on the given305 * semaphore handle. Returns @c 0 if the managed semaphore is @c306 * NULL.307 *308 * Note that this call is valid only when the current thread owns a write309 * lock on the given semaphore handle and will assert otherwise.310 *311 * @note Intended for debugging only.312 */313 uint32_t AutoWriteLockBase::writeLockLevel() const314 {315 return m->aHandles[0] ? m->aHandles[0]->writeLockLevel() : 0;316 316 } 317 317 … … 340 340 { 341 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 342 343 uint32_t i = 0; 344 344 for (HandlesVector::iterator it = m->aHandles.begin(); 345 345 it != m->aHandles.end(); … … 349 349 if (pHandle) 350 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; 351 AssertMsg(m->acUnlockedInLeave[i] == 0, ("m->cUnlockedInLeave[%d] is %d, must be 0! Called leave() twice?", i, m->acUnlockedInLeave[i])); 352 m->acUnlockedInLeave[i] = pHandle->writeLockLevel(); 353 AssertMsg(m->acUnlockedInLeave[i] >= 1, ("m->cUnlockedInLeave[%d] is %d, must be >=1!", i, m->acUnlockedInLeave[i])); 354 355 for (uint32_t left = m->acUnlockedInLeave[i]; 355 356 left; 356 357 --left) 357 358 pHandle->unlockWrite(); 358 359 } 360 ++i; 359 361 } 360 362 } … … 369 371 { 370 372 AssertMsg(m->fIsLocked, ("m->fIsLocked is false, cannot enter()!")); 371 AssertMsg(m->cUnlockedInLeave != 0, ("m->cUnlockedInLeave is 0! enter() without leave()?")); 372 373 374 uint32_t i = 0; 373 375 for (HandlesVector::iterator it = m->aHandles.begin(); 374 376 it != m->aHandles.end(); … … 378 380 if (pHandle) 379 381 { 380 for (; m->cUnlockedInLeave; --m->cUnlockedInLeave) 382 AssertMsg(m->acUnlockedInLeave[i] != 0, ("m->cUnlockedInLeave[%d] is 0! enter() without leave()?", i)); 383 384 for (; m->acUnlockedInLeave[i]; --m->acUnlockedInLeave[i]) 381 385 pHandle->lockWrite(); 382 386 } 387 ++i; 388 } 389 } 390 391 /** 392 * Same as #leave() but checks if the current thread actally owns the lock 393 * and only proceeds in this case. As a result, as opposed to #leave(), 394 * doesn't assert when called with no lock being held. 395 */ 396 void AutoWriteLockBase::maybeLeave() 397 { 398 uint32_t i = 0; 399 for (HandlesVector::iterator it = m->aHandles.begin(); 400 it != m->aHandles.end(); 401 ++it) 402 { 403 LockHandle *pHandle = *it; 404 if (pHandle) 405 { 406 if (pHandle->isWriteLockOnCurrentThread()) 407 { 408 m->acUnlockedInLeave[i] = pHandle->writeLockLevel(); 409 AssertMsg(m->acUnlockedInLeave[i] >= 1, ("m->cUnlockedInLeave[%d] is %d, must be >=1!", i, m->acUnlockedInLeave[i])); 410 411 for (uint32_t left = m->acUnlockedInLeave[i]; 412 left; 413 --left) 414 pHandle->unlockWrite(); 415 } 416 } 417 ++i; 418 } 419 } 420 421 /** 422 * Same as #enter() but checks if the current thread actally owns the lock 423 * and only proceeds if not. As a result, as opposed to #enter(), doesn't 424 * assert when called with the lock already being held. 425 */ 426 void AutoWriteLockBase::maybeEnter() 427 { 428 uint32_t i = 0; 429 for (HandlesVector::iterator it = m->aHandles.begin(); 430 it != m->aHandles.end(); 431 ++it) 432 { 433 LockHandle *pHandle = *it; 434 if (pHandle) 435 { 436 if (!pHandle->isWriteLockOnCurrentThread()) 437 { 438 for (; m->acUnlockedInLeave[i]; --m->acUnlockedInLeave[i]) 439 pHandle->lockWrite(); 440 } 441 } 442 ++i; 383 443 } 384 444 } … … 425 485 } 426 486 487 /** 488 * Returns @c true if the current thread holds a write lock on the managed 489 * read/write semaphore. Returns @c false if the managed semaphore is @c 490 * NULL. 491 * 492 * @note Intended for debugging only. 493 */ 494 bool AutoWriteLock::isWriteLockOnCurrentThread() const 495 { 496 return m->aHandles[0] ? m->aHandles[0]->isWriteLockOnCurrentThread() : false; 497 } 498 499 /** 500 * Returns the current write lock level of the managed smaphore. The lock 501 * level determines the number of nested #lock() calls on the given 502 * semaphore handle. Returns @c 0 if the managed semaphore is @c 503 * NULL. 504 * 505 * Note that this call is valid only when the current thread owns a write 506 * lock on the given semaphore handle and will assert otherwise. 507 * 508 * @note Intended for debugging only. 509 */ 510 uint32_t AutoWriteLock::writeLockLevel() const 511 { 512 return m->aHandles[0] ? m->aHandles[0]->writeLockLevel() : 0; 513 } 514 515 //////////////////////////////////////////////////////////////////////////////// 516 // 517 // AutoMultiWriteLock* 518 // 519 //////////////////////////////////////////////////////////////////////////////// 520 521 AutoMultiWriteLock2::AutoMultiWriteLock2(Lockable *pl1, Lockable *pl2) 522 : AutoWriteLockBase(2) 523 { 524 if (pl1) 525 m->aHandles[0] = pl1->lockHandle(); 526 if (pl2) 527 m->aHandles[1] = pl2->lockHandle(); 528 acquire(); 529 } 530 531 AutoMultiWriteLock2::AutoMultiWriteLock2(LockHandle *pl1, LockHandle *pl2) 532 : AutoWriteLockBase(2) 533 { 534 m->aHandles[0] = pl1; 535 m->aHandles[1] = pl2; 536 acquire(); 537 } 538 539 AutoMultiWriteLock3::AutoMultiWriteLock3(Lockable *pl1, Lockable *pl2, Lockable *pl3) 540 : AutoWriteLockBase(3) 541 { 542 if (pl1) 543 m->aHandles[0] = pl1->lockHandle(); 544 if (pl2) 545 m->aHandles[1] = pl2->lockHandle(); 546 if (pl3) 547 m->aHandles[2] = pl3->lockHandle(); 548 acquire(); 549 } 550 551 AutoMultiWriteLock3::AutoMultiWriteLock3(LockHandle *pl1, LockHandle *pl2, LockHandle *pl3) 552 : AutoWriteLockBase(3) 553 { 554 m->aHandles[0] = pl1; 555 m->aHandles[1] = pl2; 556 m->aHandles[2] = pl3; 557 acquire(); 558 } 559 427 560 } /* namespace util */ 428 561 /* vi: set tabstop=4 shiftwidth=4 expandtab: */
Note:
See TracChangeset
for help on using the changeset viewer.