LibreOffice Module framework (master) 1
transactionmanager.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 */
19
20#include <sal/config.h>
21#include <sal/log.hxx>
22
24
25#include <com/sun/star/lang/DisposedException.hpp>
26
27namespace framework{
28
29/*-************************************************************************************************************
30 @short standard ctor
31 @descr Initialize instance with right start values for correct working.
32*//*-*************************************************************************************************************/
34 : m_eWorkingMode ( E_INIT )
35 , m_nTransactionCount ( 0 )
36{
38}
39
40/*-************************************************************************************************************
41 @short standard dtor
42*//*-*************************************************************************************************************/
44{
45}
46
47/*-****************************************************************************************************
48 @short set new working mode
49 @descr These implementation knows for states of working: E_INIT, E_WORK, E_BEFORECLOSE, E_CLOSE
50 You can step during this ones only from the left to the right side and start at left side again!
51 (This is necessary e.g. for refcounted objects!)
52 This call will block till all current existing transactions was finished.
53 Following results can occur:
54 E_INIT : All requests on this implementation are refused.
55 It's your decision to react in a right way.
56
57 E_WORK : The object can work now. The full functionality is available.
58
59 E_BEFORECLOSE : The object start the closing mechanism ... but sometimes
60 e.g. the dispose() method need to call some private methods.
61 These some special methods should use E_SOFTEXCEPTIONS
62 to detect this special case!
63
64 E_CLOSE : Object is already dead! All further requests will be refused.
65 It's your decision to react in a right way.
66 @param "eMode", is the new mode - but we don't accept setting mode in wrong order!
67 @onerror We do nothing.
68*//*-*****************************************************************************************************/
70{
71 // Safe member access.
72 bool bWaitFor = false;
73 {
74 std::unique_lock aAccessGuard(m_aAccessLock);
75 // Change working mode first!
76 if (
77 (m_eWorkingMode == E_INIT && eMode == E_WORK) ||
81 )
82 {
85 {
86 bWaitFor = true;
87 }
88 }
89 }
90 // Wait for current existing transactions then!
91 // (Only necessary for changing to E_BEFORECLOSE or E_CLOSE!...
92 // otherwise; if you wait at setting E_WORK another thread could finish an acquire-call during our unlock() and wait() call
93 // ... and we will wait forever here!!!)
94 // Don't forget to release access mutex before.
95 if( bWaitFor )
96 {
98 }
99}
100
101/*-****************************************************************************************************
102 @short get current working mode
103 @descr If you stand in your close() or init() method ... but don't know
104 if you called more than ones(!) ... you can use this function to get
105 right information.
106 e.g: You have a method init() which is used to change working mode from
107 E_INIT to E_WORK and should be used to initialize some member too ...
108 What should you do:
109
110 void init( sal_Int32 nValue )
111 {
112 // Reject this call if our transaction manager say: "Object already initialized!"
113 // Otherwise initialize your member.
114 if( m_aTransactionManager.getWorkingMode() == E_INIT )
115 {
116 // Object is uninitialized ...
117 // Make member access threadsafe!
118 Guard aGuard( m_aMutex );
119
120 // Check working mode again .. because another instance could be faster.
121 // (It's possible to set this guard at first of this method too!)
122 if( m_aTransactionManager.getWorkingMode() == E_INIT )
123 {
124 m_aMember = nValue;
125
126 // Object is initialized now ... set working mode to E_WORK!
127 m_aTransactionManager.setWorkingMode( E_WORK );
128 }
129 }
130 }
131
132 @seealso method setWorkingMode()
133 @return Current set mode.
134
135 @onerror No error should occur.
136*//*-*****************************************************************************************************/
138{
139 // Synchronize access to internal member!
140 std::unique_lock aAccessLock( m_aAccessLock );
141 return m_eWorkingMode;
142}
143
144/*-****************************************************************************************************
145 @short start new transaction
146 @descr A guard should use this method to start a new transaction. He should look for rejected
147 calls to by using parameter eMode and eReason.
148 If call was not rejected your transaction will be non breakable during releasing your transaction
149 guard! BUT ... your code isn't threadsafe then! It's a transaction manager only...
150
151 @seealso method unregisterTransaction()
152
153 @param "eMode" ,used to enable/disable throwing exceptions automatically for rejected calls
154*//*-*****************************************************************************************************/
156{
157 std::unique_lock aAccessGuard( m_aAccessLock );
158 switch( m_eWorkingMode )
159 {
160 case E_INIT:
161 if( eMode == E_HARDEXCEPTIONS )
162 {
163 // Help programmer to find out, why this exception is thrown!
164 SAL_WARN( "fwk", "TransactionManager...: Owner instance not correctly initialized yet. Call was rejected! Normally it's an algorithm error ... wrong use of class!" );
165 //ATTENTION: temp. disabled - till all bad code positions are detected and changed! */
166 // throw css::uno::RuntimeException( "TransactionManager.: Owner instance not right initialized yet. Call was rejected! Normally it's an algorithm error... wrong using of class!\n", css::uno::Reference< css::uno::XInterface >() );
167 }
168 break;
169 case E_WORK:
170 break;
171 case E_BEFORECLOSE:
172 if( eMode == E_HARDEXCEPTIONS )
173 {
174 // Help programmer to find out, why this exception is thrown!
175 SAL_WARN( "fwk", "TransactionManager...: Owner instance stand in close method. Call was rejected!" );
176 throw css::lang::DisposedException( "TransactionManager: Owner instance stand in close method. Call was rejected!" );
177 }
178 break;
179 case E_CLOSE:
180 // Help programmer to find out, why this exception is thrown!
181 SAL_WARN( "fwk", "TransactionManager...: Owner instance already closed. Call was rejected!" );
182 throw css::lang::DisposedException( "TransactionManager: Owner instance already closed. Call was rejected!" );
183 }
184
185 // Register this new transaction.
186 // If it is the first one .. close gate to disable changing of working mode.
188 if( m_nTransactionCount == 1 )
189 {
191 }
192}
193
194/*-****************************************************************************************************
195 @short finish transaction
196 @descr A guard should call this method to release current transaction.
197
198 @seealso method registerTransaction()
199*//*-*****************************************************************************************************/
201{
202 // This call could not rejected!
203 // Safe access to internal member.
204 std::unique_lock aAccessGuard( m_aAccessLock );
205
206 // Deregister this transaction.
207 // If it was the last one ... open gate to enable changing of working mode!
208 // (see setWorkingMode())
209
211 if( m_nTransactionCount == 0 )
212 {
214 }
215}
216
217} // namespace framework
218
219/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
void close()
Definition: gate.hxx:98
void open()
Definition: gate.hxx:81
void wait()
Definition: gate.hxx:118
sal_Int32 m_nTransactionCount
current working mode of object which use this manager (used to reject calls at wrong time)
void registerTransaction(EExceptionMode eMode)
Gate m_aBarrier
regulate access on internal member of this instance
void setWorkingMode(EWorkingMode eMode)
EWorkingMode m_eWorkingMode
used to block transactions requests during change or work mode
Mode eMode
#define SAL_WARN(area, stream)