Line data Source code
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_SCOPED_DISPOSING_PTR_HXX
11 : #define INCLUDED_COMPHELPER_SCOPED_DISPOSING_PTR_HXX
12 :
13 : #include <cppuhelper/implbase1.hxx>
14 : #include <boost/utility.hpp>
15 : #include <boost/scoped_ptr.hpp>
16 :
17 : #include <com/sun/star/lang/XComponent.hpp>
18 : #include <com/sun/star/frame/XDesktop.hpp>
19 :
20 : #include <vcl/svapp.hxx>
21 : #include <osl/mutex.hxx>
22 :
23 : namespace comphelper
24 : {
25 : //Similar to boost::scoped_ptr, except additionally releases the ptr on XComponent::disposing and/or XTerminateListener::notifyTermination if supported
26 : template<class T> class scoped_disposing_ptr : private boost::noncopyable
27 : {
28 : private:
29 : boost::scoped_ptr<T> m_aItem;
30 : ::com::sun::star::uno::Reference< ::com::sun::star::frame::XTerminateListener> m_xTerminateListener;
31 : public:
32 174 : scoped_disposing_ptr( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XComponent > &rComponent, T * p = 0 )
33 174 : : m_aItem(p)
34 : {
35 174 : m_xTerminateListener = new TerminateListener(rComponent, *this);
36 174 : }
37 :
38 432 : virtual void reset(T * p = 0)
39 : {
40 432 : m_aItem.reset(p);
41 432 : }
42 :
43 : T & operator*() const
44 : {
45 : return *m_aItem;
46 : }
47 :
48 54 : T * get() const
49 : {
50 54 : return m_aItem.get();
51 : }
52 :
53 49732 : T * operator->() const
54 : {
55 49732 : return m_aItem.get();
56 : }
57 :
58 24866 : operator bool () const
59 : {
60 24866 : return static_cast< bool >(m_aItem);
61 : }
62 :
63 174 : virtual ~scoped_disposing_ptr()
64 : {
65 174 : reset();
66 348 : }
67 : private:
68 : class TerminateListener : public ::cppu::WeakImplHelper1< ::com::sun::star::frame::XTerminateListener >
69 : {
70 : private:
71 : ::com::sun::star::uno::Reference< ::com::sun::star::lang::XComponent > m_xComponent;
72 : scoped_disposing_ptr<T>& m_rItem;
73 : public:
74 174 : TerminateListener(const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XComponent > &rComponent,
75 174 : scoped_disposing_ptr<T>& rItem) : m_xComponent(rComponent), m_rItem(rItem)
76 : {
77 174 : if (m_xComponent.is())
78 : {
79 174 : ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDesktop> xDesktop(m_xComponent, ::com::sun::star::uno::UNO_QUERY);
80 174 : if (xDesktop.is())
81 90 : xDesktop->addTerminateListener(this);
82 : else
83 84 : m_xComponent->addEventListener(this);
84 : }
85 174 : }
86 :
87 344 : virtual ~TerminateListener()
88 : {
89 172 : if ( m_xComponent.is() )
90 : {
91 0 : ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDesktop> xDesktop(m_xComponent, ::com::sun::star::uno::UNO_QUERY);
92 0 : if (xDesktop.is())
93 0 : xDesktop->removeTerminateListener(this);
94 : else
95 0 : m_xComponent->removeEventListener(this);
96 : }
97 516 : }
98 :
99 : private:
100 : // XEventListener
101 172 : virtual void SAL_CALL disposing( const ::com::sun::star::lang::EventObject& rEvt )
102 : throw (::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE
103 : {
104 172 : bool shutDown = (rEvt.Source == m_xComponent);
105 :
106 172 : if (shutDown && m_xComponent.is())
107 : {
108 172 : ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDesktop> xDesktop(m_xComponent, ::com::sun::star::uno::UNO_QUERY);
109 172 : if (xDesktop.is())
110 88 : xDesktop->removeTerminateListener(this);
111 : else
112 84 : m_xComponent->removeEventListener(this);
113 172 : m_xComponent.clear();
114 : }
115 :
116 172 : if (shutDown)
117 172 : m_rItem.reset();
118 172 : }
119 :
120 : // XTerminateListener
121 36 : virtual void SAL_CALL queryTermination( const ::com::sun::star::lang::EventObject& )
122 : throw(::com::sun::star::frame::TerminationVetoException,
123 : ::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE
124 : {
125 36 : }
126 :
127 36 : virtual void SAL_CALL notifyTermination( const ::com::sun::star::lang::EventObject& rEvt )
128 : throw (::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE
129 : {
130 36 : disposing(rEvt);
131 36 : }
132 : };
133 : };
134 :
135 : //Something like an OutputDevice requires the SolarMutex to be taken before use
136 : //for threadsafety. The user can ensure this, except in the case of its dtor
137 : //being called from reset due to a terminate on the XComponent being called
138 : //from an aribitrary thread
139 90 : template<class T> class scoped_disposing_solar_mutex_reset_ptr
140 : : public scoped_disposing_ptr<T>
141 : {
142 : public:
143 90 : scoped_disposing_solar_mutex_reset_ptr( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XComponent > &rComponent, T * p = 0 )
144 90 : : scoped_disposing_ptr<T>(rComponent, p)
145 : {
146 90 : }
147 :
148 88 : virtual void reset(T * p = 0)
149 : {
150 88 : SolarMutexGuard aGuard;
151 88 : scoped_disposing_ptr<T>::reset(p);
152 88 : }
153 : };
154 :
155 : }
156 :
157 : #endif
158 :
159 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|