merge the formfield patch from ooo-build
[ooovba.git] / framework / source / threadhelp / lockhelper.cxx
blob9539dcfc2de66d3301b4d3c7a52aebff3d0c1182
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: lockhelper.cxx,v $
10 * $Revision: 1.8 $
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 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_framework.hxx"
34 //_________________________________________________________________________________________________________________
35 // my own includes
36 //_________________________________________________________________________________________________________________
37 #include <threadhelp/lockhelper.hxx>
38 #include <general.h>
39 #include <macros/debug.hxx>
41 #include <macros/generic.hxx>
43 //_________________________________________________________________________________________________________________
44 // interface includes
45 //_________________________________________________________________________________________________________________
47 //_________________________________________________________________________________________________________________
48 // other includes
49 //_________________________________________________________________________________________________________________
50 #include <vos/process.hxx>
52 //_________________________________________________________________________________________________________________
53 // namespace
54 //_________________________________________________________________________________________________________________
56 namespace framework{
58 //_________________________________________________________________________________________________________________
59 // const
60 //_________________________________________________________________________________________________________________
62 //_________________________________________________________________________________________________________________
63 // declarations
64 //_________________________________________________________________________________________________________________
66 /*-************************************************************************************************************//**
67 @short use ctor to initialize instance
68 @descr We must initialize our member "m_eLockType". This value specify handling of locking.
69 User use this helper as parameter for a guard creation.
70 These guard use "m_eLockType" to set lock in the right way by using right mutex or rw-lock.
72 @seealso enum ELockType
73 @seealso class ReadGuard
74 @seealso class WriteGuard
76 @param "rSolarMutex", for some components we must be "vcl-free"! So we can't work with our solar mutex
77 directly. User must set his reference at this instance - so we can work with it!
78 @return -
80 @onerror -
81 *//*-*************************************************************************************************************/
82 LockHelper::LockHelper( ::vos::IMutex* pSolarMutex )
83 : m_pFairRWLock ( NULL )
84 , m_pOwnMutex ( NULL )
85 , m_pSolarMutex ( NULL )
86 , m_pShareableOslMutex( NULL )
87 , m_bDummySolarMutex ( sal_False )
89 m_eLockType = implts_getLockType();
90 switch( m_eLockType )
92 case E_NOTHING : break; // There is nothing to do ...
93 case E_OWNMUTEX : {
94 m_pOwnMutex = new ::osl::Mutex;
96 break;
97 case E_SOLARMUTEX : {
98 if( pSolarMutex == NULL )
100 m_pSolarMutex = new ::vos::OMutex;
101 m_bDummySolarMutex = sal_True;
103 else
105 m_pSolarMutex = pSolarMutex;
108 break;
109 case E_FAIRRWLOCK : {
110 m_pFairRWLock = new FairRWLock;
112 break;
113 #ifdef ENABLE_ASSERTIONS
114 default : LOG_ASSERT2( m_eLockType!=E_NOTHING, "LockHelper::ctor()", "Invalid lock type found .. so code will not be threadsafe!" )
115 #endif
119 /*-************************************************************************************************************//**
120 @short default dtor to release safed pointer
121 @descr We have created dynamical mutex- or lock-member ... or we hold a pointer to external objects.
122 We must release it!
124 @seealso ctor()
126 @param -
127 @return -
129 @onerror -
130 *//*-*************************************************************************************************************/
131 LockHelper::~LockHelper()
133 if( m_pShareableOslMutex != NULL )
135 // Sometimes we hold two pointer to same object!
136 // (e.g. if m_eLockType==E_OWNMUTEX!)
137 // So we should forget it ... but don't delete it twice!
138 if( m_pShareableOslMutex != m_pOwnMutex )
140 delete m_pShareableOslMutex;
142 m_pShareableOslMutex = NULL;
144 if( m_pOwnMutex != NULL )
146 delete m_pOwnMutex;
147 m_pOwnMutex = NULL;
149 if( m_pSolarMutex != NULL )
151 if (m_bDummySolarMutex)
153 delete static_cast<vos::OMutex*>(m_pSolarMutex);
154 m_bDummySolarMutex = sal_False;
156 m_pSolarMutex = NULL;
158 if( m_pFairRWLock != NULL )
160 delete m_pFairRWLock;
161 m_pFairRWLock = NULL;
165 /*-************************************************************************************************************//**
166 @interface IMutex
167 @short set an exclusiv lock
168 @descr We must match this lock call with current set lock type and used lock member.
169 If a mutex should be used - it will be easy ... but if a rw-lock should be used
170 we must simulate it as a write access!
172 @attention If a shareable osl mutex exist, he must be used as twice!
173 It's neccessary for some cppu-helper classes ...
175 @seealso method acquireWriteAccess()
177 @param -
178 @return -
180 @onerror -
181 *//*-*************************************************************************************************************/
182 void LockHelper::acquire()
184 switch( m_eLockType )
186 case E_NOTHING : break; // There is nothing to do ...
187 case E_OWNMUTEX : {
188 m_pOwnMutex->acquire();
190 break;
191 case E_SOLARMUTEX : {
192 m_pSolarMutex->acquire();
194 break;
195 case E_FAIRRWLOCK : {
196 m_pFairRWLock->acquireWriteAccess();
198 break;
202 /*-************************************************************************************************************//**
203 @interface IMutex
204 @short release exclusiv lock
205 @descr We must match this unlock call with current set lock type and used lock member.
206 If a mutex should be used - it will be easy ... but if a rw-lock should be used
207 we must simulate it as a write access!
209 @attention If a shareable osl mutex exist, he must be used as twice!
210 It's neccessary for some cppu-helper classes ...
212 @seealso method releaseWriteAccess()
214 @param -
215 @return -
217 @onerror -
218 *//*-*************************************************************************************************************/
219 void LockHelper::release()
221 switch( m_eLockType )
223 case E_NOTHING : break; // There is nothing to do ...
224 case E_OWNMUTEX : {
225 m_pOwnMutex->release();
227 break;
228 case E_SOLARMUTEX : {
229 m_pSolarMutex->release();
231 break;
232 case E_FAIRRWLOCK : {
233 m_pFairRWLock->releaseWriteAccess();
235 break;
239 /*-************************************************************************************************************//**
240 @interface IRWLock
241 @short set lock for reading
242 @descr A guard should call this method to acquire read access on your member.
243 Writing isn't allowed then - but nobody could check it for you!
244 We use m_eLockType to differ between all possible "lock-member"!!!
246 @attention If a shareable osl mutex exist, he must be used as twice!
247 It's neccessary for some cppu-helper classes ...
249 @seealso method releaseReadAccess()
251 @param -
252 @return -
254 @onerror -
255 *//*-*************************************************************************************************************/
256 void LockHelper::acquireReadAccess()
258 switch( m_eLockType )
260 case E_NOTHING : break; // There is nothing to do ...
261 case E_OWNMUTEX : {
262 m_pOwnMutex->acquire();
264 break;
265 case E_SOLARMUTEX : {
266 m_pSolarMutex->acquire();
268 break;
269 case E_FAIRRWLOCK : {
270 m_pFairRWLock->acquireReadAccess();
272 break;
276 /*-************************************************************************************************************//**
277 @interface IRWLock
278 @short reset lock for reading
279 @descr A guard should call this method to release read access on your member.
280 We use m_eLockType to differ between all possible "lock-member"!!!
282 @attention If a shareable osl mutex exist, he must be used as twice!
283 It's neccessary for some cppu-helper classes ...
285 @seealso method acquireReadAccess()
287 @param -
288 @return -
290 @onerror -
291 *//*-*************************************************************************************************************/
292 void LockHelper::releaseReadAccess()
294 switch( m_eLockType )
296 case E_NOTHING : break; // There is nothing to do ...
297 case E_OWNMUTEX : {
298 m_pOwnMutex->release();
300 break;
301 case E_SOLARMUTEX : {
302 m_pSolarMutex->release();
304 break;
305 case E_FAIRRWLOCK : {
306 m_pFairRWLock->releaseReadAccess();
308 break;
312 /*-************************************************************************************************************//**
313 @interface IRWLock
314 @short set lock for writing
315 @descr A guard should call this method to acquire write access on your member.
316 Reading is allowed too - of course.
317 After successfully calling of this method you are the only writer.
318 We use m_eLockType to differ between all possible "lock-member"!!!
320 @attention If a shareable osl mutex exist, he must be used as twice!
321 It's neccessary for some cppu-helper classes ...
323 @seealso method releaseWriteAccess()
325 @param -
326 @return -
328 @onerror -
329 *//*-*************************************************************************************************************/
330 void LockHelper::acquireWriteAccess()
332 switch( m_eLockType )
334 case E_NOTHING : break; // There is nothing to do ...
335 case E_OWNMUTEX : {
336 m_pOwnMutex->acquire();
338 break;
339 case E_SOLARMUTEX : {
340 m_pSolarMutex->acquire();
342 break;
343 case E_FAIRRWLOCK : {
344 m_pFairRWLock->acquireWriteAccess();
346 break;
350 /*-************************************************************************************************************//**
351 @interface IRWLock
352 @short reset lock for writing
353 @descr A guard should call this method to release write access on your member.
354 We use m_eLockType to differ between all possible "lock-member"!!!
356 @attention If a shareable osl mutex exist, he must be used as twice!
357 It's neccessary for some cppu-helper classes ...
359 @seealso method acquireWriteAccess()
361 @param -
362 @return -
364 @onerror -
365 *//*-*************************************************************************************************************/
366 void LockHelper::releaseWriteAccess()
368 switch( m_eLockType )
370 case E_NOTHING : break; // There is nothing to do ...
371 case E_OWNMUTEX : {
372 m_pOwnMutex->release();
374 break;
375 case E_SOLARMUTEX : {
376 m_pSolarMutex->release();
378 break;
379 case E_FAIRRWLOCK : {
380 m_pFairRWLock->releaseWriteAccess();
382 break;
386 /*-************************************************************************************************************//**
387 @interface IRWLock
388 @short downgrade a write access to a read access
389 @descr A guard should call this method to change a write to a read access.
390 New readers can work too - new writer are blocked!
391 We use m_eLockType to differ between all possible "lock-member"!!!
393 @attention Ignore shareable mutex(!) - because this call never should release a lock completly!
394 We change a write access to a read access only.
396 @attention a) Don't call this method if you are not a writer!
397 Results are not defined then ...
398 An upgrade can't be implemented realy ... because acquiring new access
399 will be the same - there no differences!
400 b) Without function if m_eLockTyp is different from E_FAIRRWLOCK(!) ...
401 because, a mutex don't support it realy.
403 @seealso -
405 @param -
406 @return -
408 @onerror -
409 *//*-*************************************************************************************************************/
410 void LockHelper::downgradeWriteAccess()
412 switch( m_eLockType )
414 case E_NOTHING : break; // There is nothing to do ...
415 case E_OWNMUTEX : break; // Not supported for mutex!
416 case E_SOLARMUTEX : break; // Not supported for mutex!
417 case E_FAIRRWLOCK : m_pFairRWLock->downgradeWriteAccess();
418 break;
422 /*-************************************************************************************************************//**
423 @short return a reference to a static lock helper
424 @descr Sometimes we need the global mutex or rw-lock! (e.g. in our own static methods)
425 But it's not a good idea to use these global one very often ...
426 Thats why we use this little helper method.
427 We create our own "class global static" lock.
428 It will be created at first call only!
429 All other requests use these created one then directly.
431 @seealso -
433 @param -
434 @return A reference to a static mutex/lock member.
436 @onerror No error should occure.
437 *//*-*************************************************************************************************************/
438 LockHelper& LockHelper::getGlobalLock( ::vos::IMutex* pSolarMutex )
440 // Initialize static "member" only for one time!
441 // Algorithm:
442 // a) Start with an invalid lock (NULL pointer)
443 // b) If these method first called (lock not already exist!) ...
444 // c) ... we must create a new one. Protect follow code with the global mutex -
445 // (It must be - we create a static variable!)
446 // d) Check pointer again - because ... another instance of our class could be faster then these one!
447 // e) Create the new lock and set it for return on static variable.
448 // f) Return new created or already existing lock object.
449 static LockHelper* pLock = NULL;
450 if( pLock == NULL )
452 ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() );
453 if( pLock == NULL )
455 static LockHelper aLock( pSolarMutex );
456 pLock = &aLock;
459 return *pLock;
462 /*-************************************************************************************************************//**
463 @short return a reference to shared mutex member
464 @descr Sometimes we need a osl-mutex for sharing with our uno helper ...
465 What can we do?
466 a) If we have an initialized "own mutex" ... we can use it!
467 b) Otherwhise we must use a different mutex member :-(
468 I HOPE IT WORKS!
470 @seealso -
472 @param -
473 @return A reference to a shared mutex.
475 @onerror No error should occure.
476 *//*-*************************************************************************************************************/
477 ::osl::Mutex& LockHelper::getShareableOslMutex()
479 if( m_pShareableOslMutex == NULL )
481 ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() );
482 if( m_pShareableOslMutex == NULL )
484 switch( m_eLockType )
486 case E_OWNMUTEX : {
487 m_pShareableOslMutex = m_pOwnMutex;
489 break;
490 default : {
491 m_pShareableOslMutex = new ::osl::Mutex;
493 break;
497 return *m_pShareableOslMutex;
500 /*-************************************************************************************************************//**
501 @short search for right lock type, which should be used by an instance of this struct
502 @descr We must initialize our member "m_eLockType". This value specify handling of locking.
503 How we can do that? We search for an environment variable. We do it only for one time ....
504 because the environment is fix. So we safe this value and use it for all further requests.
505 If no variable could be found - we use a fallback!
507 @attention We have numbered all our enum values for ELockType. So we can use it as value of searched
508 environment variable too!
510 @seealso enum ELockType
511 @seealso environment LOCKTYPE
513 @param -
514 @return A reference to a created and right initialized lock type!
516 @onerror We use a fallback!
517 *//*-*************************************************************************************************************/
518 ELockType& LockHelper::implts_getLockType()
520 // Initialize static "member" only for one time!
521 // Algorithm:
522 // a) Start with an invalid variable (NULL pointer)
523 // b) If these method first called (value not already exist!) ...
524 // c) ... we must create a new one. Protect follow code with the global mutex -
525 // (It must be - we create a static variable!)
526 // d) Check pointer again - because ... another instance of our class could be faster then these one!
527 // e) Create the new static variable, get value from the environment and set it
528 // f) Return new created or already existing static variable.
529 static ELockType* pType = NULL;
530 if( pType == NULL )
532 ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() );
533 if( pType == NULL )
535 static ELockType eType = FALLBACK_LOCKTYPE;
537 ::vos::OStartupInfo aEnvironment;
538 ::rtl::OUString sValue ;
539 if( aEnvironment.getEnvironment( ENVVAR_LOCKTYPE, sValue ) == ::vos::OStartupInfo::E_None )
541 eType = (ELockType)(sValue.toInt32());
544 LOG_LOCKTYPE( FALLBACK_LOCKTYPE, eType )
546 pType = &eType;
549 return *pType;
552 } // namespace framework