/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: */ |