merge the formfield patch from ooo-build
[ooovba.git] / framework / inc / threadhelp / fairrwlock.hxx
blob79e4b5b13e21f1de0a99d5ededbb18e647980f75
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: fairrwlock.hxx,v $
10 * $Revision: 1.7 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 #ifndef __FRAMEWORK_THREADHELP_FAIRRWLOCK_HXX_
32 #define __FRAMEWORK_THREADHELP_FAIRRWLOCK_HXX_
34 //_________________________________________________________________________________________________________________
35 // my own includes
36 //_________________________________________________________________________________________________________________
38 #include <threadhelp/inoncopyable.h>
39 #include <threadhelp/irwlock.h>
40 #include <macros/debug.hxx>
42 //_________________________________________________________________________________________________________________
43 // interface includes
44 //_________________________________________________________________________________________________________________
45 #include <com/sun/star/uno/XInterface.hpp>
46 #include <com/sun/star/lang/DisposedException.hpp>
48 //_________________________________________________________________________________________________________________
49 // other includes
50 //_________________________________________________________________________________________________________________
51 #include <osl/mutex.hxx>
52 #include <osl/conditn.hxx>
54 //_________________________________________________________________________________________________________________
55 // namespace
56 //_________________________________________________________________________________________________________________
58 namespace framework{
60 //_________________________________________________________________________________________________________________
61 // const
62 //_________________________________________________________________________________________________________________
64 //_________________________________________________________________________________________________________________
65 // declarations
66 //_________________________________________________________________________________________________________________
68 /*-************************************************************************************************************//**
69 @short implement a read/write lock with fairness between read/write accessors
70 @descr These implementation never should used as base class! Use it as a member every time.
71 Use ReadGuard and/or WriteGuard in your methods (which work with these lock)
72 to make your code threadsafe.
73 Fair means: All reading or writing threads are synchronized AND serialzed by using one
74 mutex. For reader this mutex is used to access internal variables of this lock only;
75 for writer this mutex is used to have an exclusiv access on your class member!
76 => It's a multi-reader/single-writer lock, which no preferred accessor.
78 @implements IRWlock
79 @base INonCopyable
80 IRWLock
82 @devstatus ready to use
83 *//*-*************************************************************************************************************/
84 class FairRWLock : public IRWLock
85 , private INonCopyable
87 //-------------------------------------------------------------------------------------------------------------
88 // public methods
89 //-------------------------------------------------------------------------------------------------------------
90 public:
92 /*-****************************************************************************************************//**
93 @short standard ctor
94 @descr Initialize instance with right start values for correct working.
95 no reader could exist => m_nReadCount = 0
96 don't block first comming writer => m_aWriteCondition.set()
98 @seealso -
100 @param -
101 @return -
103 @onerror -
104 *//*-*****************************************************************************************************/
105 inline FairRWLock()
106 : m_nReadCount( 0 )
108 m_aWriteCondition.set();
111 inline virtual ~FairRWLock()
115 /*-****************************************************************************************************//**
116 @interface IRWLock
117 @short set lock for reading
118 @descr A guard should call this method to acquire read access on your member.
119 Writing isn't allowed then - but nobody could check it for you!
121 @seealso method releaseReadAccess()
123 @param -
124 @return -
126 @onerror -
127 *//*-*****************************************************************************************************/
128 inline virtual void acquireReadAccess()
130 // Put call in "SERIALIZE"-queue!
131 // After successful acquiring this mutex we are alone ...
132 ::osl::MutexGuard aSerializeGuard( m_aSerializer );
134 // ... but we should synchronize us with other reader!
135 // May be - they will unregister himself by using releaseReadAccess()!
136 ::osl::MutexGuard aAccessGuard( m_aAccessLock );
138 // Now we must register us as reader by increasing counter.
139 // If this the first writer we must close door for possible writer.
140 // Other reader don't look for this barrier - they work parallel to us!
141 if( m_nReadCount == 0 )
143 m_aWriteCondition.reset();
145 ++m_nReadCount;
148 /*-****************************************************************************************************//**
149 @interface IRWLock
150 @short reset lock for reading
151 @descr A guard should call this method to release read access on your member.
153 @seealso method acquireReadAccess()
155 @param -
156 @return -
158 @onerror -
159 *//*-*****************************************************************************************************/
160 inline virtual void releaseReadAccess()
162 // The access lock is enough at this point
163 // because it's not allowed to wait for all reader or writer here!
164 // That will cause a deadlock!
165 ::osl::MutexGuard aAccessGuard( m_aAccessLock );
167 // Unregister as reader first!
168 // Open writer barrier then if it was the last reader.
169 --m_nReadCount;
170 if( m_nReadCount == 0 )
172 m_aWriteCondition.set();
176 /*-****************************************************************************************************//**
177 @interface IRWLock
178 @short set lock for writing
179 @descr A guard should call this method to acquire write access on your member.
180 Reading is allowed too - of course.
181 After successfully calling of this method you are the only writer.
183 @seealso method releaseWriteAccess()
185 @param -
186 @return -
188 @onerror -
189 *//*-*****************************************************************************************************/
190 inline virtual void acquireWriteAccess()
192 // You have to stand in our serialize-queue till all reader
193 // are registered (not for releasing them!) or writer finished their work!
194 // Don't use a guard to do so - because you must hold the mutex till
195 // you call releaseWriteAccess()!
196 // After succesfull acquire you have to wait for current working reader.
197 // Used condition will open by last gone reader object.
198 m_aSerializer.acquire();
199 m_aWriteCondition.wait();
201 #ifdef ENABLE_MUTEXDEBUG
202 // A writer is an exclusiv accessor!
203 LOG_ASSERT2( m_nReadCount!=0, "FairRWLock::acquireWriteAccess()", "No threadsafe code detected ... : Read count != 0!" )
204 #endif
207 /*-****************************************************************************************************//**
208 @interface IRWLock
209 @short reset lock for writing
210 @descr A guard should call this method to release write access on your member.
212 @seealso method acquireWriteAccess()
214 @param -
215 @return -
217 @onerror -
218 *//*-*****************************************************************************************************/
219 inline virtual void releaseWriteAccess()
221 // The only one you have to do here is to release
222 // hold seriliaze-mutex. All other user of these instance are blocked
223 // by these mutex!
224 // You don't need any other mutex here - you are the only one in the moment!
226 #ifdef ENABLE_MUTEXDEBUG
227 // A writer is an exclusiv accessor!
228 LOG_ASSERT2( m_nReadCount!=0, "FairRWLock::releaseWriteAccess()", "No threadsafe code detected ... : Read count != 0!" )
229 #endif
231 m_aSerializer.release();
234 /*-****************************************************************************************************//**
235 @interface IRWLock
236 @short downgrade a write access to a read access
237 @descr A guard should call this method to change a write to a read access.
238 New readers can work too - new writer are blocked!
240 @attention Don't call this method if you are not a writer!
241 Results are not defined then ...
242 An upgrade can't be implemented realy ... because acquiring new access
243 will be the same - there no differences!
245 @seealso -
247 @param -
248 @return -
250 @onerror -
251 *//*-*****************************************************************************************************/
252 inline virtual void downgradeWriteAccess()
254 // You must be a writer to call this method!
255 // We can't check it - but otherwise it's your problem ...
256 // Thats why you don't need any mutex here.
258 #ifdef ENABLE_MUTEXDEBUG
259 // A writer is an exclusiv accessor!
260 LOG_ASSERT2( m_nReadCount!=0, "FairRWLock::downgradeWriteAccess()", "No threadsafe code detected ... : Read count != 0!" )
261 #endif
263 // Register himself as "new" reader.
264 // This value must be 0 before - because we support single writer access only!
265 ++m_nReadCount;
266 // Close barrier for other writer!
267 // Why?
268 // You hold the serializer mutex - next one can be a reader OR a writer.
269 // They must blocked then - because you will be a reader after this call
270 // and writer use this condition to wait for current reader!
271 m_aWriteCondition.reset();
272 // Open door for next waiting thread in serialize queue!
273 m_aSerializer.release();
276 //-------------------------------------------------------------------------------------------------------------
277 // private member
278 //-------------------------------------------------------------------------------------------------------------
279 private:
281 ::osl::Mutex m_aAccessLock ; /// regulate access on internal member of this instance
282 ::osl::Mutex m_aSerializer ; /// serialze incoming read/write access threads
283 ::osl::Condition m_aWriteCondition ; /// a writer must wait till current working reader are gone
284 sal_Int32 m_nReadCount ; /// every reader is registered - the last one open the door for waiting writer
286 }; // class FairRWLock
288 } // namespace framework
290 #endif // #ifndef __FRAMEWORK_THREADHELP_FAIRRWLOCK_HXX_