VirtualBox

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

Last change on this file since 47469 was 45127, checked in by vboxsync, 11 years ago

AutoLock.cpp: Try the new read/write critical section.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 21.5 KB
Line 
1/* $Id: AutoLock.cpp 45127 2013-03-21 14:42:22Z vboxsync $ */
2/** @file
3 * Automatic locks, implementation.
4 */
5
6/*
7 * Copyright (C) 2006-2013 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/err.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,
130 g_mapLockValidationClasses[lockClass]);
131#else /* !VBOX_WITH_MAIN_LOCK_VALIDATION */
132 return false;
133#endif /* !VBOX_WITH_MAIN_LOCK_VALIDATION */
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*/ void RWLockHandle::lockRead(LOCKVAL_SRC_POS_DECL)
233{
234#ifdef GLUE_USE_CRITSECTRW
235# ifdef VBOX_WITH_MAIN_LOCK_VALIDATION
236 int vrc = RTCritSectRwEnterSharedDebug(&m->CritSect, (uintptr_t)ASMReturnAddress(), RT_SRC_POS_ARGS);
237# else
238 int vrc = RTCritSectRwEnterShared(&m->CritSect);
239# endif
240#else
241# ifdef VBOX_WITH_MAIN_LOCK_VALIDATION
242 int vrc = RTSemRWRequestReadDebug(m->sem, RT_INDEFINITE_WAIT, (uintptr_t)ASMReturnAddress(), RT_SRC_POS_ARGS);
243# else
244 int vrc = RTSemRWRequestRead(m->sem, RT_INDEFINITE_WAIT);
245# endif
246#endif
247 AssertRC(vrc);
248}
249
250/*virtual*/ void RWLockHandle::unlockRead()
251{
252#ifdef GLUE_USE_CRITSECTRW
253 int vrc = RTCritSectRwLeaveShared(&m->CritSect);
254#else
255 int vrc = RTSemRWReleaseRead(m->sem);
256#endif
257 AssertRC(vrc);
258}
259
260/*virtual*/ uint32_t RWLockHandle::writeLockLevel() const
261{
262 /* Note! This does not include read recursions done by the writer! */
263#ifdef GLUE_USE_CRITSECTRW
264 return RTCritSectRwGetWriteRecursion(&m->CritSect);
265#else
266 return RTSemRWGetWriteRecursion(m->sem);
267#endif
268}
269
270#ifdef VBOX_WITH_MAIN_LOCK_VALIDATION
271/*virtual*/ const char* RWLockHandle::describe() const
272{
273 return m->strDescription.c_str();
274}
275#endif
276
277////////////////////////////////////////////////////////////////////////////////
278//
279// WriteLockHandle
280//
281////////////////////////////////////////////////////////////////////////////////
282
283struct WriteLockHandle::Data
284{
285 Data()
286 { }
287
288 mutable RTCRITSECT sem;
289 VBoxLockingClass lockClass;
290
291#ifdef VBOX_WITH_MAIN_LOCK_VALIDATION
292 com::Utf8Str strDescription;
293#endif
294};
295
296WriteLockHandle::WriteLockHandle(VBoxLockingClass lockClass)
297{
298 m = new Data;
299
300 m->lockClass = lockClass;
301
302#ifdef VBOX_WITH_MAIN_LOCK_VALIDATION
303 m->strDescription = com::Utf8StrFmt("crit %RCv", this);
304 int vrc = RTCritSectInitEx(&m->sem, 0/*fFlags*/, g_mapLockValidationClasses[lockClass], RTLOCKVAL_SUB_CLASS_ANY, NULL);
305#else
306 int vrc = RTCritSectInitEx(&m->sem, 0/*fFlags*/, NIL_RTLOCKVALCLASS, RTLOCKVAL_SUB_CLASS_ANY, NULL);
307#endif
308 AssertRC(vrc);
309}
310
311WriteLockHandle::~WriteLockHandle()
312{
313 RTCritSectDelete(&m->sem);
314 delete m;
315}
316
317/*virtual*/ bool WriteLockHandle::isWriteLockOnCurrentThread() const
318{
319 return RTCritSectIsOwner(&m->sem);
320}
321
322/*virtual*/ void WriteLockHandle::lockWrite(LOCKVAL_SRC_POS_DECL)
323{
324#ifdef VBOX_WITH_MAIN_LOCK_VALIDATION
325 RTCritSectEnterDebug(&m->sem, (uintptr_t)ASMReturnAddress(), RT_SRC_POS_ARGS);
326#else
327 RTCritSectEnter(&m->sem);
328#endif
329}
330
331/*virtual*/ void WriteLockHandle::unlockWrite()
332{
333 RTCritSectLeave(&m->sem);
334}
335
336/*virtual*/ void WriteLockHandle::lockRead(LOCKVAL_SRC_POS_DECL)
337{
338 lockWrite(LOCKVAL_SRC_POS_ARGS);
339}
340
341/*virtual*/ void WriteLockHandle::unlockRead()
342{
343 unlockWrite();
344}
345
346/*virtual*/ uint32_t WriteLockHandle::writeLockLevel() const
347{
348 return RTCritSectGetRecursion(&m->sem);
349}
350
351#ifdef VBOX_WITH_MAIN_LOCK_VALIDATION
352/*virtual*/ const char* WriteLockHandle::describe() const
353{
354 return m->strDescription.c_str();
355}
356#endif
357
358////////////////////////////////////////////////////////////////////////////////
359//
360// AutoLockBase
361//
362////////////////////////////////////////////////////////////////////////////////
363
364typedef std::vector<LockHandle*> HandlesVector;
365
366struct AutoLockBase::Data
367{
368 Data(size_t cHandles
369#ifdef VBOX_WITH_MAIN_LOCK_VALIDATION
370 , const char *pcszFile_,
371 unsigned uLine_,
372 const char *pcszFunction_
373#endif
374 )
375 : fIsLocked(false),
376 aHandles(cHandles) // size of array
377#ifdef VBOX_WITH_MAIN_LOCK_VALIDATION
378 , pcszFile(pcszFile_),
379 uLine(uLine_),
380 pcszFunction(pcszFunction_)
381#endif
382 {
383 for (uint32_t i = 0; i < cHandles; ++i)
384 aHandles[i] = NULL;
385 }
386
387 bool fIsLocked; // if true, then all items in aHandles are locked by this AutoLock and
388 // need to be unlocked in the destructor
389 HandlesVector aHandles; // array (vector) of LockHandle instances; in the case of AutoWriteLock
390 // and AutoReadLock, there will only be one item on the list; with the
391 // AutoMulti* derivatives, there will be multiple
392
393#ifdef VBOX_WITH_MAIN_LOCK_VALIDATION
394 // information about where the lock occurred (passed down from the AutoLock classes)
395 const char *pcszFile;
396 unsigned uLine;
397 const char *pcszFunction;
398#endif
399};
400
401AutoLockBase::AutoLockBase(uint32_t cHandles
402 COMMA_LOCKVAL_SRC_POS_DECL)
403{
404 m = new Data(cHandles
405 COMMA_LOCKVAL_SRC_POS_ARGS);
406}
407
408AutoLockBase::AutoLockBase(uint32_t cHandles,
409 LockHandle *pHandle
410 COMMA_LOCKVAL_SRC_POS_DECL)
411{
412 Assert(cHandles == 1);
413 m = new Data(1
414 COMMA_LOCKVAL_SRC_POS_ARGS);
415 m->aHandles[0] = pHandle;
416}
417
418AutoLockBase::~AutoLockBase()
419{
420 delete m;
421}
422
423/**
424 * Requests ownership of all contained lock handles by calling
425 * the pure virtual callLockImpl() function on each of them,
426 * which must be implemented by the descendant class; in the
427 * implementation, AutoWriteLock will request a write lock
428 * whereas AutoReadLock will request a read lock.
429 *
430 * Does *not* modify the lock counts in the member variables.
431 */
432void AutoLockBase::callLockOnAllHandles()
433{
434 for (HandlesVector::iterator it = m->aHandles.begin();
435 it != m->aHandles.end();
436 ++it)
437 {
438 LockHandle *pHandle = *it;
439 if (pHandle)
440 // call virtual function implemented in AutoWriteLock or AutoReadLock
441 this->callLockImpl(*pHandle);
442 }
443}
444
445/**
446 * Releases ownership of all contained lock handles by calling
447 * the pure virtual callUnlockImpl() function on each of them,
448 * which must be implemented by the descendant class; in the
449 * implementation, AutoWriteLock will release a write lock
450 * whereas AutoReadLock will release a read lock.
451 *
452 * Does *not* modify the lock counts in the member variables.
453 */
454void AutoLockBase::callUnlockOnAllHandles()
455{
456 // unlock in reverse order!
457 for (HandlesVector::reverse_iterator it = m->aHandles.rbegin();
458 it != m->aHandles.rend();
459 ++it)
460 {
461 LockHandle *pHandle = *it;
462 if (pHandle)
463 // call virtual function implemented in AutoWriteLock or AutoReadLock
464 this->callUnlockImpl(*pHandle);
465 }
466}
467
468/**
469 * Destructor implementation that can also be called explicitly, if required.
470 * Restores the exact state before the AutoLock was created; that is, unlocks
471 * all contained semaphores.
472 */
473void AutoLockBase::cleanup()
474{
475 if (m->fIsLocked)
476 callUnlockOnAllHandles();
477}
478
479/**
480 * Requests ownership of all contained semaphores. Public method that can
481 * only be called once and that also gets called by the AutoLock constructors.
482 */
483void AutoLockBase::acquire()
484{
485 AssertMsgReturnVoid(!m->fIsLocked, ("m->fIsLocked is true, attempting to lock twice!"));
486 callLockOnAllHandles();
487 m->fIsLocked = true;
488}
489
490/**
491 * Releases ownership of all contained semaphores. Public method.
492 */
493void AutoLockBase::release()
494{
495 AssertMsgReturnVoid(m->fIsLocked, ("m->fIsLocked is false, cannot release!"));
496 callUnlockOnAllHandles();
497 m->fIsLocked = false;
498}
499
500////////////////////////////////////////////////////////////////////////////////
501//
502// AutoReadLock
503//
504////////////////////////////////////////////////////////////////////////////////
505
506/**
507 * Release all read locks acquired by this instance through the #lock()
508 * call and destroys the instance.
509 *
510 * Note that if there there are nested #lock() calls without the
511 * corresponding number of #unlock() calls when the destructor is called, it
512 * will assert. This is because having an unbalanced number of nested locks
513 * is a program logic error which must be fixed.
514 */
515/*virtual*/ AutoReadLock::~AutoReadLock()
516{
517 LockHandle *pHandle = m->aHandles[0];
518
519 if (pHandle)
520 {
521 if (m->fIsLocked)
522 callUnlockImpl(*pHandle);
523 }
524}
525
526/**
527 * Implementation of the pure virtual declared in AutoLockBase.
528 * This gets called by AutoLockBase.acquire() to actually request
529 * the semaphore; in the AutoReadLock implementation, we request
530 * the semaphore in read mode.
531 */
532/*virtual*/ void AutoReadLock::callLockImpl(LockHandle &l)
533{
534#ifdef VBOX_WITH_MAIN_LOCK_VALIDATION
535 l.lockRead(m->pcszFile, m->uLine, m->pcszFunction);
536#else
537 l.lockRead();
538#endif
539}
540
541/**
542 * Implementation of the pure virtual declared in AutoLockBase.
543 * This gets called by AutoLockBase.release() to actually release
544 * the semaphore; in the AutoReadLock implementation, we release
545 * the semaphore in read mode.
546 */
547/*virtual*/ void AutoReadLock::callUnlockImpl(LockHandle &l)
548{
549 l.unlockRead();
550}
551
552////////////////////////////////////////////////////////////////////////////////
553//
554// AutoWriteLockBase
555//
556////////////////////////////////////////////////////////////////////////////////
557
558/**
559 * Implementation of the pure virtual declared in AutoLockBase.
560 * This gets called by AutoLockBase.acquire() to actually request
561 * the semaphore; in the AutoWriteLock implementation, we request
562 * the semaphore in write mode.
563 */
564/*virtual*/ void AutoWriteLockBase::callLockImpl(LockHandle &l)
565{
566#ifdef VBOX_WITH_MAIN_LOCK_VALIDATION
567 l.lockWrite(m->pcszFile, m->uLine, m->pcszFunction);
568#else
569 l.lockWrite();
570#endif
571}
572
573/**
574 * Implementation of the pure virtual declared in AutoLockBase.
575 * This gets called by AutoLockBase.release() to actually release
576 * the semaphore; in the AutoWriteLock implementation, we release
577 * the semaphore in write mode.
578 */
579/*virtual*/ void AutoWriteLockBase::callUnlockImpl(LockHandle &l)
580{
581 l.unlockWrite();
582}
583
584////////////////////////////////////////////////////////////////////////////////
585//
586// AutoWriteLock
587//
588////////////////////////////////////////////////////////////////////////////////
589
590AutoWriteLock::AutoWriteLock(uint32_t cHandles,
591 LockHandle** pHandles
592 COMMA_LOCKVAL_SRC_POS_DECL)
593 : AutoWriteLockBase(cHandles
594 COMMA_LOCKVAL_SRC_POS_ARGS)
595{
596 Assert(cHandles);
597 Assert(pHandles);
598
599 for (uint32_t i = 0; i < cHandles; ++i)
600 m->aHandles[i] = pHandles[i];
601
602 acquire();
603}
604
605
606
607/**
608 * Attaches another handle to this auto lock instance.
609 *
610 * The previous object's lock is completely released before the new one is
611 * acquired. The lock level of the new handle will be the same. This
612 * also means that if the lock was not acquired at all before #attach(), it
613 * will not be acquired on the new handle too.
614 *
615 * @param aHandle New handle to attach.
616 */
617void AutoWriteLock::attach(LockHandle *aHandle)
618{
619 LockHandle *pHandle = m->aHandles[0];
620
621 /* detect simple self-reattachment */
622 if (pHandle != aHandle)
623 {
624 bool fWasLocked = m->fIsLocked;
625
626 cleanup();
627
628 m->aHandles[0] = aHandle;
629 m->fIsLocked = fWasLocked;
630
631 if (aHandle)
632 if (fWasLocked)
633 callLockImpl(*aHandle);
634 }
635}
636
637/**
638 * Returns @c true if the current thread holds a write lock on the managed
639 * read/write semaphore. Returns @c false if the managed semaphore is @c
640 * NULL.
641 *
642 * @note Intended for debugging only.
643 */
644bool AutoWriteLock::isWriteLockOnCurrentThread() const
645{
646 return m->aHandles[0] ? m->aHandles[0]->isWriteLockOnCurrentThread() : false;
647}
648
649 /**
650 * Returns the current write lock level of the managed semaphore. The lock
651 * level determines the number of nested #lock() calls on the given
652 * semaphore handle. Returns @c 0 if the managed semaphore is @c
653 * NULL.
654 *
655 * Note that this call is valid only when the current thread owns a write
656 * lock on the given semaphore handle and will assert otherwise.
657 *
658 * @note Intended for debugging only.
659 */
660uint32_t AutoWriteLock::writeLockLevel() const
661{
662 return m->aHandles[0] ? m->aHandles[0]->writeLockLevel() : 0;
663}
664
665////////////////////////////////////////////////////////////////////////////////
666//
667// AutoMultiWriteLock*
668//
669////////////////////////////////////////////////////////////////////////////////
670
671AutoMultiWriteLock2::AutoMultiWriteLock2(Lockable *pl1,
672 Lockable *pl2
673 COMMA_LOCKVAL_SRC_POS_DECL)
674 : AutoWriteLockBase(2
675 COMMA_LOCKVAL_SRC_POS_ARGS)
676{
677 if (pl1)
678 m->aHandles[0] = pl1->lockHandle();
679 if (pl2)
680 m->aHandles[1] = pl2->lockHandle();
681 acquire();
682}
683
684AutoMultiWriteLock2::AutoMultiWriteLock2(LockHandle *pl1,
685 LockHandle *pl2
686 COMMA_LOCKVAL_SRC_POS_DECL)
687 : AutoWriteLockBase(2
688 COMMA_LOCKVAL_SRC_POS_ARGS)
689{
690 m->aHandles[0] = pl1;
691 m->aHandles[1] = pl2;
692 acquire();
693}
694
695AutoMultiWriteLock3::AutoMultiWriteLock3(Lockable *pl1,
696 Lockable *pl2,
697 Lockable *pl3
698 COMMA_LOCKVAL_SRC_POS_DECL)
699 : AutoWriteLockBase(3
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 if (pl3)
707 m->aHandles[2] = pl3->lockHandle();
708 acquire();
709}
710
711AutoMultiWriteLock3::AutoMultiWriteLock3(LockHandle *pl1,
712 LockHandle *pl2,
713 LockHandle *pl3
714 COMMA_LOCKVAL_SRC_POS_DECL)
715 : AutoWriteLockBase(3
716 COMMA_LOCKVAL_SRC_POS_ARGS)
717{
718 m->aHandles[0] = pl1;
719 m->aHandles[1] = pl2;
720 m->aHandles[2] = pl3;
721 acquire();
722}
723
724AutoMultiWriteLock4::AutoMultiWriteLock4(Lockable *pl1,
725 Lockable *pl2,
726 Lockable *pl3,
727 Lockable *pl4
728 COMMA_LOCKVAL_SRC_POS_DECL)
729 : AutoWriteLockBase(4
730 COMMA_LOCKVAL_SRC_POS_ARGS)
731{
732 if (pl1)
733 m->aHandles[0] = pl1->lockHandle();
734 if (pl2)
735 m->aHandles[1] = pl2->lockHandle();
736 if (pl3)
737 m->aHandles[2] = pl3->lockHandle();
738 if (pl4)
739 m->aHandles[3] = pl4->lockHandle();
740 acquire();
741}
742
743AutoMultiWriteLock4::AutoMultiWriteLock4(LockHandle *pl1,
744 LockHandle *pl2,
745 LockHandle *pl3,
746 LockHandle *pl4
747 COMMA_LOCKVAL_SRC_POS_DECL)
748 : AutoWriteLockBase(4
749 COMMA_LOCKVAL_SRC_POS_ARGS)
750{
751 m->aHandles[0] = pl1;
752 m->aHandles[1] = pl2;
753 m->aHandles[2] = pl3;
754 m->aHandles[3] = pl4;
755 acquire();
756}
757
758} /* namespace util */
759/* vi: set tabstop=4 shiftwidth=4 expandtab: */
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use