LibreOffice Module dbaccess (master) 1
documenteventnotifier.cxx
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 * 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
21
22#include <com/sun/star/frame/DoubleInitializationException.hpp>
23
26#include <cppuhelper/weak.hxx>
28#include <vcl/svapp.hxx>
29
30namespace dbaccess
31{
32
33 using ::com::sun::star::uno::Reference;
34 using ::com::sun::star::uno::Exception;
35 using ::com::sun::star::uno::Any;
36 using ::com::sun::star::frame::DoubleInitializationException;
37 using ::com::sun::star::document::XDocumentEventListener;
38 using ::com::sun::star::document::DocumentEvent;
39 using ::com::sun::star::frame::XController2;
40
41 using namespace ::com::sun::star;
42
43 // DocumentEventHolder
44 typedef ::comphelper::EventHolder< DocumentEvent > DocumentEventHolder;
45
46 // DocumentEventNotifier_Impl
48 {
49 oslInterlockedCount m_refCount;
51 ::osl::Mutex& m_rMutex;
54 std::shared_ptr<::comphelper::AsyncEventNotifierAutoJoin> m_pEventBroadcaster;
57
58 public:
59 DocumentEventNotifier_Impl( ::cppu::OWeakObject& _rBroadcasterDocument, ::osl::Mutex& _rMutex )
60 :m_refCount( 0 )
61 ,m_rDocument( _rBroadcasterDocument )
62 ,m_rMutex( _rMutex )
63 ,m_bInitialized( false )
64 ,m_bDisposed( false )
65 ,m_aLegacyEventListeners( _rMutex )
67 {
68 }
69
70 // IEventProcessor
71 virtual void SAL_CALL acquire() noexcept override;
72 virtual void SAL_CALL release() noexcept override;
73
74 void addLegacyEventListener( const Reference< document::XEventListener >& Listener )
75 {
77 }
78
79 void removeLegacyEventListener( const Reference< document::XEventListener >& Listener )
80 {
82 }
83
84 void addDocumentEventListener( const Reference< XDocumentEventListener >& Listener )
85 {
87 }
88
89 void removeDocumentEventListener( const Reference< XDocumentEventListener >& Listener )
90 {
92 }
93
94 void disposing();
95
97
98 void notifyDocumentEvent( const OUString& EventName, const Reference< XController2 >& ViewController,
99 const Any& Supplement )
100 {
101 impl_notifyEvent_nothrow( DocumentEvent(
102 m_rDocument, EventName, ViewController, Supplement ) );
103 }
104
105 void notifyDocumentEventAsync( const OUString& EventName, const Reference< XController2 >& ViewController,
106 const Any& Supplement )
107 {
108 impl_notifyEventAsync_nothrow( DocumentEvent(
109 m_rDocument, EventName, ViewController, Supplement ) );
110 }
111
112 protected:
114 {
115 }
116
117 // IEventProcessor
118 virtual void processEvent( const ::comphelper::AnyEvent& _rEvent ) override;
119
120 private:
121 void impl_notifyEvent_nothrow( const DocumentEvent& _rEvent );
122 void impl_notifyEventAsync_nothrow( const DocumentEvent& _rEvent );
123 };
124
125 void SAL_CALL DocumentEventNotifier_Impl::acquire() noexcept
126 {
127 osl_atomic_increment( &m_refCount );
128 }
129
130 void SAL_CALL DocumentEventNotifier_Impl::release() noexcept
131 {
132 if ( 0 == osl_atomic_decrement( &m_refCount ) )
133 delete this;
134 }
135
137 {
138 // SYNCHRONIZED ->
139 // cancel any pending asynchronous events
140 ::osl::ResettableMutexGuard aGuard( m_rMutex );
142 {
143 m_pEventBroadcaster->removeEventsForProcessor( this );
144 m_pEventBroadcaster->terminate();
145 }
146
147 auto xEventBroadcaster = std::exchange(m_pEventBroadcaster, {});
148
149 lang::EventObject aEvent( m_rDocument );
150 aGuard.clear();
151 // <-- SYNCHRONIZED
152
153 if (xEventBroadcaster)
154 {
156 // unblock threads blocked on that so we can join
157 sal_uInt32 nLockCount = (rSolarMutex.IsCurrentThread()) ? rSolarMutex.release(true) : 0;
158 xEventBroadcaster->join();
159 if (nLockCount)
160 rSolarMutex.acquire(nLockCount);
161 xEventBroadcaster.reset();
162 }
165
166 // SYNCHRONIZED ->
167 aGuard.reset();
168 m_bDisposed = true;
169 // <-- SYNCHRONIZED
170 }
171
173 {
174 if ( m_bInitialized )
175 throw DoubleInitializationException();
176
177 m_bInitialized = true;
179 {
180 // there are already pending asynchronous events
182 }
183 }
184
185 void DocumentEventNotifier_Impl::impl_notifyEvent_nothrow( const DocumentEvent& _rEvent )
186 {
187 OSL_PRECOND( m_bInitialized,
188 "DocumentEventNotifier_Impl::impl_notifyEvent_nothrow: only to be called when the document is already initialized!" );
189 try
190 {
191 document::EventObject aLegacyEvent( _rEvent.Source, _rEvent.EventName );
192 m_aLegacyEventListeners.notifyEach( &document::XEventListener::notifyEvent, aLegacyEvent );
193 }
194 catch(const Exception&)
195 {
196 DBG_UNHANDLED_EXCEPTION("dbaccess");
197 }
198 try
199 {
200 m_aDocumentEventListeners.notifyEach( &XDocumentEventListener::documentEventOccured, _rEvent );
201 }
202 catch( const Exception& )
203 {
204 DBG_UNHANDLED_EXCEPTION("dbaccess");
205 }
206 }
207
209 {
211 {
213 ::newAsyncEventNotifierAutoJoin("DocumentEventNotifier");
214 if ( m_bInitialized )
215 {
216 // start processing the events if and only if we (our document, respectively) are
217 // already initialized
219 }
220 }
221 m_pEventBroadcaster->addEvent( new DocumentEventHolder( _rEvent ), this );
222 }
223
224 void DocumentEventNotifier_Impl::processEvent( const ::comphelper::AnyEvent& _rEvent )
225 {
226 // beware, this is called from the notification thread
227 {
228 ::osl::MutexGuard aGuard( m_rMutex );
229 if ( m_bDisposed )
230 return;
231 }
232 const DocumentEventHolder& rEventHolder = dynamic_cast< const DocumentEventHolder& >( _rEvent );
234 }
235
236 // DocumentEventNotifier
237 DocumentEventNotifier::DocumentEventNotifier( ::cppu::OWeakObject& _rBroadcasterDocument, ::osl::Mutex& _rMutex )
238 :m_pImpl( new DocumentEventNotifier_Impl( _rBroadcasterDocument, _rMutex ) )
239 {
240 }
241
243 {
244 }
245
247 {
248 m_pImpl->disposing();
249 }
250
252 {
253 m_pImpl->onDocumentInitialized();
254 }
255
256 void DocumentEventNotifier::addLegacyEventListener( const Reference< document::XEventListener >& Listener )
257 {
258 m_pImpl->addLegacyEventListener( Listener );
259 }
260
261 void DocumentEventNotifier::removeLegacyEventListener( const Reference< document::XEventListener >& Listener )
262 {
263 m_pImpl->removeLegacyEventListener( Listener );
264 }
265
266 void DocumentEventNotifier::addDocumentEventListener( const Reference< XDocumentEventListener >& Listener )
267 {
268 m_pImpl->addDocumentEventListener( Listener );
269 }
270
271 void DocumentEventNotifier::removeDocumentEventListener( const Reference< XDocumentEventListener >& Listener )
272 {
273 m_pImpl->removeDocumentEventListener( Listener );
274 }
275
276 void DocumentEventNotifier::notifyDocumentEvent( const OUString& EventName,
277 const Reference< XController2 >& ViewController, const Any& Supplement )
278 {
279 m_pImpl->notifyDocumentEvent( EventName, ViewController, Supplement );
280 }
281
282 void DocumentEventNotifier::notifyDocumentEventAsync( const OUString& EventName,
283 const Reference< XController2 >& ViewController, const Any& Supplement )
284 {
285 m_pImpl->notifyDocumentEventAsync( EventName, ViewController, Supplement );
286 }
287
288} // namespace dbaccess
289
290/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
::std::unique_ptr< XmlIdRegistry_Impl > m_pImpl
AnyEventRef aEvent
static comphelper::SolarMutex & GetSolarMutex()
static std::shared_ptr< AsyncEventNotifierAutoJoin > newAsyncEventNotifierAutoJoin(char const *name)
static void launch(std::shared_ptr< AsyncEventNotifierAutoJoin > const &)
const EventObjectType & getEventObject() const
sal_Int32 addInterface(const css::uno::Reference< ListenerT > &rxIFace)
void disposeAndClear(const css::lang::EventObject &rEvt)
sal_Int32 removeInterface(const css::uno::Reference< ListenerT > &rxIFace)
void notifyEach(void(SAL_CALL ListenerT::*NotificationMethod)(const EventT &), const EventT &Event)
sal_uInt32 release(bool bUnlockAll=false)
virtual bool IsCurrentThread() const
void acquire(sal_uInt32 nLockCount=1)
std::shared_ptr<::comphelper::AsyncEventNotifierAutoJoin > m_pEventBroadcaster
virtual void processEvent(const ::comphelper::AnyEvent &_rEvent) override
void notifyDocumentEvent(const OUString &EventName, const Reference< XController2 > &ViewController, const Any &Supplement)
void removeLegacyEventListener(const Reference< document::XEventListener > &Listener)
virtual void SAL_CALL release() noexcept override
::comphelper::OInterfaceContainerHelper3< XDocumentEventListener > m_aDocumentEventListeners
DocumentEventNotifier_Impl(::cppu::OWeakObject &_rBroadcasterDocument, ::osl::Mutex &_rMutex)
void notifyDocumentEventAsync(const OUString &EventName, const Reference< XController2 > &ViewController, const Any &Supplement)
void addDocumentEventListener(const Reference< XDocumentEventListener > &Listener)
void impl_notifyEventAsync_nothrow(const DocumentEvent &_rEvent)
::comphelper::OInterfaceContainerHelper3< css::document::XEventListener > m_aLegacyEventListeners
void addLegacyEventListener(const Reference< document::XEventListener > &Listener)
void removeDocumentEventListener(const Reference< XDocumentEventListener > &Listener)
virtual void SAL_CALL acquire() noexcept override
void impl_notifyEvent_nothrow(const DocumentEvent &_rEvent)
DocumentEventNotifier(::cppu::OWeakObject &_rBroadcasterDocument, ::osl::Mutex &_rMutex)
void addDocumentEventListener(const css::uno::Reference< css::document::XDocumentEventListener > &Listener)
void onDocumentInitialized()
tells the instance that its document is completely initialized now.
void disposing()
disposes the instance @precond the mutex is not locked
void addLegacyEventListener(const css::uno::Reference< css::document::XEventListener > &Listener)
void notifyDocumentEvent(const OUString &EventName, const css::uno::Reference< css::frame::XController2 > &_rxViewController, const css::uno::Any &Supplement)
notifies a document event described by the given parameters
::rtl::Reference< DocumentEventNotifier_Impl > m_pImpl
void removeDocumentEventListener(const css::uno::Reference< css::document::XDocumentEventListener > &Listener)
void notifyDocumentEventAsync(const OUString &EventName, const css::uno::Reference< css::frame::XController2 > &ViewController, const css::uno::Any &Supplement)
notifies a document event, described by the given parameters, asynchronously
void removeLegacyEventListener(const css::uno::Reference< css::document::XEventListener > &Listener)
#define DBG_UNHANDLED_EXCEPTION(...)
@ Exception
::comphelper::EventHolder< DocumentEvent > DocumentEventHolder