VirtualBox

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

Last change on this file since 88956 was 82968, checked in by vboxsync, 5 years ago

Copyright year updates by scm.

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