Avoid potential negative array index access to cached text.
[LibreOffice.git] / chart2 / source / inc / LifeTime.hxx
blobe16edd1e595abeba0faa420f3e62eabcc8c392e4
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
19 #pragma once
21 #include <mutex>
22 #include <osl/conditn.hxx>
23 #include <comphelper/interfacecontainer4.hxx>
24 #include "charttoolsdllapi.hxx"
26 namespace com::sun::star::document { class XStorageChangeListener; }
27 namespace com::sun::star::lang { class XComponent; }
28 namespace com::sun::star::lang { class XEventListener; }
29 namespace com::sun::star::util { class CloseVetoException; }
30 namespace com::sun::star::util { class XCloseListener; }
31 namespace com::sun::star::util { class XCloseable; }
32 namespace com::sun::star::util { class XModifyListener; }
33 namespace com::sun::star::view { class XSelectionChangeListener; }
35 namespace apphelper
38 class OOO_DLLPUBLIC_CHARTTOOLS LifeTimeManager
40 friend class LifeTimeGuard;
41 public:
42 LifeTimeManager( css::lang::XComponent* pComponent );
43 virtual ~LifeTimeManager();
45 bool impl_isDisposed( bool bAssert=true );
46 /// @throws css::uno::RuntimeException
47 bool dispose();
49 mutable std::mutex m_aAccessMutex;
50 ::comphelper::OInterfaceContainerHelper4<css::util::XCloseListener> m_aCloseListeners;
51 ::comphelper::OInterfaceContainerHelper4<css::util::XModifyListener> m_aModifyListeners;
52 ::comphelper::OInterfaceContainerHelper4<css::document::XStorageChangeListener> m_aStorageChangeListeners;
53 ::comphelper::OInterfaceContainerHelper4<css::lang::XEventListener> m_aEventListeners;
54 ::comphelper::OInterfaceContainerHelper4<css::view::XSelectionChangeListener> m_aSelectionChangeListeners;
56 protected:
57 SAL_DLLPRIVATE virtual bool impl_canStartApiCall();
58 SAL_DLLPRIVATE virtual void impl_apiCallCountReachedNull(std::unique_lock<std::mutex>& /*rGuard*/){}
60 SAL_DLLPRIVATE void impl_registerApiCall(bool bLongLastingCall);
61 SAL_DLLPRIVATE void impl_unregisterApiCall(std::unique_lock<std::mutex>& rGuard, bool bLongLastingCall);
63 css::lang::XComponent* m_pComponent;
64 ::osl::Condition m_aNoAccessCountCondition;
65 sal_Int32 m_nAccessCount;
66 bool volatile m_bDisposed;
67 bool volatile m_bInDispose;
68 ::osl::Condition m_aNoLongLastingCallCountCondition;
69 sal_Int32 m_nLongLastingCallCount;
72 class CloseableLifeTimeManager final : public LifeTimeManager
74 css::util::XCloseable* m_pCloseable;
76 ::osl::Condition m_aEndTryClosingCondition;
77 bool volatile m_bClosed;
78 bool volatile m_bInTryClose;
79 //the ownership between model and controller is not clear at first
80 //each controller might consider him as owner of the model first
81 //at start the model is not considered as owner of itself
82 bool volatile m_bOwnership;
84 public:
85 CloseableLifeTimeManager( css::util::XCloseable* pCloseable
86 , css::lang::XComponent* pComponent );
87 virtual ~CloseableLifeTimeManager() override;
89 bool impl_isDisposedOrClosed( bool bAssert=true );
90 /// @throws css::uno::Exception
91 bool g_close_startTryClose(bool bDeliverOwnership);
92 /// @throws css::util::CloseVetoException
93 void g_close_isNeedToCancelLongLastingCalls( bool bDeliverOwnership, css::util::CloseVetoException const & ex );
94 void g_close_endTryClose(bool bDeliverOwnership );
95 void g_close_endTryClose_doClose();
96 /// @throws css::uno::RuntimeException
97 void g_addCloseListener( const css::uno::Reference< css::util::XCloseListener > & xListener );
99 private:
100 virtual bool impl_canStartApiCall() override;
101 virtual void impl_apiCallCountReachedNull(std::unique_lock<std::mutex>& rGuard) override;
103 void impl_setOwnership( bool bDeliverOwnership, bool bMyVeto );
104 void impl_doClose(std::unique_lock<std::mutex>& rGuard);
108 Use this Guard in your ApiCalls to protect access on resources
109 which will be released in dispose.
110 It's guaranteed that the release of resources only starts if your
111 guarded call has finished.
112 ! It's only partly guaranteed that this resources will not change during the call.
113 See the example for details.
115 This class is to be used as described in the example.
117 If this guard is used in all api calls of an XCloseable object
118 it's guaranteed that the closeable will close itself after finishing the last call
119 if it should do so.
121 ::ApiCall
123 //hold no mutex!!!
124 LifeTimeGuard aLifeTimeGuard(m_aLifeTimeManager);
126 //mutex is acquired; call is not registered
128 if(!aLifeTimeGuard.startApiCall())
129 return ; //behave as passive as possible, if disposed or closed
131 //mutex is acquired, call is registered
133 //you might access some private members here
134 //but then you need to protect access to these members always like this
135 //never call to the outside here
138 aLifeTimeGuard.clear(); //!!!
140 //Mutex is released, the running call is still registered
141 //this call will finish before the 'release-section' in dispose is allowed to start
144 //you might access some private members here guarded with your own mutex
145 //but release your mutex at the end of this block
148 //you can call to the outside (without holding the mutex) without becoming disposed
150 //End of method -> ~LifeTimeGuard
151 //-> call is unregistered
152 //-> this object might be disposed now
155 your XComponent::dispose method has to be implemented in the following way:
157 ::dispose()
159 //hold no mutex!!!
160 if( !m_aLifeTimeManager.dispose() )
161 return;
163 //--release all resources and references
169 class LifeTimeGuard
172 public:
173 LifeTimeGuard( LifeTimeManager& rManager )
174 : m_guard( rManager.m_aAccessMutex )
175 , m_rManager(rManager)
176 , m_bCallRegistered(false)
177 , m_bLongLastingCallRegistered(false)
181 bool startApiCall(bool bLongLastingCall=false);
182 ~LifeTimeGuard();
183 void clear() { m_guard.unlock(); }
185 private:
186 std::unique_lock<std::mutex> m_guard;
187 LifeTimeManager& m_rManager;
188 bool m_bCallRegistered;
189 bool m_bLongLastingCallRegistered;
191 private:
192 LifeTimeGuard( const LifeTimeGuard& ) = delete;
193 LifeTimeGuard& operator= ( const LifeTimeGuard& ) = delete;
196 }//end namespace apphelper
198 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */