VirtualBox

source: vbox/trunk/src/VBox/Main/glue/AutoLock.cpp@ 95353

Last change on this file since 95353 was 93115, checked in by vboxsync, 3 years ago

scm --update-copyright-year

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 22.6 KB
Line 
1/* $Id: AutoLock.cpp 93115 2022-01-01 11:31:46Z vboxsync $ */
2/** @file
3 * Automatic locks, implementation.
4 */
5
6/*
7 * Copyright (C) 2006-2022 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18
19/*********************************************************************************************************************************
20* Defined Constants And Macros *
21*********************************************************************************************************************************/
22#define GLUE_USE_CRITSECTRW
23
24
25/*********************************************************************************************************************************
26* Header Files *
27*********************************************************************************************************************************/
28#include <iprt/cdefs.h>
29#include <iprt/critsect.h>
30#include <iprt/thread.h>
31#include <iprt/semaphore.h>
32
33#include <iprt/errcore.h>
34#include <iprt/assert.h>
35
36#if defined(RT_LOCK_STRICT)
37# include <iprt/asm.h> // for ASMReturnAddress
38#endif
39
40#include <iprt/string.h>
41#include <iprt/path.h>
42#include <iprt/stream.h>
43
44#include "VBox/com/AutoLock.h"
45#include <VBox/com/string.h>
46
47#include <vector>
48#include <list>
49#include <map>
50
51
52namespace util
53{
54
55////////////////////////////////////////////////////////////////////////////////
56//
57// RuntimeLockClass
58//
59////////////////////////////////////////////////////////////////////////////////
60
61#ifdef VBOX_WITH_MAIN_LOCK_VALIDATION
62typedef std::map<VBoxLockingClass, RTLOCKVALCLASS> LockValidationClassesMap;
63LockValidationClassesMap g_mapLockValidationClasses;
64#endif
65
66/**
67 * Called from initterm.cpp on process initialization (on the main thread)
68 * to give us a chance to initialize lock validation runtime data.
69 */
70void InitAutoLockSystem()
71{
72#ifdef VBOX_WITH_MAIN_LOCK_VALIDATION
73 struct
74 {
75 VBoxLockingClass cls;
76 const char *pcszDescription;
77 } aClasses[] =
78 {
79 { LOCKCLASS_VIRTUALBOXOBJECT, "2-VIRTUALBOXOBJECT" },
80 { LOCKCLASS_HOSTOBJECT, "3-HOSTOBJECT" },
81 { LOCKCLASS_LISTOFMACHINES, "4-LISTOFMACHINES" },
82 { LOCKCLASS_MACHINEOBJECT, "5-MACHINEOBJECT" },
83 { LOCKCLASS_SNAPSHOTOBJECT, "6-SNAPSHOTOBJECT" },
84 { LOCKCLASS_MEDIUMQUERY, "7-MEDIUMQUERY" },
85 { LOCKCLASS_LISTOFMEDIA, "8-LISTOFMEDIA" },
86 { LOCKCLASS_LISTOFOTHEROBJECTS, "9-LISTOFOTHEROBJECTS" },
87 { LOCKCLASS_OTHEROBJECT, "10-OTHEROBJECT" },
88 { LOCKCLASS_PROGRESSLIST, "11-PROGRESSLIST" },
89 { LOCKCLASS_OBJECTSTATE, "12-OBJECTSTATE" },
90 { LOCKCLASS_TRANSLATOR, "13-TRANSLATOR" }
91 };
92
93 RTLOCKVALCLASS hClass;
94 int vrc;
95 for (unsigned i = 0; i < RT_ELEMENTS(aClasses); ++i)
96 {
97 vrc = RTLockValidatorClassCreate(&hClass,
98 true, /*fAutodidact*/
99 RT_SRC_POS,
100 aClasses[i].pcszDescription);
101 AssertRC(vrc);
102
103 // teach the new class that the classes created previously can be held
104 // while the new class is being acquired
105 for (LockValidationClassesMap::iterator it = g_mapLockValidationClasses.begin();
106 it != g_mapLockValidationClasses.end();
107 ++it)
108 {
109 RTLOCKVALCLASS &canBeHeld = it->second;
110 vrc = RTLockValidatorClassAddPriorClass(hClass,
111 canBeHeld);
112 AssertRC(vrc);
113 }
114
115 // and store the new class
116 g_mapLockValidationClasses[aClasses[i].cls] = hClass;
117 }
118
119/* WriteLockHandle critsect1(LOCKCLASS_VIRTUALBOXOBJECT);
120 WriteLockHandle critsect2(LOCKCLASS_VIRTUALBOXLIST);
121
122 AutoWriteLock lock1(critsect1 COMMA_LOCKVAL_SRC_POS);
123 AutoWriteLock lock2(critsect2 COMMA_LOCKVAL_SRC_POS);*/
124#endif
125}
126
127bool AutoLockHoldsLocksInClass(VBoxLockingClass lockClass)
128{
129#ifdef VBOX_WITH_MAIN_LOCK_VALIDATION
130 return RTLockValidatorHoldsLocksInClass(NIL_RTTHREAD, g_mapLockValidationClasses[lockClass]);
131#else
132 RT_NOREF(lockClass);
133 return false;
134#endif
135}
136
137////////////////////////////////////////////////////////////////////////////////
138//
139// RWLockHandle
140//
141////////////////////////////////////////////////////////////////////////////////
142
143struct RWLockHandle::Data
144{
145 Data()
146 { }
147
148#ifdef GLUE_USE_CRITSECTRW
149 mutable RTCRITSECTRW CritSect;
150#else
151 RTSEMRW sem;
152#endif
153 VBoxLockingClass lockClass;
154
155#ifdef VBOX_WITH_MAIN_LOCK_VALIDATION
156 com::Utf8Str strDescription;
157#endif
158};
159
160RWLockHandle::RWLockHandle(VBoxLockingClass lockClass)
161{
162 m = new Data();
163
164 m->lockClass = lockClass;
165#ifdef VBOX_WITH_MAIN_LOCK_VALIDATION
166 m->strDescription = com::Utf8StrFmt("r/w %RCv", this);
167#endif
168
169#ifdef GLUE_USE_CRITSECTRW
170# ifdef VBOX_WITH_MAIN_LOCK_VALIDATION
171 int vrc = RTCritSectRwInitEx(&m->CritSect, 0 /*fFlags*/, g_mapLockValidationClasses[lockClass], RTLOCKVAL_SUB_CLASS_ANY, NULL);
172# else
173 int vrc = RTCritSectRwInitEx(&m->CritSect, 0 /*fFlags*/, NIL_RTLOCKVALCLASS, RTLOCKVAL_SUB_CLASS_ANY, NULL);
174# endif
175#else
176# ifdef VBOX_WITH_MAIN_LOCK_VALIDATION
177 int vrc = RTSemRWCreateEx(&m->sem, 0 /*fFlags*/, g_mapLockValidationClasses[lockClass], RTLOCKVAL_SUB_CLASS_ANY, NULL);
178# else
179 int vrc = RTSemRWCreateEx(&m->sem, 0 /*fFlags*/, NIL_RTLOCKVALCLASS, RTLOCKVAL_SUB_CLASS_ANY, NULL);
180# endif
181#endif
182 AssertRC(vrc);
183}
184
185/*virtual*/ RWLockHandle::~RWLockHandle()
186{
187#ifdef GLUE_USE_CRITSECTRW
188 RTCritSectRwDelete(&m->CritSect);
189#else
190 RTSemRWDestroy(m->sem);
191#endif
192 delete m;
193}
194
195/*virtual*/ bool RWLockHandle::isWriteLockOnCurrentThread() const
196{
197#ifdef GLUE_USE_CRITSECTRW
198 return RTCritSectRwIsWriteOwner(&m->CritSect);
199#else
200 return RTSemRWIsWriteOwner(m->sem);
201#endif
202}
203
204/*virtual*/ void RWLockHandle::lockWrite(LOCKVAL_SRC_POS_DECL)
205{
206#ifdef GLUE_USE_CRITSECTRW
207# ifdef VBOX_WITH_MAIN_LOCK_VALIDATION
208 int vrc = RTCritSectRwEnterExclDebug(&m->CritSect, (uintptr_t)ASMReturnAddress(), RT_SRC_POS_ARGS);
209# else
210 int vrc = RTCritSectRwEnterExcl(&m->CritSect);
211# endif
212#else
213# ifdef VBOX_WITH_MAIN_LOCK_VALIDATION
214 int vrc = RTSemRWRequestWriteDebug(m->sem, RT_INDEFINITE_WAIT, (uintptr_t)ASMReturnAddress(), RT_SRC_POS_ARGS);
215# else
216 int vrc = RTSemRWRequestWrite(m->sem, RT_INDEFINITE_WAIT);
217# endif
218#endif
219 AssertRC(vrc);
220}
221
222/*virtual*/ void RWLockHandle::unlockWrite()
223{
224#ifdef GLUE_USE_CRITSECTRW
225 int vrc = RTCritSectRwLeaveExcl(&m->CritSect);
226#else
227 int vrc = RTSemRWReleaseWrite(m->sem);
228#endif
229 AssertRC(vrc);
230
231}
232
233/*virtual*/ bool RWLockHandle::isReadLockedOnCurrentThread(bool fWannaHear) const
234{
235#ifdef GLUE_USE_CRITSECTRW
236 return RTCritSectRwIsReadOwner(&m->CritSect, fWannaHear);
237#else
238 return RTSemRWIsReadOwner(m->sem, fWannaHear);
239#endif
240}
241
242/*virtual*/ void RWLockHandle::lockRead(LOCKVAL_SRC_POS_DECL)
243{
244#ifdef GLUE_USE_CRITSECTRW
245# ifdef VBOX_WITH_MAIN_LOCK_VALIDATION
246 int vrc = RTCritSectRwEnterSharedDebug(&m->CritSect, (uintptr_t)ASMReturnAddress(), RT_SRC_POS_ARGS);
247# else
248 int vrc = RTCritSectRwEnterShared(&m->CritSect);
249# endif
250#else
251# ifdef VBOX_WITH_MAIN_LOCK_VALIDATION
252 int vrc = RTSemRWRequestReadDebug(m->sem, RT_INDEFINITE_WAIT, (uintptr_t)ASMReturnAddress(), RT_SRC_POS_ARGS);
253# else
254 int vrc = RTSemRWRequestRead(m->sem, RT_INDEFINITE_WAIT);
255# endif
256#endif
257 AssertRC(vrc);
258}
259
260/*virtual*/ void RWLockHandle::unlockRead()
261{
262#ifdef GLUE_USE_CRITSECTRW
263 int vrc = RTCritSectRwLeaveShared(&m->CritSect);
264#else
265 int vrc = RTSemRWReleaseRead(m->sem);
266#endif
267 AssertRC(vrc);
268}
269
270/*virtual*/ uint32_t RWLockHandle::writeLockLevel() const
271{
272 /* Note! This does not include read recursions done by the writer! */
273#ifdef GLUE_USE_CRITSECTRW
274 return RTCritSectRwGetWriteRecursion(&m->CritSect);
275#else
276 return RTSemRWGetWriteRecursion(m->sem);
277#endif
278}
279
280#ifdef VBOX_WITH_MAIN_LOCK_VALIDATION
281/*virtual*/ const char* RWLockHandle::describe() const
282{
283 return m->strDescription.c_str();
284}
285#endif
286
287////////////////////////////////////////////////////////////////////////////////
288//
289// WriteLockHandle
290//
291////////////////////////////////////////////////////////////////////////////////
292
293struct WriteLockHandle::Data
294{
295 Data()
296 { }
297
298 mutable RTCRITSECT sem;
299 VBoxLockingClass lockClass;
300
301#ifdef VBOX_WITH_MAIN_LOCK_VALIDATION
302 com::Utf8Str strDescription;
303#endif
304};
305
306WriteLockHandle::WriteLockHandle(VBoxLockingClass lockClass)
307{
308 m = new Data;
309
310 m->lockClass = lockClass;
311
312#ifdef VBOX_WITH_MAIN_LOCK_VALIDATION
313 m->strDescription = com::Utf8StrFmt("crit %RCv", this);
314 int vrc = RTCritSectInitEx(&m->sem, 0/*fFlags*/, g_mapLockValidationClasses[lockClass], RTLOCKVAL_SUB_CLASS_ANY, NULL);
315#else
316 int vrc = RTCritSectInitEx(&m->sem, 0/*fFlags*/, NIL_RTLOCKVALCLASS, RTLOCKVAL_SUB_CLASS_ANY, NULL);
317#endif
318 AssertRC(vrc);
319}
320
321WriteLockHandle::~WriteLockHandle()
322{
323 RTCritSectDelete(&m->sem);
324 delete m;
325}
326
327/*virtual*/ bool WriteLockHandle::isWriteLockOnCurrentThread() const
328{
329 return RTCritSectIsOwner(&m->sem);
330}
331
332/*virtual*/ void WriteLockHandle::lockWrite(LOCKVAL_SRC_POS_DECL)
333{
334#ifdef VBOX_WITH_MAIN_LOCK_VALIDATION
335 RTCritSectEnterDebug(&m->sem, (uintptr_t)ASMReturnAddress(), RT_SRC_POS_ARGS);
336#else
337 RTCritSectEnter(&m->sem);
338#endif
339}
340
341/*virtual*/ bool WriteLockHandle::isReadLockedOnCurrentThread(bool fWannaHear) const
342{
343 RT_NOREF(fWannaHear);
344 return RTCritSectIsOwner(&m->sem);
345}
346
347/*virtual*/ void WriteLockHandle::unlockWrite()
348{
349 RTCritSectLeave(&m->sem);
350}
351
352/*virtual*/ void WriteLockHandle::lockRead(LOCKVAL_SRC_POS_DECL)
353{
354 lockWrite(LOCKVAL_SRC_POS_ARGS);
355}
356
357/*virtual*/ void WriteLockHandle::unlockRead()
358{
359 unlockWrite();
360}
361
362/*virtual*/ uint32_t WriteLockHandle::writeLockLevel() const
363{
364 return RTCritSectGetRecursion(&m->sem);
365}
366
367#ifdef VBOX_WITH_MAIN_LOCK_VALIDATION
368/*virtual*/ const char* WriteLockHandle::describe() const
369{
370 return m->strDescription.c_str();
371}
372#endif
373
374////////////////////////////////////////////////////////////////////////////////
375//
376// AutoLockBase
377//
378////////////////////////////////////////////////////////////////////////////////
379
380typedef std::vector<LockHandle*> HandlesVector;
381
382struct AutoLockBase::Data
383{
384 Data(size_t cHandles
385#ifdef VBOX_WITH_MAIN_LOCK_VALIDATION
386 , const char *pcszFile_,
387 unsigned uLine_,
388 const char *pcszFunction_
389#endif
390 )
391 : fIsLocked(false),
392 aHandles(cHandles) // size of array
393#ifdef VBOX_WITH_MAIN_LOCK_VALIDATION
394 , pcszFile(pcszFile_),
395 uLine(uLine_),
396 pcszFunction(pcszFunction_)
397#endif
398 {
399 for (uint32_t i = 0; i < cHandles; ++i)
400 aHandles[i] = NULL;
401 }
402
403 bool fIsLocked; // if true, then all items in aHandles are locked by this AutoLock and
404 // need to be unlocked in the destructor
405 HandlesVector aHandles; // array (vector) of LockHandle instances; in the case of AutoWriteLock
406 // and AutoReadLock, there will only be one item on the list; with the
407 // AutoMulti* derivatives, there will be multiple
408
409#ifdef VBOX_WITH_MAIN_LOCK_VALIDATION
410 // information about where the lock occurred (passed down from the AutoLock classes)
411 const char *pcszFile;
412 unsigned uLine;
413 const char *pcszFunction;
414#endif
415};
416
417AutoLockBase::AutoLockBase(uint32_t cHandles
418 COMMA_LOCKVAL_SRC_POS_DECL)
419{
420 m = new Data(cHandles COMMA_LOCKVAL_SRC_POS_ARGS);
421}
422
423AutoLockBase::AutoLockBase(uint32_t cHandles,
424 LockHandle *pHandle
425 COMMA_LOCKVAL_SRC_POS_DECL)
426{
427 Assert(cHandles == 1); NOREF(cHandles);
428 m = new Data(1 COMMA_LOCKVAL_SRC_POS_ARGS);
429 m->aHandles[0] = pHandle;
430}
431
432AutoLockBase::~AutoLockBase()
433{
434 delete m;
435}
436
437/**
438 * Requests ownership of all contained lock handles by calling
439 * the pure virtual callLockImpl() function on each of them,
440 * which must be implemented by the descendant class; in the
441 * implementation, AutoWriteLock will request a write lock
442 * whereas AutoReadLock will request a read lock.
443 *
444 * Does *not* modify the lock counts in the member variables.
445 */
446void AutoLockBase::callLockOnAllHandles()
447{
448 for (HandlesVector::iterator it = m->aHandles.begin();
449 it != m->aHandles.end();
450 ++it)
451 {
452 LockHandle *pHandle = *it;
453 if (pHandle)
454 // call virtual function implemented in AutoWriteLock or AutoReadLock
455 this->callLockImpl(*pHandle);
456 }
457}
458
459/**
460 * Releases ownership of all contained lock handles by calling
461 * the pure virtual callUnlockImpl() function on each of them,
462 * which must be implemented by the descendant class; in the
463 * implementation, AutoWriteLock will release a write lock
464 * whereas AutoReadLock will release a read lock.
465 *
466 * Does *not* modify the lock counts in the member variables.
467 */
468void AutoLockBase::callUnlockOnAllHandles()
469{
470 // unlock in reverse order!
471 for (HandlesVector::reverse_iterator it = m->aHandles.rbegin();
472 it != m->aHandles.rend();
473 ++it)
474 {
475 LockHandle *pHandle = *it;
476 if (pHandle)
477 // call virtual function implemented in AutoWriteLock or AutoReadLock
478 this->callUnlockImpl(*pHandle);
479 }
480}
481
482/**
483 * Destructor implementation that can also be called explicitly, if required.
484 * Restores the exact state before the AutoLock was created; that is, unlocks
485 * all contained semaphores.
486 */
487void AutoLockBase::cleanup()
488{
489 if (m->fIsLocked)
490 callUnlockOnAllHandles();
491}
492
493/**
494 * Requests ownership of all contained semaphores. Public method that can
495 * only be called once and that also gets called by the AutoLock constructors.
496 */
497void AutoLockBase::acquire()
498{
499 AssertMsgReturnVoid(!m->fIsLocked, ("m->fIsLocked is true, attempting to lock twice!"));
500 callLockOnAllHandles();
501 m->fIsLocked = true;
502}
503
504/**
505 * Releases ownership of all contained semaphores. Public method.
506 */
507void AutoLockBase::release()
508{
509 AssertMsgReturnVoid(m->fIsLocked, ("m->fIsLocked is false, cannot release!"));
510 callUnlockOnAllHandles();
511 m->fIsLocked = false;
512}
513
514////////////////////////////////////////////////////////////////////////////////
515//
516// AutoReadLock
517//
518////////////////////////////////////////////////////////////////////////////////
519
520/**
521 * Release all read locks acquired by this instance through the #lock()
522 * call and destroys the instance.
523 *
524 * Note that if there there are nested #lock() calls without the
525 * corresponding number of #unlock() calls when the destructor is called, it
526 * will assert. This is because having an unbalanced number of nested locks
527 * is a program logic error which must be fixed.
528 */
529/*virtual*/ AutoReadLock::~AutoReadLock()
530{
531 LockHandle *pHandle = m->aHandles[0];
532
533 if (pHandle)
534 {
535 if (m->fIsLocked)
536 callUnlockImpl(*pHandle);
537 }
538}
539
540/**
541 * Implementation of the pure virtual declared in AutoLockBase.
542 * This gets called by AutoLockBase.acquire() to actually request
543 * the semaphore; in the AutoReadLock implementation, we request
544 * the semaphore in read mode.
545 */
546/*virtual*/ void AutoReadLock::callLockImpl(LockHandle &l)
547{
548#ifdef VBOX_WITH_MAIN_LOCK_VALIDATION
549 l.lockRead(m->pcszFile, m->uLine, m->pcszFunction);
550#else
551 l.lockRead();
552#endif
553}
554
555/**
556 * Implementation of the pure virtual declared in AutoLockBase.
557 * This gets called by AutoLockBase.release() to actually release
558 * the semaphore; in the AutoReadLock implementation, we release
559 * the semaphore in read mode.
560 */
561/*virtual*/ void AutoReadLock::callUnlockImpl(LockHandle &l)
562{
563 l.unlockRead();
564}
565
566////////////////////////////////////////////////////////////////////////////////
567//
568// AutoWriteLockBase
569//
570////////////////////////////////////////////////////////////////////////////////
571
572/**
573 * Implementation of the pure virtual declared in AutoLockBase.
574 * This gets called by AutoLockBase.acquire() to actually request
575 * the semaphore; in the AutoWriteLock implementation, we request
576 * the semaphore in write mode.
577 */
578/*virtual*/ void AutoWriteLockBase::callLockImpl(LockHandle &l)
579{
580#ifdef VBOX_WITH_MAIN_LOCK_VALIDATION
581 l.lockWrite(m->pcszFile, m->uLine, m->pcszFunction);
582#else
583 l.lockWrite();
584#endif
585}
586
587/**
588 * Implementation of the pure virtual declared in AutoLockBase.
589 * This gets called by AutoLockBase.release() to actually release
590 * the semaphore; in the AutoWriteLock implementation, we release
591 * the semaphore in write mode.
592 */
593/*virtual*/ void AutoWriteLockBase::callUnlockImpl(LockHandle &l)
594{
595 l.unlockWrite();
596}
597
598////////////////////////////////////////////////////////////////////////////////
599//
600// AutoWriteLock
601//
602////////////////////////////////////////////////////////////////////////////////
603
604AutoWriteLock::AutoWriteLock(uint32_t cHandles,
605 LockHandle** pHandles
606 COMMA_LOCKVAL_SRC_POS_DECL)
607 : AutoWriteLockBase(cHandles
608 COMMA_LOCKVAL_SRC_POS_ARGS)
609{
610 Assert(cHandles);
611 Assert(pHandles);
612
613 for (uint32_t i = 0; i < cHandles; ++i)
614 m->aHandles[i] = pHandles[i];
615
616 acquire();
617}
618
619
620
621/**
622 * Attaches another handle to this auto lock instance.
623 *
624 * The previous object's lock is completely released before the new one is
625 * acquired. The lock level of the new handle will be the same. This
626 * also means that if the lock was not acquired at all before #attach(), it
627 * will not be acquired on the new handle too.
628 *
629 * @param aHandle New handle to attach.
630 */
631void AutoWriteLock::attach(LockHandle *aHandle)
632{
633 LockHandle *pHandle = m->aHandles[0];
634
635 /* detect simple self-reattachment */
636 if (pHandle != aHandle)
637 {
638 bool fWasLocked = m->fIsLocked;
639
640 cleanup();
641
642 m->aHandles[0] = aHandle;
643 m->fIsLocked = fWasLocked;
644
645 if (aHandle)
646 if (fWasLocked)
647 callLockImpl(*aHandle);
648 }
649}
650
651/**
652 * Returns @c true if the current thread holds a write lock on the managed
653 * read/write semaphore. Returns @c false if the managed semaphore is @c
654 * NULL.
655 *
656 * @note Intended for debugging only.
657 */
658bool AutoWriteLock::isWriteLockOnCurrentThread() const
659{
660 return m->aHandles[0] ? m->aHandles[0]->isWriteLockOnCurrentThread() : false;
661}
662
663 /**
664 * Returns the current write lock level of the managed semaphore. The lock
665 * level determines the number of nested #lock() calls on the given
666 * semaphore handle. Returns @c 0 if the managed semaphore is @c
667 * NULL.
668 *
669 * Note that this call is valid only when the current thread owns a write
670 * lock on the given semaphore handle and will assert otherwise.
671 *
672 * @note Intended for debugging only.
673 */
674uint32_t AutoWriteLock::writeLockLevel() const
675{
676 return m->aHandles[0] ? m->aHandles[0]->writeLockLevel() : 0;
677}
678
679/**
680 * Returns @c true if the current thread holds a write lock on the managed
681 * read/write semaphore. Returns @c false if the managed semaphore is @c
682 * NULL.
683 *
684 * @note Intended for debugging only (esp. considering fWannaHear).
685 */
686bool AutoWriteLock::isReadLockedOnCurrentThread(bool fWannaHear) const
687{
688 return m->aHandles[0] ? m->aHandles[0]->isReadLockedOnCurrentThread(fWannaHear) : false;
689}
690
691////////////////////////////////////////////////////////////////////////////////
692//
693// AutoMultiWriteLock*
694//
695////////////////////////////////////////////////////////////////////////////////
696
697AutoMultiWriteLock2::AutoMultiWriteLock2(Lockable *pl1,
698 Lockable *pl2
699 COMMA_LOCKVAL_SRC_POS_DECL)
700 : AutoWriteLockBase(2
701 COMMA_LOCKVAL_SRC_POS_ARGS)
702{
703 if (pl1)
704 m->aHandles[0] = pl1->lockHandle();
705 if (pl2)
706 m->aHandles[1] = pl2->lockHandle();
707 acquire();
708}
709
710AutoMultiWriteLock2::AutoMultiWriteLock2(LockHandle *pl1,
711 LockHandle *pl2
712 COMMA_LOCKVAL_SRC_POS_DECL)
713 : AutoWriteLockBase(2
714 COMMA_LOCKVAL_SRC_POS_ARGS)
715{
716 m->aHandles[0] = pl1;
717 m->aHandles[1] = pl2;
718 acquire();
719}
720
721AutoMultiWriteLock3::AutoMultiWriteLock3(Lockable *pl1,
722 Lockable *pl2,
723 Lockable *pl3
724 COMMA_LOCKVAL_SRC_POS_DECL)
725 : AutoWriteLockBase(3
726 COMMA_LOCKVAL_SRC_POS_ARGS)
727{
728 if (pl1)
729 m->aHandles[0] = pl1->lockHandle();
730 if (pl2)
731 m->aHandles[1] = pl2->lockHandle();
732 if (pl3)
733 m->aHandles[2] = pl3->lockHandle();
734 acquire();
735}
736
737AutoMultiWriteLock3::AutoMultiWriteLock3(LockHandle *pl1,
738 LockHandle *pl2,
739 LockHandle *pl3
740 COMMA_LOCKVAL_SRC_POS_DECL)
741 : AutoWriteLockBase(3
742 COMMA_LOCKVAL_SRC_POS_ARGS)
743{
744 m->aHandles[0] = pl1;
745 m->aHandles[1] = pl2;
746 m->aHandles[2] = pl3;
747 acquire();
748}
749
750AutoMultiWriteLock4::AutoMultiWriteLock4(Lockable *pl1,
751 Lockable *pl2,
752 Lockable *pl3,
753 Lockable *pl4
754 COMMA_LOCKVAL_SRC_POS_DECL)
755 : AutoWriteLockBase(4
756 COMMA_LOCKVAL_SRC_POS_ARGS)
757{
758 if (pl1)
759 m->aHandles[0] = pl1->lockHandle();
760 if (pl2)
761 m->aHandles[1] = pl2->lockHandle();
762 if (pl3)
763 m->aHandles[2] = pl3->lockHandle();
764 if (pl4)
765 m->aHandles[3] = pl4->lockHandle();
766 acquire();
767}
768
769AutoMultiWriteLock4::AutoMultiWriteLock4(LockHandle *pl1,
770 LockHandle *pl2,
771 LockHandle *pl3,
772 LockHandle *pl4
773 COMMA_LOCKVAL_SRC_POS_DECL)
774 : AutoWriteLockBase(4
775 COMMA_LOCKVAL_SRC_POS_ARGS)
776{
777 m->aHandles[0] = pl1;
778 m->aHandles[1] = pl2;
779 m->aHandles[2] = pl3;
780 m->aHandles[3] = pl4;
781 acquire();
782}
783
784} /* namespace util */
785/* vi: set tabstop=4 shiftwidth=4 expandtab: */
Note: See TracBrowser for help on using the repository browser.

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