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 #ifndef __FRAMEWORK_THREADHELP_WRITEGUARD_HXX_
29 #define __FRAMEWORK_THREADHELP_WRITEGUARD_HXX_
30 
31 //_________________________________________________________________________________________________________________
32 //	my own includes
33 //_________________________________________________________________________________________________________________
34 
35 #include <threadhelp/inoncopyable.h>
36 #include <threadhelp/irwlock.h>
37 
38 //#ifndef __FRAMEWORK_THREADHELP_THREADHELPBASE_HXX_
39 //#include <threadhelp/threadhelpbase.hxx>
40 //#endif
41 
42 //_________________________________________________________________________________________________________________
43 //	interface includes
44 //_________________________________________________________________________________________________________________
45 
46 //_________________________________________________________________________________________________________________
47 //	other includes
48 //_________________________________________________________________________________________________________________
49 
50 //_________________________________________________________________________________________________________________
51 //	namespace
52 //_________________________________________________________________________________________________________________
53 
54 namespace framework{
55 
56 //_________________________________________________________________________________________________________________
57 //	const
58 //_________________________________________________________________________________________________________________
59 
60 //_________________________________________________________________________________________________________________
61 //	declarations
62 //_________________________________________________________________________________________________________________
63 
64 /*-************************************************************************************************************//**
65 	@short          implement a guard to set write locks
66 	@descr			This guard should be used to set a lock for reading AND writing object internal member.
67 					We never need a own mutex to safe our internal member access - because
68 					a guard is used as function-local member only. There exist no multithreaded access to it realy ...
69 
70     @attention      a) To prevent us against wrong using, the default ctor, copy ctor and the =operator are maked private!
71                     b) Use interface "IRWLock" of set LockHelper only - because we must support a finer granularity of locking.
72                        Interface "IMutex" should be used by easier guard implementations ... like "ResetableGuard"!
73 
74 	@implements		-
75     @base           INonCopyable
76 
77 	@devstatus		ready to use
78 *//*-*************************************************************************************************************/
79 class WriteGuard : private INonCopyable
80 {
81 	//-------------------------------------------------------------------------------------------------------------
82 	//	public methods
83 	//-------------------------------------------------------------------------------------------------------------
84 	public:
85 
86         /*-****************************************************************************************************//**
87             @short      ctor
88             @descr      These ctors initialize the guard with a reference to used lock member of object to protect.
89                         Null isn't allowed as value!
90 
91             @seealso    -
92 
93             @param      "pLock" ,reference to used lock member of object to protect
94             @param      "rLock" ,reference to used lock member of object to protect
95             @return     -
96 
97             @onerror    -
98         *//*-*****************************************************************************************************/
99         inline WriteGuard( IRWLock* pLock )
100             :   m_pLock ( pLock     )
101             ,   m_eMode ( E_NOLOCK  )
102         {
103             lock();
104         }
105 
106         //*********************************************************************************************************
107         inline WriteGuard( IRWLock& rLock )
108             :   m_pLock ( &rLock    )
109             ,   m_eMode ( E_NOLOCK  )
110         {
111             lock();
112         }
113 
114         /*-****************************************************************************************************//**
115             @short      dtor
116             @descr      We unlock the used lock member automaticly if user forget it.
117 
118             @seealso    -
119 
120             @param      -
121             @return     -
122 
123             @onerror    -
124         *//*-*****************************************************************************************************/
125         inline ~WriteGuard()
126         {
127             unlock();
128         }
129 
130         /*-****************************************************************************************************//**
131             @short      set write lock
132             @descr      Call this method to set the write lock. The call will block till all current threads are synchronized!
133 
134             @seealso    method unlock()
135 
136             @param      -
137             @return     -
138 
139             @onerror    -
140         *//*-*****************************************************************************************************/
141         inline void lock()
142         {
143             switch( m_eMode )
144             {
145                 case E_NOLOCK       :   {
146                                             // Acquire write access and set return state.
147                                             // Mode is set later if it was successful!
148                                             m_pLock->acquireWriteAccess();
149                                             m_eMode = E_WRITELOCK;
150                                         }
151                                         break;
152                 case E_READLOCK     :   {
153                                             // User has downgrade to read access before!
154                                             // We must release it before we can set a new write access!
155                                             m_pLock->releaseReadAccess();
156                                             m_pLock->acquireWriteAccess();
157                                             m_eMode = E_WRITELOCK;
158                                         }
159                                         break;
160                 default:                break; // nothing to do
161             }
162         }
163 
164         /*-****************************************************************************************************//**
165             @short      unset write lock
166             @descr      Call this method to unlock the rw-lock temp.!
167                         Normaly we do it at dtor automaticly for you ...
168 
169             @seealso    method lock()
170 
171             @param      -
172             @return     -
173 
174             @onerror    -
175         *//*-*****************************************************************************************************/
176         inline void unlock()
177         {
178             switch( m_eMode )
179             {
180                 case E_READLOCK     :   {
181                                             // User has downgraded to a read lock before!
182                                             // => There isn't realy a write lock ...
183                                             m_pLock->releaseReadAccess();
184                                             m_eMode = E_NOLOCK;
185                                         }
186                                         break;
187                 case E_WRITELOCK    :   {
188                                             m_pLock->releaseWriteAccess();
189                                             m_eMode = E_NOLOCK;
190                                         }
191                                         break;
192                 default:                break; // nothing to do
193             }
194         }
195 
196         /*-****************************************************************************************************//**
197             @short      downgrade write access to read access without new blocking!
198             @descr      If this write lock is set you can change it to a "read lock".
199                         An "upgrade" is the same like new calling "lock()"!
200 
201             @seealso    -
202 
203             @param      -
204             @return     -
205 
206             @onerror    -
207         *//*-*****************************************************************************************************/
208         inline void downgrade()
209         {
210             if( m_eMode == E_WRITELOCK )
211             {
212                 m_pLock->downgradeWriteAccess();
213                 m_eMode = E_READLOCK;
214             }
215         }
216 
217         /*-****************************************************************************************************//**
218             @short      return internal states
219             @descr      For user they dont know what they are doing ...
220 
221             @seealso    -
222 
223             @param      -
224             @return     Current set lock mode.
225 
226             @onerror    No error should occure.
227         *//*-*****************************************************************************************************/
228         inline ELockMode getMode() const
229         {
230             return m_eMode;
231         }
232 
233 	//-------------------------------------------------------------------------------------------------------------
234 	//	private methods
235 	//-------------------------------------------------------------------------------------------------------------
236 	private:
237 
238 		/*-****************************************************************************************************//**
239 			@short		disable using of these functions!
240 			@descr		It's not allowed to use this methods. Different problem can occure otherwise.
241 						Thats why we disable it by make it private.
242 
243 			@seealso	other ctor
244 
245 			@param		-
246 			@return		-
247 
248 			@onerror	-
249 		*//*-*****************************************************************************************************/
250 		WriteGuard();
251 
252 	//-------------------------------------------------------------------------------------------------------------
253 	//	private member
254 	//-------------------------------------------------------------------------------------------------------------
255 	private:
256 
257         IRWLock*    m_pLock ;   /// reference to lock-member of protected object
258 		ELockMode	m_eMode	;	/// protection against multiple lock calls without unlock and difference between supported lock modi
259 
260 };		//	class WriteGuard
261 
262 }       //  namespace framework
263 
264 #endif	//	#ifndef __FRAMEWORK_THREADHELP_WRITEGUARD_HXX_
265