Coverage Report

Created: 2026-03-31 11:00

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/include/tools/lazydelete.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
20
#pragma once
21
22
#include <tools/toolsdllapi.h>
23
24
#include <com/sun/star/lang/XComponent.hpp>
25
#include <rtl/ref.hxx>
26
27
#include <optional>
28
29
namespace tools
30
{
31
    /*
32
    You may not access some objects after DeInitVCL has been called this includes their destruction
33
    therefore disallowing the existence of static object like e.g. a static Bitmap
34
    To work around this use DeleteOnDeinit<Bitmap> which will allow you to have a static object container,
35
    that will have its contents destroyed on DeinitVCL. The single drawback is that you need to check on the
36
    container object whether it still contains content before actually accessing it.
37
38
    caveat: when constructing a vcl object, you certainly want to ensure that InitVCL has run already.
39
    However this is not necessarily the case when using a class static member or a file level static variable.
40
    In these cases make judicious use of the set() method of DeleteOnDeinit, but beware of the changing
41
    ownership.
42
43
    example use case: use a lazy initialized on call Bitmap in a paint method. Of course a paint method
44
    would not normally be called after DeInitVCL anyway, so the check might not be necessary in a
45
    Window::Paint implementation, but always checking is a good idea.
46
47
    SomeWindow::Paint()
48
    {
49
        static tools::DeleteOnDeinit< Bitmap > aBmp( ... );
50
51
        if( aBmp.get() ) // check whether DeInitVCL has been called already
52
            DrawBitmapEx( Point( 10, 10 ), *aBmp );
53
    }
54
    */
55
56
    class TOOLS_DLLPUBLIC DeleteOnDeinitBase
57
    {
58
    public:
59
        static void ImplDeleteOnDeInit();
60
        virtual ~DeleteOnDeinitBase();
61
    protected:
62
        static void addDeinitContainer( DeleteOnDeinitBase* i_pContainer );
63
64
        virtual void doCleanup() = 0;
65
    };
66
67
    enum class DeleteOnDeinitFlag { Empty };
68
69
    template < typename T >
70
    class DeleteOnDeinit final : public DeleteOnDeinitBase
71
    {
72
        std::optional<T> m_pT;
73
0
        virtual void doCleanup() override { m_pT.reset(); }
Unexecuted instantiation: tools::DeleteOnDeinit<Wallpaper>::doCleanup()
Unexecuted instantiation: textline.cxx:tools::DeleteOnDeinit<(anonymous namespace)::WavyLineCache>::doCleanup()
Unexecuted instantiation: TextLayoutCache.cxx:tools::DeleteOnDeinit<vcl::text::(anonymous namespace)::TextLayoutCacheMap>::doCleanup()
Unexecuted instantiation: tools::DeleteOnDeinit<SalLayoutGlyphsCache>::doCleanup()
Unexecuted instantiation: tools::DeleteOnDeinit<std::__1::vector<com::sun::star::datatransfer::DataFlavor, std::__1::allocator<com::sun::star::datatransfer::DataFlavor> > >::doCleanup()
Unexecuted instantiation: tools::DeleteOnDeinit<com::sun::star::uno::Reference<com::sun::star::i18n::XBreakIterator> >::doCleanup()
Unexecuted instantiation: vclhelperbufferdevice.cxx:tools::DeleteOnDeinit<(anonymous namespace)::VDevBuffer>::doCleanup()
Unexecuted instantiation: tools::DeleteOnDeinit<rtl::Reference<SfxItemPool> >::doCleanup()
Unexecuted instantiation: tools::DeleteOnDeinit<EditDLL>::doCleanup()
Unexecuted instantiation: svdhdl.cxx:tools::DeleteOnDeinit<(anonymous namespace)::SdrHdlBitmapSet>::doCleanup()
Unexecuted instantiation: tools::DeleteOnDeinit<drawinglayer::primitive2d::DiscreteShadow>::doCleanup()
Unexecuted instantiation: tools::DeleteOnDeinit<Bitmap>::doCleanup()
Unexecuted instantiation: tools::DeleteOnDeinit<com::sun::star::uno::Reference<com::sun::star::i18n::XLocaleData4> >::doCleanup()
Unexecuted instantiation: tools::DeleteOnDeinit<filter::config::FilterCache>::doCleanup()
Unexecuted instantiation: tools::DeleteOnDeinit<std::__1::unordered_map<int, rtl::Reference<LOKClipboard>, std::__1::hash<int>, std::__1::equal_to<int>, std::__1::allocator<std::__1::pair<int const, rtl::Reference<LOKClipboard> > > > >::doCleanup()
Unexecuted instantiation: tools::DeleteOnDeinit<VclPtr<OutputDevice> >::doCleanup()
Unexecuted instantiation: tools::DeleteOnDeinit<std::__1::shared_ptr<weld::Window> >::doCleanup()
74
    public:
75
        template <class... Args >
76
        DeleteOnDeinit(Args&&... args )
77
94
        {
78
94
            m_pT.emplace(args...);
79
94
            addDeinitContainer( this );
80
94
        }
Unexecuted instantiation: tools::DeleteOnDeinit<Wallpaper>::DeleteOnDeinit<Color const&>(Color const&)
Unexecuted instantiation: textline.cxx:tools::DeleteOnDeinit<(anonymous namespace)::WavyLineCache>::DeleteOnDeinit<>()
TextLayoutCache.cxx:tools::DeleteOnDeinit<vcl::text::(anonymous namespace)::TextLayoutCacheMap>::DeleteOnDeinit<long>(long&&)
Line
Count
Source
77
29
        {
78
29
            m_pT.emplace(args...);
79
29
            addDeinitContainer( this );
80
29
        }
tools::DeleteOnDeinit<SalLayoutGlyphsCache>::DeleteOnDeinit<long>(long&&)
Line
Count
Source
77
14
        {
78
14
            m_pT.emplace(args...);
79
14
            addDeinitContainer( this );
80
14
        }
tools::DeleteOnDeinit<std::__1::vector<com::sun::star::datatransfer::DataFlavor, std::__1::allocator<com::sun::star::datatransfer::DataFlavor> > >::DeleteOnDeinit<>()
Line
Count
Source
77
2
        {
78
2
            m_pT.emplace(args...);
79
2
            addDeinitContainer( this );
80
2
        }
tools::DeleteOnDeinit<com::sun::star::uno::Reference<com::sun::star::i18n::XBreakIterator> >::DeleteOnDeinit<>()
Line
Count
Source
77
4
        {
78
4
            m_pT.emplace(args...);
79
4
            addDeinitContainer( this );
80
4
        }
Unexecuted instantiation: vclhelperbufferdevice.cxx:tools::DeleteOnDeinit<(anonymous namespace)::VDevBuffer>::DeleteOnDeinit<>()
tools::DeleteOnDeinit<rtl::Reference<SfxItemPool> >::DeleteOnDeinit<rtl::Reference<SfxItemPool> >(rtl::Reference<SfxItemPool>&&)
Line
Count
Source
77
13
        {
78
13
            m_pT.emplace(args...);
79
13
            addDeinitContainer( this );
80
13
        }
tools::DeleteOnDeinit<EditDLL>::DeleteOnDeinit<>()
Line
Count
Source
77
25
        {
78
25
            m_pT.emplace(args...);
79
25
            addDeinitContainer( this );
80
25
        }
Unexecuted instantiation: svdhdl.cxx:tools::DeleteOnDeinit<(anonymous namespace)::SdrHdlBitmapSet>::DeleteOnDeinit<>()
Unexecuted instantiation: tools::DeleteOnDeinit<drawinglayer::primitive2d::DiscreteShadow>::DeleteOnDeinit<Bitmap>(Bitmap&&)
tools::DeleteOnDeinit<filter::config::FilterCache>::DeleteOnDeinit<>()
Line
Count
Source
77
4
        {
78
4
            m_pT.emplace(args...);
79
4
            addDeinitContainer( this );
80
4
        }
Unexecuted instantiation: tools::DeleteOnDeinit<std::__1::unordered_map<int, rtl::Reference<LOKClipboard>, std::__1::hash<int>, std::__1::equal_to<int>, std::__1::allocator<std::__1::pair<int const, rtl::Reference<LOKClipboard> > > > >::DeleteOnDeinit<>()
Unexecuted instantiation: tools::DeleteOnDeinit<Bitmap>::DeleteOnDeinit<>()
tools::DeleteOnDeinit<VclPtr<OutputDevice> >::DeleteOnDeinit<>()
Line
Count
Source
77
2
        {
78
2
            m_pT.emplace(args...);
79
2
            addDeinitContainer( this );
80
2
        }
tools::DeleteOnDeinit<std::__1::shared_ptr<weld::Window> >::DeleteOnDeinit<>()
Line
Count
Source
77
1
        {
78
1
            m_pT.emplace(args...);
79
1
            addDeinitContainer( this );
80
1
        }
81
        DeleteOnDeinit(DeleteOnDeinitFlag)
82
1
        {
83
1
            addDeinitContainer( this );
84
1
        }
Unexecuted instantiation: tools::DeleteOnDeinit<Bitmap>::DeleteOnDeinit(tools::DeleteOnDeinitFlag)
tools::DeleteOnDeinit<com::sun::star::uno::Reference<com::sun::star::i18n::XLocaleData4> >::DeleteOnDeinit(tools::DeleteOnDeinitFlag)
Line
Count
Source
82
1
        {
83
1
            addDeinitContainer( this );
84
1
        }
85
86
        // get contents
87
27.3M
        T* get() { return m_pT ? &*m_pT : nullptr; }
Unexecuted instantiation: tools::DeleteOnDeinit<Wallpaper>::get()
Unexecuted instantiation: textline.cxx:tools::DeleteOnDeinit<(anonymous namespace)::WavyLineCache>::get()
TextLayoutCache.cxx:tools::DeleteOnDeinit<vcl::text::(anonymous namespace)::TextLayoutCacheMap>::get()
Line
Count
Source
87
14.3M
        T* get() { return m_pT ? &*m_pT : nullptr; }
tools::DeleteOnDeinit<SalLayoutGlyphsCache>::get()
Line
Count
Source
87
8.44M
        T* get() { return m_pT ? &*m_pT : nullptr; }
tools::DeleteOnDeinit<std::__1::vector<com::sun::star::datatransfer::DataFlavor, std::__1::allocator<com::sun::star::datatransfer::DataFlavor> > >::get()
Line
Count
Source
87
848
        T* get() { return m_pT ? &*m_pT : nullptr; }
tools::DeleteOnDeinit<com::sun::star::uno::Reference<com::sun::star::i18n::XBreakIterator> >::get()
Line
Count
Source
87
2.43k
        T* get() { return m_pT ? &*m_pT : nullptr; }
Unexecuted instantiation: vclhelperbufferdevice.cxx:tools::DeleteOnDeinit<(anonymous namespace)::VDevBuffer>::get()
tools::DeleteOnDeinit<rtl::Reference<SfxItemPool> >::get()
Line
Count
Source
87
17
        T* get() { return m_pT ? &*m_pT : nullptr; }
tools::DeleteOnDeinit<EditDLL>::get()
Line
Count
Source
87
4.14M
        T* get() { return m_pT ? &*m_pT : nullptr; }
Unexecuted instantiation: svdhdl.cxx:tools::DeleteOnDeinit<(anonymous namespace)::SdrHdlBitmapSet>::get()
Unexecuted instantiation: tools::DeleteOnDeinit<drawinglayer::primitive2d::DiscreteShadow>::get()
Unexecuted instantiation: tools::DeleteOnDeinit<Bitmap>::get()
tools::DeleteOnDeinit<com::sun::star::uno::Reference<com::sun::star::i18n::XLocaleData4> >::get()
Line
Count
Source
87
10.6k
        T* get() { return m_pT ? &*m_pT : nullptr; }
tools::DeleteOnDeinit<filter::config::FilterCache>::get()
Line
Count
Source
87
30.0k
        T* get() { return m_pT ? &*m_pT : nullptr; }
Unexecuted instantiation: tools::DeleteOnDeinit<std::__1::unordered_map<int, rtl::Reference<LOKClipboard>, std::__1::hash<int>, std::__1::equal_to<int>, std::__1::allocator<std::__1::pair<int const, rtl::Reference<LOKClipboard> > > > >::get()
tools::DeleteOnDeinit<VclPtr<OutputDevice> >::get()
Line
Count
Source
87
368k
        T* get() { return m_pT ? &*m_pT : nullptr; }
tools::DeleteOnDeinit<std::__1::shared_ptr<weld::Window> >::get()
Line
Count
Source
87
92
        T* get() { return m_pT ? &*m_pT : nullptr; }
88
89
        // set contents, returning old contents
90
        // ownership is transferred !
91
        template <class... Args >
92
        std::optional<T> set(Args&&... args)
93
5
        {
94
5
            auto pOld = std::move(m_pT);
95
5
            m_pT.emplace(args...);
96
5
            return pOld;
97
5
        }
std::__1::optional<com::sun::star::uno::Reference<com::sun::star::i18n::XBreakIterator> > tools::DeleteOnDeinit<com::sun::star::uno::Reference<com::sun::star::i18n::XBreakIterator> >::set<com::sun::star::uno::Reference<com::sun::star::i18n::XBreakIterator> >(com::sun::star::uno::Reference<com::sun::star::i18n::XBreakIterator>&&)
Line
Count
Source
93
4
        {
94
4
            auto pOld = std::move(m_pT);
95
4
            m_pT.emplace(args...);
96
4
            return pOld;
97
4
        }
Unexecuted instantiation: std::__1::optional<Bitmap> tools::DeleteOnDeinit<Bitmap>::set<Bitmap&>(Bitmap&)
std::__1::optional<com::sun::star::uno::Reference<com::sun::star::i18n::XLocaleData4> > tools::DeleteOnDeinit<com::sun::star::uno::Reference<com::sun::star::i18n::XLocaleData4> >::set<com::sun::star::uno::Reference<com::sun::star::i18n::XLocaleData4> >(com::sun::star::uno::Reference<com::sun::star::i18n::XLocaleData4>&&)
Line
Count
Source
93
1
        {
94
1
            auto pOld = std::move(m_pT);
95
1
            m_pT.emplace(args...);
96
1
            return pOld;
97
1
        }
Unexecuted instantiation: std::__1::optional<Bitmap> tools::DeleteOnDeinit<Bitmap>::set<Bitmap>(Bitmap&&)
98
    };
99
100
    /** Similar to DeleteOnDeinit, the DeleteUnoReferenceOnDeinit
101
        template class makes sure that a static UNO object is disposed
102
        and released at the right time.
103
104
        Use like
105
            static DeleteUnoReferenceOnDeinit<lang::XMultiServiceFactory>
106
                xStaticFactory (\<create factory object>);
107
            Reference<lang::XMultiServiceFactory> xFactory (xStaticFactory.get());
108
            if (xFactory.is())
109
                \<do something with xFactory>
110
    */
111
    template <typename I>
112
    class DeleteUnoReferenceOnDeinit final : public tools::DeleteOnDeinitBase
113
    {
114
        css::uno::Reference<I> m_xI;
115
0
        virtual void doCleanup() override { set(nullptr); }
116
    public:
117
1
        DeleteUnoReferenceOnDeinit(css::uno::Reference<I> _xI ) : m_xI(std::move( _xI )) {
118
1
            addDeinitContainer( this ); }
119
120
12
        css::uno::Reference<I> get() { return m_xI; }
121
122
        void set (const css::uno::Reference<I>& r_xNew )
123
0
        {
124
0
            css::uno::Reference< css::lang::XComponent> xComponent (m_xI, css::uno::UNO_QUERY);
125
0
            m_xI = r_xNew;
126
0
            if (xComponent.is()) try
127
0
            {
128
0
                xComponent->dispose();
129
0
            }
130
0
            catch( css::uno::Exception& )
131
0
            {
132
0
            }
133
0
        }
134
    };
135
136
    /** Similar to DeleteOnDeinit, the DeleteRtlReferenceOnDeinit
137
        template class makes sure that a static rtl::Reference managed object is disposed
138
        and released at the right time.
139
140
        Use like
141
            static DeleteUnoReferenceOnDeinit<Foo> xStaticFactory (new Foo);
142
            rtl::Reference<Foo> xFactory (xStaticFactory.get());
143
            if (xFactory.is())
144
                \<do something with xFactory>
145
    */
146
    template <typename I>
147
    class DeleteRtlReferenceOnDeinit final : public tools::DeleteOnDeinitBase
148
    {
149
        rtl::Reference<I> m_xI;
150
0
        virtual void doCleanup() override { set(nullptr); }
151
    public:
152
15
        DeleteRtlReferenceOnDeinit(rtl::Reference<I> _xI ) : m_xI(std::move( _xI )) {
153
15
            addDeinitContainer( this ); }
154
155
423k
        rtl::Reference<I> get() { return m_xI; }
156
157
        void set (const rtl::Reference<I>& r_xNew )
158
0
        {
159
0
            m_xI = r_xNew;
160
0
        }
161
    };
162
}
163
164
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */