Coverage Report

Created: 2026-05-16 09:25

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/chart2/source/inc/LifeTime.hxx
Line
Count
Source
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
#pragma once
20
21
#include <mutex>
22
#include <osl/conditn.hxx>
23
#include <comphelper/interfacecontainer4.hxx>
24
25
namespace com::sun::star::document { class XStorageChangeListener; }
26
namespace com::sun::star::lang { class XComponent; }
27
namespace com::sun::star::lang { class XEventListener; }
28
namespace com::sun::star::util { class CloseVetoException; }
29
namespace com::sun::star::util { class XCloseListener; }
30
namespace com::sun::star::util { class XCloseable; }
31
namespace com::sun::star::util { class XModifyListener; }
32
namespace com::sun::star::view { class XSelectionChangeListener; }
33
34
namespace apphelper
35
{
36
37
class LifeTimeManager
38
{
39
friend class LifeTimeGuard;
40
public:
41
    LifeTimeManager( css::lang::XComponent* pComponent );
42
    virtual ~LifeTimeManager();
43
44
    bool        impl_isDisposed( bool bAssert=true );
45
    /// @throws css::uno::RuntimeException
46
    bool    dispose();
47
48
    mutable std::mutex                    m_aAccessMutex;
49
    ::comphelper::OInterfaceContainerHelper4<css::util::XCloseListener> m_aCloseListeners;
50
    ::comphelper::OInterfaceContainerHelper4<css::util::XModifyListener> m_aModifyListeners;
51
    ::comphelper::OInterfaceContainerHelper4<css::document::XStorageChangeListener> m_aStorageChangeListeners;
52
    ::comphelper::OInterfaceContainerHelper4<css::lang::XEventListener> m_aEventListeners;
53
    ::comphelper::OInterfaceContainerHelper4<css::view::XSelectionChangeListener> m_aSelectionChangeListeners;
54
55
protected:
56
    virtual bool impl_canStartApiCall();
57
0
    virtual void impl_apiCallCountReachedNull(std::unique_lock<std::mutex>& /*rGuard*/){}
58
59
    void        impl_registerApiCall(bool bLongLastingCall);
60
    void        impl_unregisterApiCall(std::unique_lock<std::mutex>& rGuard, bool bLongLastingCall);
61
62
    css::lang::XComponent*     m_pComponent;
63
    ::osl::Condition        m_aNoAccessCountCondition;
64
    sal_Int32               m_nAccessCount;
65
    bool volatile       m_bDisposed;
66
    bool volatile       m_bInDispose;
67
    ::osl::Condition        m_aNoLongLastingCallCountCondition;
68
    sal_Int32               m_nLongLastingCallCount;
69
};
70
71
class CloseableLifeTimeManager final : public LifeTimeManager
72
{
73
    css::util::XCloseable*         m_pCloseable;
74
75
    ::osl::Condition    m_aEndTryClosingCondition;
76
    bool                m_bClosed;
77
    bool                m_bInTryClose;
78
    //the ownership between model and controller is not clear at first
79
    //each controller might consider him as owner of the model first
80
    //at start the model is not considered as owner of itself
81
    bool                m_bOwnership;
82
83
public:
84
    CloseableLifeTimeManager( css::util::XCloseable* pCloseable
85
        , css::lang::XComponent* pComponent );
86
    virtual ~CloseableLifeTimeManager() override;
87
88
    bool    impl_isDisposedOrClosed( bool bAssert=true );
89
/// @throws css::uno::Exception
90
    bool    g_close_startTryClose(bool bDeliverOwnership);
91
/// @throws css::util::CloseVetoException
92
    void    g_close_isNeedToCancelLongLastingCalls( bool bDeliverOwnership, css::util::CloseVetoException const & ex );
93
    void    g_close_endTryClose();
94
    void    g_close_endTryClose_doClose();
95
/// @throws css::uno::RuntimeException
96
    void    g_addCloseListener( const css::uno::Reference< css::util::XCloseListener > & xListener );
97
98
private:
99
    virtual bool    impl_canStartApiCall() override;
100
    virtual void impl_apiCallCountReachedNull(std::unique_lock<std::mutex>& rGuard) override;
101
102
    void        impl_doClose(std::unique_lock<std::mutex>& rGuard);
103
};
104
105
/*
106
Use this Guard in your ApiCalls to protect access on resources
107
which will be released in dispose.
108
It's guaranteed that the release of resources only starts if your
109
guarded call has finished.
110
! It's only partly guaranteed that this resources will not change during the call.
111
See the example for details.
112
113
This class is to be used as described in the example.
114
115
If this guard is used in all api calls of an XCloseable object
116
it's guaranteed that the closeable will close itself after finishing the last call
117
if it should do so.
118
119
  ::ApiCall
120
{
121
    //hold no mutex!!!
122
    LifeTimeGuard aLifeTimeGuard(m_aLifeTimeManager);
123
124
    //mutex is acquired; call is not registered
125
126
    if(!aLifeTimeGuard.startApiCall())
127
        return ; //behave as passive as possible, if disposed or closed
128
129
    //mutex is acquired, call is registered
130
    {
131
        //you might access some private members here
132
        //but then you need to protect access to these members always like this
133
        //never call to the outside here
134
    }
135
136
    aLifeTimeGuard.clear(); //!!!
137
138
      //Mutex is released, the running call is still registered
139
    //this call will finish before the 'release-section' in dispose is allowed to start
140
141
    {
142
        //you might access some private members here guarded with your own mutex
143
        //but release your mutex at the end of this block
144
    }
145
146
    //you can call to the outside (without holding the mutex) without becoming disposed
147
148
    //End of method -> ~LifeTimeGuard
149
    //-> call is unregistered
150
    //-> this object might be disposed now
151
}
152
153
your XComponent::dispose method has to be implemented in the following way:
154
155
    ::dispose()
156
{
157
    //hold no mutex!!!
158
    if( !m_aLifeTimeManager.dispose() )
159
        return;
160
161
    //--release all resources and references
162
163
}
164
165
*/
166
167
class LifeTimeGuard
168
{
169
170
public:
171
    LifeTimeGuard( LifeTimeManager& rManager )
172
0
        : m_guard( rManager.m_aAccessMutex )
173
0
        , m_rManager(rManager)
174
0
        , m_bCallRegistered(false)
175
0
        , m_bLongLastingCallRegistered(false)
176
0
    {
177
178
0
    }
179
    bool startApiCall(bool bLongLastingCall=false);
180
    ~LifeTimeGuard();
181
0
    void clear() { m_guard.unlock(); }
182
183
private:
184
    std::unique_lock<std::mutex> m_guard;
185
    LifeTimeManager&    m_rManager;
186
    bool            m_bCallRegistered;
187
    bool            m_bLongLastingCallRegistered;
188
189
private:
190
    LifeTimeGuard( const LifeTimeGuard& ) = delete;
191
    LifeTimeGuard& operator= ( const LifeTimeGuard& ) = delete;
192
};
193
194
}//end namespace apphelper
195
196
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */