Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*
3 : : * Version: MPL 1.1 / GPLv3+ / LGPLv3+
4 : : *
5 : : * The contents of this file are subject to the Mozilla Public License Version
6 : : * 1.1 (the "License"); you may not use this file except in compliance with
7 : : * the License or as specified alternatively below. You may obtain a copy of
8 : : * the License at http://www.mozilla.org/MPL/
9 : : *
10 : : * Software distributed under the License is distributed on an "AS IS" basis,
11 : : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 : : * for the specific language governing rights and limitations under the
13 : : * License.
14 : : *
15 : : * Major Contributor(s):
16 : : * Copyright (C) 2011 Red Hat, Inc., Caolán McNamara <caolanm@redhat.com>
17 : : * (initial developer)
18 : : *
19 : : * All Rights Reserved.
20 : : *
21 : : * For minor contributions see the git repository.
22 : : *
23 : : * Alternatively, the contents of this file may be used under the terms of
24 : : * either the GNU General Public License Version 3 or later (the "GPLv3+"), or
25 : : * the GNU Lesser General Public License Version 3 or later (the "LGPLv3+"),
26 : : * in which case the provisions of the GPLv3+ or the LGPLv3+ are applicable
27 : : * instead of those above.
28 : : */
29 : :
30 : : #ifndef _SCOPED_DISPOSING_PTR
31 : : #define _SCOPED_DISPOSING_PTR
32 : :
33 : : #include <cppuhelper/implbase1.hxx>
34 : : #include <boost/utility.hpp>
35 : : #include <boost/scoped_ptr.hpp>
36 : :
37 : : #include <com/sun/star/lang/XComponent.hpp>
38 : : #include <com/sun/star/frame/XDesktop.hpp>
39 : :
40 : : // for locking SolarMutex: svapp + mutex
41 : : #include <vcl/svapp.hxx>
42 : : #include <osl/mutex.hxx>
43 : :
44 : : namespace comphelper
45 : : {
46 : : //Similar to boost::scoped_ptr, except additionally releases the ptr on XComponent::disposing and/or XTerminateListener::notifyTermination if supported
47 : : template<class T> class scoped_disposing_ptr : private boost::noncopyable
48 : : {
49 : : private:
50 : : boost::scoped_ptr<T> m_aItem;
51 : : ::com::sun::star::uno::Reference< ::com::sun::star::frame::XTerminateListener> m_xTerminateListener;
52 : : public:
53 : 240 : scoped_disposing_ptr( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XComponent > &rComponent, T * p = 0 )
54 : 240 : : m_aItem(p)
55 : : {
56 [ + - ][ + - ]: 240 : m_xTerminateListener = new TerminateListener(rComponent, *this);
[ + - ]
57 : 240 : }
58 : :
59 : 657 : virtual void reset(T * p = 0)
60 : : {
61 : 657 : m_aItem.reset(p);
62 : 657 : }
63 : :
64 : : T & operator*() const
65 : : {
66 : : return *m_aItem;
67 : : }
68 : :
69 : 55444 : T * get() const
70 : : {
71 : 55444 : return m_aItem.get();
72 : : }
73 : :
74 : 48163 : T * operator->() const
75 : : {
76 : 48163 : return m_aItem.get();
77 : : }
78 : :
79 : 79436 : operator bool () const
80 : : {
81 : 79436 : return m_aItem;
82 : : }
83 : :
84 : 240 : virtual ~scoped_disposing_ptr()
85 : : {
86 [ + - - + ]: 480 : reset();
87 [ + - ]: 480 : }
88 : : private:
89 : : class TerminateListener : public ::cppu::WeakImplHelper1< ::com::sun::star::frame::XTerminateListener >
90 : : {
91 : : private:
92 : : ::com::sun::star::uno::Reference< ::com::sun::star::lang::XComponent > m_xComponent;
93 : : scoped_disposing_ptr<T>& m_rItem;
94 : : public:
95 : 240 : TerminateListener(const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XComponent > &rComponent,
96 : 240 : scoped_disposing_ptr<T>& rItem) : m_xComponent(rComponent), m_rItem(rItem)
97 : : {
98 [ + - ]: 240 : if (m_xComponent.is())
99 : : {
100 [ + - ]: 240 : ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDesktop> xDesktop(m_xComponent, ::com::sun::star::uno::UNO_QUERY);
101 [ + + ]: 240 : if (xDesktop.is())
102 [ + - ][ + - ]: 73 : xDesktop->addTerminateListener(this);
[ + - ]
103 : : else
104 [ + - ][ + - ]: 240 : m_xComponent->addEventListener(this);
[ + - ]
105 : : }
106 : 240 : }
107 : :
108 : 480 : ~TerminateListener()
109 : : {
110 [ - + ]: 240 : if ( m_xComponent.is() )
111 : : {
112 [ # # ]: 0 : ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDesktop> xDesktop(m_xComponent, ::com::sun::star::uno::UNO_QUERY);
113 [ # # ]: 0 : if (xDesktop.is())
114 [ # # ][ # # ]: 0 : xDesktop->removeTerminateListener(this);
[ # # ]
115 : : else
116 [ # # ][ # # ]: 240 : m_xComponent->removeEventListener(this);
[ # # ][ - + ]
117 : : }
118 : 720 : }
119 : :
120 : : private:
121 : : // XEventListener
122 : 240 : virtual void SAL_CALL disposing( const ::com::sun::star::lang::EventObject& rEvt )
123 : : throw (::com::sun::star::uno::RuntimeException)
124 : : {
125 : 240 : bool shutDown = (rEvt.Source == m_xComponent);
126 : :
127 [ + - ][ + - ]: 240 : if (shutDown && m_xComponent.is())
[ + - ]
128 : : {
129 [ + - ]: 240 : ::com::sun::star::uno::Reference< ::com::sun::star::frame::XDesktop> xDesktop(m_xComponent, ::com::sun::star::uno::UNO_QUERY);
130 [ + + ]: 240 : if (xDesktop.is())
131 [ + - ][ + - ]: 73 : xDesktop->removeTerminateListener(this);
[ + - ]
132 : : else
133 [ + - ][ + - ]: 167 : m_xComponent->removeEventListener(this);
[ + - ]
134 : 240 : m_xComponent.clear();
135 : : }
136 : :
137 [ + - ]: 240 : if (shutDown)
138 : 240 : m_rItem.reset();
139 : 240 : }
140 : :
141 : : // XTerminateListener
142 : 40 : virtual void SAL_CALL queryTermination( const ::com::sun::star::lang::EventObject& )
143 : : throw(::com::sun::star::frame::TerminationVetoException,
144 : : ::com::sun::star::uno::RuntimeException)
145 : : {
146 : 40 : }
147 : :
148 : 40 : virtual void SAL_CALL notifyTermination( const ::com::sun::star::lang::EventObject& rEvt )
149 : : throw (::com::sun::star::uno::RuntimeException)
150 : : {
151 : 40 : disposing(rEvt);
152 : 40 : }
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 aribitrary thread
160 [ - + ]: 210 : template<class T> class scoped_disposing_solar_mutex_reset_ptr
161 : : : public scoped_disposing_ptr<T>
162 : : {
163 : : public:
164 : 210 : scoped_disposing_solar_mutex_reset_ptr( const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XComponent > &rComponent, T * p = 0 )
165 : 210 : : scoped_disposing_ptr<T>(rComponent, p)
166 : : {
167 : 210 : }
168 : :
169 : 347 : virtual void reset(T * p = 0)
170 : : {
171 [ + - ]: 347 : SolarMutexGuard aGuard;
172 [ + - ][ + - ]: 347 : scoped_disposing_ptr<T>::reset(p);
173 : 347 : }
174 : : };
175 : :
176 : : }
177 : :
178 : : #endif
179 : :
180 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|