1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 23 24 // MARKER(update_precomp.py): autogen include statement, do not remove 25 #include "precompiled_unotools.hxx" 26 #include "unotools/readwritemutexguard.hxx" 27 #include <tools/debug.hxx> 28 29 30 namespace utl { 31 ReadWriteGuard(ReadWriteMutex & rMutexP,sal_Int32 nRequestMode)32ReadWriteGuard::ReadWriteGuard( ReadWriteMutex& rMutexP, 33 sal_Int32 nRequestMode ) 34 : rMutex( rMutexP ) 35 { 36 // don't do anything until a pending write completed (or another 37 // ReadWriteGuard leaves the ctor phase) 38 ::osl::MutexGuard aGuard( rMutex.pWriteMutex ); 39 nMode = nRequestMode; 40 if ( nMode & ReadWriteGuardMode::nWrite ) 41 { 42 rMutex.pWriteMutex->acquire(); 43 // wait for any read to complete 44 // TODO: set up a waiting thread instead of a loop 45 sal_Bool bWait = sal_True; 46 do 47 { 48 rMutex.pMutex->acquire(); 49 bWait = (rMutex.nReadCount != 0); 50 if ( nMode & ReadWriteGuardMode::nCriticalChange ) 51 bWait |= (rMutex.nBlockCriticalCount != 0); 52 rMutex.pMutex->release(); 53 } while ( bWait ); 54 } 55 else if ( nMode & ReadWriteGuardMode::nBlockCritical ) 56 { 57 rMutex.pMutex->acquire(); 58 ++rMutex.nBlockCriticalCount; 59 rMutex.pMutex->release(); 60 } 61 else 62 { 63 rMutex.pMutex->acquire(); 64 ++rMutex.nReadCount; 65 rMutex.pMutex->release(); 66 } 67 } 68 69 ~ReadWriteGuard()70ReadWriteGuard::~ReadWriteGuard() 71 { 72 if ( nMode & ReadWriteGuardMode::nWrite ) 73 rMutex.pWriteMutex->release(); 74 else if ( nMode & ReadWriteGuardMode::nBlockCritical ) 75 { 76 rMutex.pMutex->acquire(); 77 --rMutex.nBlockCriticalCount; 78 rMutex.pMutex->release(); 79 } 80 else 81 { 82 rMutex.pMutex->acquire(); 83 --rMutex.nReadCount; 84 rMutex.pMutex->release(); 85 } 86 } 87 88 changeReadToWrite()89void ReadWriteGuard::changeReadToWrite() 90 { 91 sal_Bool bOk = !(nMode & (ReadWriteGuardMode::nWrite | ReadWriteGuardMode::nBlockCritical)); 92 DBG_ASSERT( bOk, "ReadWriteGuard::changeReadToWrite: can't" ); 93 if ( bOk ) 94 { 95 // MUST release read before acquiring write mutex or dead lock would 96 // occur if there was a write in another thread waiting for this read 97 // to complete. 98 rMutex.pMutex->acquire(); 99 --rMutex.nReadCount; 100 rMutex.pMutex->release(); 101 102 rMutex.pWriteMutex->acquire(); 103 nMode |= ReadWriteGuardMode::nWrite; 104 // wait for any other read to complete 105 // TODO: set up a waiting thread instead of a loop 106 sal_Bool bWait = sal_True; 107 do 108 { 109 rMutex.pMutex->acquire(); 110 bWait = (rMutex.nReadCount != 0); 111 rMutex.pMutex->release(); 112 } while ( bWait ); 113 } 114 } 115 116 } // namespace utl 117