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