LibreOffice Module comphelper (master) 1
unique_disposing_ptr.hxx
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
10#ifndef INCLUDED_COMPHELPER_UNIQUE_DISPOSING_PTR_HXX
11#define INCLUDED_COMPHELPER_UNIQUE_DISPOSING_PTR_HXX
12
13#include <memory>
15
16#include <com/sun/star/lang/XComponent.hpp>
17#include <com/sun/star/frame/XDesktop.hpp>
18#include <com/sun/star/lang/XServiceInfo.hpp>
19
20#include <o3tl/deleter.hxx>
21#include <utility>
22#include <vcl/svapp.hxx>
23
24namespace comphelper
25{
26//Similar to std::unique_ptr, except additionally releases the ptr on XComponent::disposing and/or XTerminateListener::notifyTermination if supported
27template<class T> class unique_disposing_ptr
28{
29private:
30 std::unique_ptr<T, o3tl::default_delete<T>> m_xItem;
31 css::uno::Reference< css::frame::XTerminateListener> m_xTerminateListener;
32
35public:
36 unique_disposing_ptr( const css::uno::Reference< css::lang::XComponent > &rComponent, T * p = nullptr, bool bComponent = false)
37 : m_xItem(p)
38 {
39 m_xTerminateListener = new TerminateListener(rComponent, *this, bComponent);
40 }
41
42 virtual void reset(T * p = nullptr)
43 {
44 m_xItem.reset(p);
45 }
46
47 T & operator*() const
48 {
49 return *m_xItem;
50 }
51
52 T * get() const
53 {
54 return m_xItem.get();
55 }
56
57 T * operator->() const
58 {
59 return m_xItem.get();
60 }
61
62 operator bool () const
63 {
64 return static_cast< bool >(m_xItem);
65 }
66
67 virtual ~unique_disposing_ptr() COVERITY_NOEXCEPT_FALSE
68 {
69 reset();
70 }
71private:
72 class TerminateListener final : public ::cppu::WeakImplHelper< css::frame::XTerminateListener,
73 css::lang::XServiceInfo>
74 {
75 private:
76 css::uno::Reference< css::lang::XComponent > m_xComponent;
78 bool const mbComponentDLL;
79 public:
80 TerminateListener(css::uno::Reference< css::lang::XComponent > xComponent,
81 unique_disposing_ptr<T>& rItem, bool bComponentDLL) :
82 m_xComponent(std::move(xComponent)),
83 m_rItem(rItem),
84 mbComponentDLL(bComponentDLL)
85 {
86 if (m_xComponent.is())
87 {
88 css::uno::Reference< css::frame::XDesktop> xDesktop(m_xComponent, css::uno::UNO_QUERY);
89 if (xDesktop.is())
90 xDesktop->addTerminateListener(this);
91 else
92 m_xComponent->addEventListener(this);
93 }
94 }
95
96 virtual ~TerminateListener() override
97 {
98 if ( m_xComponent.is() )
99 {
100 css::uno::Reference< css::frame::XDesktop> xDesktop(m_xComponent, css::uno::UNO_QUERY);
101 if (xDesktop.is())
102 xDesktop->removeTerminateListener(this);
103 else
104 m_xComponent->removeEventListener(this);
105 }
106 }
107
108 // XEventListener
109 virtual void SAL_CALL disposing( const css::lang::EventObject& rEvt ) override
110 {
111 bool shutDown = (rEvt.Source == m_xComponent);
112
113 if (shutDown && m_xComponent.is())
114 {
115 css::uno::Reference< css::frame::XDesktop> xDesktop(m_xComponent, css::uno::UNO_QUERY);
116 if (xDesktop.is())
117 xDesktop->removeTerminateListener(this);
118 else
119 m_xComponent->removeEventListener(this);
120 m_xComponent.clear();
121 }
122
123 if (shutDown)
124 m_rItem.reset();
125 }
126
127 // XTerminateListener
128 virtual void SAL_CALL queryTermination( const css::lang::EventObject& ) override
129 {
130 }
131
132 virtual void SAL_CALL notifyTermination( const css::lang::EventObject& rEvt ) override
133 {
134 disposing(rEvt);
135 }
136
137 virtual OUString SAL_CALL getImplementationName() override
138 {
139 if (mbComponentDLL)
140 return "com.sun.star.comp.ComponentDLLListener";
141 else
142 return "com.sun.star.comp.DisposingTerminateListener";
143 }
144
145 virtual sal_Bool SAL_CALL supportsService(const OUString& /*rName*/) override
146 {
147 return false;
148 }
149
150 virtual css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames() override
151 {
152 return css::uno::Sequence<OUString>();
153 }
154 };
155};
156
157//Something like an OutputDevice requires the SolarMutex to be taken before use
158//for threadsafety. The user can ensure this, except in the case of its dtor
159//being called from reset due to a terminate on the XComponent being called
160//from an arbitrary thread
162 : public unique_disposing_ptr<T>
163{
164public:
165 unique_disposing_solar_mutex_reset_ptr( const css::uno::Reference< css::lang::XComponent > &rComponent, T * p = nullptr, bool bComponent = false)
166 : unique_disposing_ptr<T>(rComponent, p, bComponent)
167 {
168 }
169
170 virtual void reset(T * p = nullptr) override
171 {
172 SolarMutexGuard aGuard;
174 }
175
177 {
179 reset();
180 }
181};
182
183}
184
185#endif
186
187/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
static SolarMutex * get()
Help components to get the SolarMutex easily.
Definition: solarmutex.cxx:34
TerminateListener(css::uno::Reference< css::lang::XComponent > xComponent, unique_disposing_ptr< T > &rItem, bool bComponentDLL)
virtual void SAL_CALL disposing(const css::lang::EventObject &rEvt) override
css::uno::Reference< css::lang::XComponent > m_xComponent
virtual OUString SAL_CALL getImplementationName() override
virtual void SAL_CALL notifyTermination(const css::lang::EventObject &rEvt) override
virtual sal_Bool SAL_CALL supportsService(const OUString &) override
virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override
virtual void SAL_CALL queryTermination(const css::lang::EventObject &) override
css::uno::Reference< css::frame::XTerminateListener > m_xTerminateListener
std::unique_ptr< T, o3tl::default_delete< T > > m_xItem
unique_disposing_ptr(const unique_disposing_ptr &)=delete
virtual ~unique_disposing_ptr() COVERITY_NOEXCEPT_FALSE
virtual void reset(T *p=nullptr)
unique_disposing_ptr & operator=(const unique_disposing_ptr &)=delete
unique_disposing_ptr(const css::uno::Reference< css::lang::XComponent > &rComponent, T *p=nullptr, bool bComponent=false)
unique_disposing_solar_mutex_reset_ptr(const css::uno::Reference< css::lang::XComponent > &rComponent, T *p=nullptr, bool bComponent=false)
void * p
unsigned char sal_Bool