1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_unotools.hxx" 30 #include "unotools/readwritemutexguard.hxx" 31 #include <tools/debug.hxx> 32 33 34 namespace utl { 35 36 ReadWriteGuard::ReadWriteGuard( ReadWriteMutex& rMutexP, 37 sal_Int32 nRequestMode ) 38 : rMutex( rMutexP ) 39 { 40 // don't do anything until a pending write completed (or another 41 // ReadWriteGuard leaves the ctor phase) 42 ::osl::MutexGuard aGuard( rMutex.pWriteMutex ); 43 nMode = nRequestMode; 44 if ( nMode & ReadWriteGuardMode::nWrite ) 45 { 46 rMutex.pWriteMutex->acquire(); 47 // wait for any read to complete 48 // TODO: set up a waiting thread instead of a loop 49 sal_Bool bWait = sal_True; 50 do 51 { 52 rMutex.pMutex->acquire(); 53 bWait = (rMutex.nReadCount != 0); 54 if ( nMode & ReadWriteGuardMode::nCriticalChange ) 55 bWait |= (rMutex.nBlockCriticalCount != 0); 56 rMutex.pMutex->release(); 57 } while ( bWait ); 58 } 59 else if ( nMode & ReadWriteGuardMode::nBlockCritical ) 60 { 61 rMutex.pMutex->acquire(); 62 ++rMutex.nBlockCriticalCount; 63 rMutex.pMutex->release(); 64 } 65 else 66 { 67 rMutex.pMutex->acquire(); 68 ++rMutex.nReadCount; 69 rMutex.pMutex->release(); 70 } 71 } 72 73 74 ReadWriteGuard::~ReadWriteGuard() 75 { 76 if ( nMode & ReadWriteGuardMode::nWrite ) 77 rMutex.pWriteMutex->release(); 78 else if ( nMode & ReadWriteGuardMode::nBlockCritical ) 79 { 80 rMutex.pMutex->acquire(); 81 --rMutex.nBlockCriticalCount; 82 rMutex.pMutex->release(); 83 } 84 else 85 { 86 rMutex.pMutex->acquire(); 87 --rMutex.nReadCount; 88 rMutex.pMutex->release(); 89 } 90 } 91 92 93 void ReadWriteGuard::changeReadToWrite() 94 { 95 sal_Bool bOk = !(nMode & (ReadWriteGuardMode::nWrite | ReadWriteGuardMode::nBlockCritical)); 96 DBG_ASSERT( bOk, "ReadWriteGuard::changeReadToWrite: can't" ); 97 if ( bOk ) 98 { 99 // MUST release read before acquiring write mutex or dead lock would 100 // occur if there was a write in another thread waiting for this read 101 // to complete. 102 rMutex.pMutex->acquire(); 103 --rMutex.nReadCount; 104 rMutex.pMutex->release(); 105 106 rMutex.pWriteMutex->acquire(); 107 nMode |= ReadWriteGuardMode::nWrite; 108 // wait for any other read to complete 109 // TODO: set up a waiting thread instead of a loop 110 sal_Bool bWait = sal_True; 111 do 112 { 113 rMutex.pMutex->acquire(); 114 bWait = (rMutex.nReadCount != 0); 115 rMutex.pMutex->release(); 116 } while ( bWait ); 117 } 118 } 119 120 } // namespace utl 121