1*6d739b60SAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
3*6d739b60SAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
4*6d739b60SAndrew Rist  * or more contributor license agreements.  See the NOTICE file
5*6d739b60SAndrew Rist  * distributed with this work for additional information
6*6d739b60SAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
7*6d739b60SAndrew Rist  * to you under the Apache License, Version 2.0 (the
8*6d739b60SAndrew Rist  * "License"); you may not use this file except in compliance
9*6d739b60SAndrew Rist  * with the License.  You may obtain a copy of the License at
10*6d739b60SAndrew Rist  *
11*6d739b60SAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12*6d739b60SAndrew Rist  *
13*6d739b60SAndrew Rist  * Unless required by applicable law or agreed to in writing,
14*6d739b60SAndrew Rist  * software distributed under the License is distributed on an
15*6d739b60SAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*6d739b60SAndrew Rist  * KIND, either express or implied.  See the License for the
17*6d739b60SAndrew Rist  * specific language governing permissions and limitations
18*6d739b60SAndrew Rist  * under the License.
19*6d739b60SAndrew Rist  *
20*6d739b60SAndrew Rist  *************************************************************/
21*6d739b60SAndrew Rist 
22*6d739b60SAndrew Rist 
23cdf0e10cSrcweir 
24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
25cdf0e10cSrcweir #include "precompiled_framework.hxx"
26cdf0e10cSrcweir 
27cdf0e10cSrcweir //_________________________________________________________________________________________________________________
28cdf0e10cSrcweir //	my own includes
29cdf0e10cSrcweir //_________________________________________________________________________________________________________________
30cdf0e10cSrcweir #include <threadhelp/transactionmanager.hxx>
31cdf0e10cSrcweir #include <threadhelp/resetableguard.hxx>
32cdf0e10cSrcweir #include <macros/debug.hxx>
33cdf0e10cSrcweir 
34cdf0e10cSrcweir #include <macros/generic.hxx>
35cdf0e10cSrcweir #include <fwidllapi.h>
36cdf0e10cSrcweir 
37cdf0e10cSrcweir //_________________________________________________________________________________________________________________
38cdf0e10cSrcweir //	interface includes
39cdf0e10cSrcweir //_________________________________________________________________________________________________________________
40cdf0e10cSrcweir #include <com/sun/star/lang/DisposedException.hpp>
41cdf0e10cSrcweir //_________________________________________________________________________________________________________________
42cdf0e10cSrcweir //	other includes
43cdf0e10cSrcweir //_________________________________________________________________________________________________________________
44cdf0e10cSrcweir 
45cdf0e10cSrcweir //_________________________________________________________________________________________________________________
46cdf0e10cSrcweir //	const
47cdf0e10cSrcweir //_________________________________________________________________________________________________________________
48cdf0e10cSrcweir 
49cdf0e10cSrcweir //_________________________________________________________________________________________________________________
50cdf0e10cSrcweir //	namespace
51cdf0e10cSrcweir //_________________________________________________________________________________________________________________
52cdf0e10cSrcweir 
53cdf0e10cSrcweir namespace framework{
54cdf0e10cSrcweir 
55cdf0e10cSrcweir //_________________________________________________________________________________________________________________
56cdf0e10cSrcweir //	non exported const
57cdf0e10cSrcweir //_________________________________________________________________________________________________________________
58cdf0e10cSrcweir 
59cdf0e10cSrcweir //_________________________________________________________________________________________________________________
60cdf0e10cSrcweir //	non exported declarations
61cdf0e10cSrcweir //_________________________________________________________________________________________________________________
62cdf0e10cSrcweir 
63cdf0e10cSrcweir //_________________________________________________________________________________________________________________
64cdf0e10cSrcweir //	definitions
65cdf0e10cSrcweir //_________________________________________________________________________________________________________________
66cdf0e10cSrcweir 
67cdf0e10cSrcweir /*-************************************************************************************************************//**
68cdf0e10cSrcweir     @short      standard ctor
69cdf0e10cSrcweir     @descr      Initialize instance with right start values for correct working.
70cdf0e10cSrcweir 
71cdf0e10cSrcweir     @seealso    -
72cdf0e10cSrcweir 
73cdf0e10cSrcweir     @param      -
74cdf0e10cSrcweir     @return     -
75cdf0e10cSrcweir 
76cdf0e10cSrcweir     @onerror    -
77cdf0e10cSrcweir *//*-*************************************************************************************************************/
TransactionManager()78cdf0e10cSrcweir TransactionManager::TransactionManager()
79cdf0e10cSrcweir     : m_eWorkingMode      ( E_INIT )
80cdf0e10cSrcweir     , m_nTransactionCount ( 0      )
81cdf0e10cSrcweir {
82cdf0e10cSrcweir     m_aBarrier.open();
83cdf0e10cSrcweir }
84cdf0e10cSrcweir 
85cdf0e10cSrcweir /*-************************************************************************************************************//**
86cdf0e10cSrcweir     @short      standard dtor
87cdf0e10cSrcweir     @descr      -
88cdf0e10cSrcweir 
89cdf0e10cSrcweir     @seealso    -
90cdf0e10cSrcweir 
91cdf0e10cSrcweir     @param      -
92cdf0e10cSrcweir     @return     -
93cdf0e10cSrcweir 
94cdf0e10cSrcweir     @onerror    -
95cdf0e10cSrcweir *//*-*************************************************************************************************************/
~TransactionManager()96cdf0e10cSrcweir TransactionManager::~TransactionManager()
97cdf0e10cSrcweir {
98cdf0e10cSrcweir }
99cdf0e10cSrcweir 
100cdf0e10cSrcweir /*-****************************************************************************************************//**
101cdf0e10cSrcweir     @interface  ITransactionManager
102cdf0e10cSrcweir     @short      set new working mode
103cdf0e10cSrcweir     @descr      These implementation knows for states of working: E_INIT, E_WORK, E_CLOSING, E_CLOSE
104cdf0e10cSrcweir                 You can step during this ones only from the left to the right side and start at left side again!
105cdf0e10cSrcweir                 (This is neccessary e.g. for refcounted objects!)
106cdf0e10cSrcweir                 This call will block till all current existing transactions was finished.
107cdf0e10cSrcweir                 Follow results occure:
108cdf0e10cSrcweir                     E_INIT        :  All requests on this implementation are refused.
109cdf0e10cSrcweir                                         It's your decision to react in a right way.
110cdf0e10cSrcweir 
111cdf0e10cSrcweir                     E_WORK        :  The object can work now. The full functionality is available.
112cdf0e10cSrcweir 
113cdf0e10cSrcweir                     E_BEFORECLOSE :  The object start the closing mechanism ... but sometimes
114cdf0e10cSrcweir                                         e.g. the dispose() method need to call some private methods.
115cdf0e10cSrcweir                                         These some special methods should use E_SOFTEXCEPTIONS or ignore
116cdf0e10cSrcweir                                         E_INCLOSE as returned reason for E_NOEXCEPTIONS to detect this special case!
117cdf0e10cSrcweir 
118cdf0e10cSrcweir                     E_CLOSE       :  Object is already dead! All further requests will be refused.
119cdf0e10cSrcweir                                         It's your decision to react in a right way.
120cdf0e10cSrcweir 
121cdf0e10cSrcweir     @seealso    -
122cdf0e10cSrcweir 
123cdf0e10cSrcweir     @param      "eMode", is the new mode - but we don't accept setting mode in wrong order!
124cdf0e10cSrcweir     @return     -
125cdf0e10cSrcweir 
126cdf0e10cSrcweir     @onerror    We do nothing.
127cdf0e10cSrcweir *//*-*****************************************************************************************************/
setWorkingMode(EWorkingMode eMode)128cdf0e10cSrcweir void  TransactionManager::setWorkingMode( EWorkingMode eMode )
129cdf0e10cSrcweir {
130cdf0e10cSrcweir     // Safe member access.
131cdf0e10cSrcweir     ::osl::ClearableMutexGuard  aAccessGuard( m_aAccessLock );
132cdf0e10cSrcweir     sal_Bool                    bWaitFor    = sal_False      ;
133cdf0e10cSrcweir     // Change working mode first!
134cdf0e10cSrcweir     if  (
135cdf0e10cSrcweir             ( m_eWorkingMode == E_INIT        && eMode == E_WORK        ) ||
136cdf0e10cSrcweir             ( m_eWorkingMode == E_WORK        && eMode == E_BEFORECLOSE ) ||
137cdf0e10cSrcweir             ( m_eWorkingMode == E_BEFORECLOSE && eMode == E_CLOSE       ) ||
138cdf0e10cSrcweir             ( m_eWorkingMode == E_CLOSE       && eMode == E_INIT        )
139cdf0e10cSrcweir         )
140cdf0e10cSrcweir     {
141cdf0e10cSrcweir         m_eWorkingMode = eMode;
142cdf0e10cSrcweir         if( m_eWorkingMode == E_BEFORECLOSE || m_eWorkingMode == E_CLOSE )
143cdf0e10cSrcweir         {
144cdf0e10cSrcweir             bWaitFor = sal_True;
145cdf0e10cSrcweir         }
146cdf0e10cSrcweir     }
147cdf0e10cSrcweir 
148cdf0e10cSrcweir     // Wait for current existing transactions then!
149cdf0e10cSrcweir     // (Only neccessary for changing to E_BEFORECLOSE or E_CLOSE! ...
150cdf0e10cSrcweir     // otherwise; if you wait at setting E_WORK another thrad could finish a acquire-call during our unlock() and wait() call
151cdf0e10cSrcweir     // ... and we will wait forever here!!!)
152cdf0e10cSrcweir     // Don't forget to release access mutex before.
153cdf0e10cSrcweir     aAccessGuard.clear();
154cdf0e10cSrcweir     if( bWaitFor == sal_True )
155cdf0e10cSrcweir     {
156cdf0e10cSrcweir         m_aBarrier.wait();
157cdf0e10cSrcweir     }
158cdf0e10cSrcweir }
159cdf0e10cSrcweir 
160cdf0e10cSrcweir /*-****************************************************************************************************//**
161cdf0e10cSrcweir     @interface  ITransactionManager
162cdf0e10cSrcweir     @short      get current working mode
163cdf0e10cSrcweir     @descr      If you stand in your close() or init() method ... but don't know
164cdf0e10cSrcweir                 if you called more then ones(!) ... you can use this function to get
165cdf0e10cSrcweir                 right information.
166cdf0e10cSrcweir                 e.g:    You have a method init() which is used to change working mode from
167cdf0e10cSrcweir                         E_INIT to E_WORK and should be used to initialize some member too ...
168cdf0e10cSrcweir                         What should you do:
169cdf0e10cSrcweir 
170cdf0e10cSrcweir                             void init( sal_Int32 nValue )
171cdf0e10cSrcweir                             {
172cdf0e10cSrcweir                                 // Reject this call if our transaction manager say: "Object already initialized!"
173cdf0e10cSrcweir                                 // Otherwise initialize your member.
174cdf0e10cSrcweir                                 if( m_aTransactionManager.getWorkingMode() == E_INIT )
175cdf0e10cSrcweir                                 {
176cdf0e10cSrcweir                                     // Object is uninitialized ...
177cdf0e10cSrcweir                                     // Make member access threadsafe!
178cdf0e10cSrcweir                                     ResetableGuard aGuard( m_aMutex );
179cdf0e10cSrcweir 
180cdf0e10cSrcweir                                     // Check working mode again .. because anozï¿œther instance could be faster.
181cdf0e10cSrcweir                                     // (It's possible to set this guard at first of this method too!)
182cdf0e10cSrcweir                                     if( m_aTransactionManager.getWorkingMode() == E_INIT )
183cdf0e10cSrcweir                                     {
184cdf0e10cSrcweir                                         m_aMember = nValue;
185cdf0e10cSrcweir 
186cdf0e10cSrcweir                                         // Object is initialized now ... set working mode to E_WORK!
187cdf0e10cSrcweir                                         m_aTransactionManager.setWorkingMode( E_WORK );
188cdf0e10cSrcweir                                     }
189cdf0e10cSrcweir                                 }
190cdf0e10cSrcweir                             }
191cdf0e10cSrcweir 
192cdf0e10cSrcweir     @seealso    method setWorkingMode()
193cdf0e10cSrcweir 
194cdf0e10cSrcweir     @param      -
195cdf0e10cSrcweir     @return     Current set mode.
196cdf0e10cSrcweir 
197cdf0e10cSrcweir     @onerror    No error should occure.
198cdf0e10cSrcweir *//*-*****************************************************************************************************/
getWorkingMode() const199cdf0e10cSrcweir EWorkingMode TransactionManager::getWorkingMode() const
200cdf0e10cSrcweir {
201cdf0e10cSrcweir     // Synchronize access to internal member!
202cdf0e10cSrcweir     ::osl::MutexGuard aAccessLock( m_aAccessLock );
203cdf0e10cSrcweir     return m_eWorkingMode;
204cdf0e10cSrcweir }
205cdf0e10cSrcweir 
206cdf0e10cSrcweir /*-****************************************************************************************************//**
207cdf0e10cSrcweir     @interface  ITransactionManager
208cdf0e10cSrcweir     @short      start new transaction
209cdf0e10cSrcweir     @descr      A guard should use this method to start a new transaction. He should looks for rejected
210cdf0e10cSrcweir                 calls to by using parameter eMode and eReason.
211cdf0e10cSrcweir                 If call was not rejected your transaction will be non breakable during releasing your transaction
212cdf0e10cSrcweir                 guard! BUT ... your code isn't threadsafe then! It's a transaction manager only ....
213cdf0e10cSrcweir 
214cdf0e10cSrcweir     @seealso    method unregisterTransaction()
215cdf0e10cSrcweir 
216cdf0e10cSrcweir     @param      "eMode"     ,used to enable/disable throwing exceptions automaticly for rejected calls
217cdf0e10cSrcweir     @param      "eReason"   ,reason for rejected calls if eMode=E_NOEXCEPTIONS
218cdf0e10cSrcweir     @return     -
219cdf0e10cSrcweir 
220cdf0e10cSrcweir     @onerror    -
221cdf0e10cSrcweir *//*-*****************************************************************************************************/
registerTransaction(EExceptionMode eMode,ERejectReason & eReason)222cdf0e10cSrcweir void  TransactionManager::registerTransaction( EExceptionMode eMode, ERejectReason& eReason ) throw( css::uno::RuntimeException, css::lang::DisposedException )
223cdf0e10cSrcweir {
224cdf0e10cSrcweir     // Look for rejected calls first.
225cdf0e10cSrcweir     // If call was refused we throw some exceptions or do nothing!
226cdf0e10cSrcweir     // It depends from given parameter eMode.
227cdf0e10cSrcweir     if( isCallRejected( eReason ) == sal_True )
228cdf0e10cSrcweir     {
229cdf0e10cSrcweir         impl_throwExceptions( eMode, eReason );
230cdf0e10cSrcweir     }
231cdf0e10cSrcweir 
232cdf0e10cSrcweir     // BUT if no exception was thrown ... (may be eMode = E_SOFTEXCEPTIONS!)
233cdf0e10cSrcweir     // we must register this transaction too!
234cdf0e10cSrcweir     // Don't use "else" or a new scope here!!!
235cdf0e10cSrcweir 
236cdf0e10cSrcweir     // Safe access to internal member.
237cdf0e10cSrcweir     ::osl::MutexGuard aAccessGuard( m_aAccessLock );
238cdf0e10cSrcweir 
239cdf0e10cSrcweir     #ifdef ENABLE_MUTEXDEBUG
240cdf0e10cSrcweir     LOG_ASSERT2( m_nTransactionCount<0, "TransactionManager::acquire()", "Wrong ref count detected!" )
241cdf0e10cSrcweir     #endif
242cdf0e10cSrcweir 
243cdf0e10cSrcweir     // Register this new transaction.
244cdf0e10cSrcweir     // If it is the first one .. close gate to disable changing of working mode.
245cdf0e10cSrcweir     ++m_nTransactionCount;
246cdf0e10cSrcweir     if( m_nTransactionCount == 1 )
247cdf0e10cSrcweir     {
248cdf0e10cSrcweir         m_aBarrier.close();
249cdf0e10cSrcweir     }
250cdf0e10cSrcweir }
251cdf0e10cSrcweir 
252cdf0e10cSrcweir /*-****************************************************************************************************//**
253cdf0e10cSrcweir     @interface  ITransactionManager
254cdf0e10cSrcweir     @short      finish transaction
255cdf0e10cSrcweir     @descr      A guard should call this method to release current transaction.
256cdf0e10cSrcweir 
257cdf0e10cSrcweir     @seealso    method registerTransaction()
258cdf0e10cSrcweir 
259cdf0e10cSrcweir     @param      -
260cdf0e10cSrcweir     @return     -
261cdf0e10cSrcweir 
262cdf0e10cSrcweir     @onerror    -
263cdf0e10cSrcweir *//*-*****************************************************************************************************/
unregisterTransaction()264cdf0e10cSrcweir void  TransactionManager::unregisterTransaction() throw( css::uno::RuntimeException, css::lang::DisposedException )
265cdf0e10cSrcweir {
266cdf0e10cSrcweir     // This call could not rejected!
267cdf0e10cSrcweir     // Safe access to internal member.
268cdf0e10cSrcweir     ::osl::MutexGuard aAccessGuard( m_aAccessLock );
269cdf0e10cSrcweir 
270cdf0e10cSrcweir     #ifdef ENABLE_MUTEXDEBUG
271cdf0e10cSrcweir     LOG_ASSERT2( m_nTransactionCount<=0, "TransactionManager::release()", "Wrong ref count detected!" )
272cdf0e10cSrcweir     #endif
273cdf0e10cSrcweir 
274cdf0e10cSrcweir     // Deregister this transaction.
275cdf0e10cSrcweir     // If it was the last one ... open gate to enable changing of working mode!
276cdf0e10cSrcweir     // (see setWorkingMode())
277cdf0e10cSrcweir 
278cdf0e10cSrcweir     --m_nTransactionCount;
279cdf0e10cSrcweir     if( m_nTransactionCount == 0 )
280cdf0e10cSrcweir     {
281cdf0e10cSrcweir         m_aBarrier.open();
282cdf0e10cSrcweir     }
283cdf0e10cSrcweir }
284cdf0e10cSrcweir 
285cdf0e10cSrcweir /*-****************************************************************************************************//**
286cdf0e10cSrcweir     @interface  ITransactionManager
287cdf0e10cSrcweir     @short      look for rejected calls
288cdf0e10cSrcweir     @descr      Sometimes user need a possibility to get information about rejected calls
289cdf0e10cSrcweir                 without starting a transaction!
290cdf0e10cSrcweir 
291cdf0e10cSrcweir     @seealso    -
292cdf0e10cSrcweir 
293cdf0e10cSrcweir     @param      "eReason" returns reason of a rejected call
294cdf0e10cSrcweir     @return     true if call was rejected, false otherwise
295cdf0e10cSrcweir 
296cdf0e10cSrcweir     @onerror    We return false.
297cdf0e10cSrcweir *//*-*****************************************************************************************************/
isCallRejected(ERejectReason & eReason) const298cdf0e10cSrcweir sal_Bool  TransactionManager::isCallRejected( ERejectReason& eReason ) const
299cdf0e10cSrcweir {
300cdf0e10cSrcweir     // This call must safe access to internal member only.
301cdf0e10cSrcweir     // Set "possible reason" for return and check reject-state then!
302cdf0e10cSrcweir     // User should look for return value first - reason then ...
303cdf0e10cSrcweir     ::osl::MutexGuard aAccessGuard( m_aAccessLock );
304cdf0e10cSrcweir     switch( m_eWorkingMode )
305cdf0e10cSrcweir     {
306cdf0e10cSrcweir         case E_INIT        : eReason = E_UNINITIALIZED ;
307cdf0e10cSrcweir                                 break;
308cdf0e10cSrcweir         case E_WORK        : eReason = E_NOREASON      ;
309cdf0e10cSrcweir                                 break;
310cdf0e10cSrcweir         case E_BEFORECLOSE : eReason = E_INCLOSE       ;
311cdf0e10cSrcweir                                 break;
312cdf0e10cSrcweir         case E_CLOSE       : eReason = E_CLOSED        ;
313cdf0e10cSrcweir                                 break;
314cdf0e10cSrcweir     }
315cdf0e10cSrcweir     return( eReason!=E_NOREASON );
316cdf0e10cSrcweir }
317cdf0e10cSrcweir 
318cdf0e10cSrcweir /*-****************************************************************************************************//**
319cdf0e10cSrcweir     @short      throw any exceptions for rejected calls
320cdf0e10cSrcweir     @descr      If user whish to use our automaticly exception mode we use this impl-method.
321cdf0e10cSrcweir                 We check all combinations of eReason and eExceptionMode and throw right exception with some
322cdf0e10cSrcweir                 descriptions for recipient of it.
323cdf0e10cSrcweir 
324cdf0e10cSrcweir     @seealso    method registerTransaction()
325cdf0e10cSrcweir     @seealso    enum ERejectReason
326cdf0e10cSrcweir     @seealso    enum EExceptionMode
327cdf0e10cSrcweir 
328cdf0e10cSrcweir     @param      "eReason" , reason for rejected call
329cdf0e10cSrcweir     @param      "eMode"   , exception mode - set by user
330cdf0e10cSrcweir     @return     -
331cdf0e10cSrcweir 
332cdf0e10cSrcweir     @onerror    -
333cdf0e10cSrcweir *//*-*****************************************************************************************************/
impl_throwExceptions(EExceptionMode eMode,ERejectReason eReason) const334cdf0e10cSrcweir void TransactionManager::impl_throwExceptions( EExceptionMode eMode, ERejectReason eReason ) const throw( css::uno::RuntimeException, css::lang::DisposedException )
335cdf0e10cSrcweir {
336cdf0e10cSrcweir     if( eMode != E_NOEXCEPTIONS )
337cdf0e10cSrcweir     {
338cdf0e10cSrcweir         switch( eReason )
339cdf0e10cSrcweir         {
340cdf0e10cSrcweir             case E_UNINITIALIZED   :    if( eMode == E_HARDEXCEPTIONS )
341cdf0e10cSrcweir                                         {
342cdf0e10cSrcweir                                             // Help programmer to find out, why this exception is thrown!
343cdf0e10cSrcweir                                             LOG_ERROR( "TransactionManager...", "Owner instance not right initialized yet. Call was rejected! Normaly it's an algorithm error ... wrong usin of class!" )
344cdf0e10cSrcweir                                             //ATTENTION: temp. disabled - till all bad code positions are detected and changed! */
345cdf0e10cSrcweir                                             // throw css::uno::RuntimeException( DECLARE_ASCII("TransactionManager...\nOwner instance not right initialized yet. Call was rejected! Normaly it's an algorithm error ... wrong usin of class!\n" ), css::uno::Reference< css::uno::XInterface >() );
346cdf0e10cSrcweir                                         }
347cdf0e10cSrcweir                                         break;
348cdf0e10cSrcweir             case E_INCLOSE         :    if( eMode == E_HARDEXCEPTIONS )
349cdf0e10cSrcweir                                         {
350cdf0e10cSrcweir                                             // Help programmer to find out, why this exception is thrown!
351cdf0e10cSrcweir                                             LOG_ERROR( "TransactionManager...", "Owner instance stand in close method. Call was rejected!" )
352cdf0e10cSrcweir                                             throw css::lang::DisposedException( DECLARE_ASCII("TransactionManager...\nOwner instance stand in close method. Call was rejected!\n" ), css::uno::Reference< css::uno::XInterface >() );
353cdf0e10cSrcweir                                         }
354cdf0e10cSrcweir                                         break;
355cdf0e10cSrcweir             case E_CLOSED           :   {
356cdf0e10cSrcweir                                             // Help programmer to find out, why this exception is thrown!
357cdf0e10cSrcweir                                             LOG_ERROR( "TransactionManager...", "Owner instance already closed. Call was rejected!" )
358cdf0e10cSrcweir                                             throw css::lang::DisposedException( DECLARE_ASCII("TransactionManager...\nOwner instance already closed. Call was rejected!\n" ), css::uno::Reference< css::uno::XInterface >() );
359cdf0e10cSrcweir                                         }
360cdf0e10cSrcweir             case E_NOREASON         :   {
361cdf0e10cSrcweir                                             // Help programmer to find out
362cdf0e10cSrcweir                                             LOG_ERROR( "TransactionManager...", "Impossible case E_NOREASON!" )
363cdf0e10cSrcweir                                         }
364cdf0e10cSrcweir                                         break;
365cdf0e10cSrcweir             default:                    break; // nothing to do
366cdf0e10cSrcweir         }
367cdf0e10cSrcweir     }
368cdf0e10cSrcweir }
369cdf0e10cSrcweir 
370cdf0e10cSrcweir }	//	namespace framework
371