diff options
author | Frank Schoenheit [fs] <frank.schoenheit@sun.com> | 2010-05-06 12:09:28 +0200 |
---|---|---|
committer | Frank Schoenheit [fs] <frank.schoenheit@sun.com> | 2010-05-06 12:09:28 +0200 |
commit | a7c84375db517769035080c8fed33b2f303fc42f (patch) | |
tree | 0183eae4e175fc12c7ecd8a67a66d723f1aced66 | |
parent | 119f78a4d99618ae1e788d70cd8aab012cf81d34 (diff) |
os141: allow the VCLXWindow to process arbitrary callbacks asynchronously, without a locked SolarMutex. Intended for UNO listeners.
Employ this mechanism for VCLXButton's actionPerformed callbacks, so we don't get threading problems in those
callbacks.
Normally, *each and every* UNO notification would need to happen without a SolarMutex, like VCLXWindow itself
already does this for mouse events and window enabled/disabled events. However, for each and every event which
we migrate to this new mechanism, we need to carefully evaluate which C++ clients might need to be adjusted. Java
clients don't have a problem with this, of course.
-rw-r--r-- | toolkit/inc/toolkit/awt/vclxwindow.hxx | 18 | ||||
-rw-r--r-- | toolkit/source/awt/vclxwindow.cxx | 99 | ||||
-rw-r--r-- | toolkit/source/awt/vclxwindows.cxx | 11 |
3 files changed, 108 insertions, 20 deletions
diff --git a/toolkit/inc/toolkit/awt/vclxwindow.hxx b/toolkit/inc/toolkit/awt/vclxwindow.hxx index 97f36850dff9..6ad3c3ab6076 100644 --- a/toolkit/inc/toolkit/awt/vclxwindow.hxx +++ b/toolkit/inc/toolkit/awt/vclxwindow.hxx @@ -51,6 +51,7 @@ #include <stdarg.h> #include <list> +#include <boost/function.hpp> class Window; class VclSimpleEvent; @@ -114,6 +115,23 @@ protected: ::cppu::OInterfaceContainerHelper& GetTopWindowListeners(); public: + typedef ::boost::function0< void > Callback; + +protected: + /** executes the given callback asynchronously + + At the moment the callback is called, the Solar Mutex is not locked. In particular, this implies that + you cannot rely on |this| not being disposed. However, you *can* rely on |this| being still alive (i.e. + having a ref count > 0). + + As a consequence, this can be used for doing listener notifications, using event multiplexers. Those multiplexers + care for the disposed state themself, and are alive as long as |this| is alive. + */ + void ImplExecuteAsyncWithoutSolarLock( + const Callback& i_callback + ); + +public: VCLXWindow( bool bWithDefaultProps = false ); ~VCLXWindow(); diff --git a/toolkit/source/awt/vclxwindow.cxx b/toolkit/source/awt/vclxwindow.cxx index 248571819067..bb880fe68b66 100644 --- a/toolkit/source/awt/vclxwindow.cxx +++ b/toolkit/source/awt/vclxwindow.cxx @@ -218,8 +218,8 @@ namespace class SAL_DLLPRIVATE VCLXWindowImpl : public ::comphelper::IEventProcessor { private: - typedef ::std::vector< ::rtl::Reference< ::comphelper::AnyEvent > > - EventArray; + typedef ::std::vector< ::rtl::Reference< ::comphelper::AnyEvent > > LegacyEventArray; + typedef ::std::vector< VCLXWindow::Callback > CallbackArray; private: VCLXWindow& mrAntiImpl; @@ -243,8 +243,11 @@ private: VclContainerListenerMultiplexer maContainerListeners; TopWindowListenerMultiplexer maTopWindowListeners; - EventArray maEvents; - ULONG mnEventId; + LegacyEventArray maLegacyEvents; + ULONG mnLegacyEventId; + + CallbackArray maCallbackEvents; + ULONG mnCallbackEventId; public: bool mbDisposing : 1; @@ -293,6 +296,10 @@ public: */ void notifyPlainEvent( const lang::EventObject& _rPlainEvent, PlainEventType _nType ); + /** impl-version of VCLXWindow::ImplExecuteAsyncWithoutSolarLock + */ + void callBackAsync( const VCLXWindow::Callback& i_callback ); + /** notifies the object that its VCLXWindow is being disposed */ void disposing(); @@ -326,7 +333,8 @@ protected: virtual void processEvent( const ::comphelper::AnyEvent& _rEvent ); private: - DECL_LINK( OnProcessEvent, void* ); + DECL_LINK( OnProcessLegacyEvent, void* ); + DECL_LINK( OnProcessCallbacks, void* ); private: /** notifies an arbitrary event @@ -373,7 +381,8 @@ VCLXWindowImpl::VCLXWindowImpl( VCLXWindow& _rAntiImpl, ::vos::IMutex& _rMutex, ,maPaintListeners( _rAntiImpl ) ,maContainerListeners( _rAntiImpl ) ,maTopWindowListeners( _rAntiImpl ) - ,mnEventId( 0 ) + ,mnLegacyEventId( 0 ) + ,mnCallbackEventId( 0 ) ,mbDisposing( false ) ,mbDesignMode( false ) ,mbSynthesizingVCLEvent( false ) @@ -394,9 +403,14 @@ VCLXWindowImpl::~VCLXWindowImpl() void VCLXWindowImpl::disposing() { ::vos::OGuard aGuard( mrMutex ); - if ( mnEventId ) - Application::RemoveUserEvent( mnEventId ); - mnEventId = 0; + if ( mnLegacyEventId ) + Application::RemoveUserEvent( mnLegacyEventId ); + mnLegacyEventId = 0; + + if ( mnCallbackEventId ) + Application::RemoveUserEvent( mnCallbackEventId ); + mnCallbackEventId = 0; + mbDisposed= true; ::com::sun::star::lang::EventObject aEvent; @@ -417,9 +431,9 @@ void VCLXWindowImpl::disposing() //-------------------------------------------------------------------- void VCLXWindowImpl::impl_notifyAnyEvent( const ::rtl::Reference< ::comphelper::AnyEvent >& _rEvent ) { - maEvents.push_back( _rEvent ); - if ( !mnEventId ) - mnEventId = Application::PostUserEvent( LINK( this, VCLXWindowImpl, OnProcessEvent ) ); + maLegacyEvents.push_back( _rEvent ); + if ( !mnLegacyEventId ) + mnLegacyEventId = Application::PostUserEvent( LINK( this, VCLXWindowImpl, OnProcessLegacyEvent ) ); } //-------------------------------------------------------------------- @@ -439,25 +453,25 @@ void VCLXWindowImpl::notifyPlainEvent( const lang::EventObject& _rPlainEvent, Pl } //-------------------------------------------------------------------- -IMPL_LINK( VCLXWindowImpl, OnProcessEvent, void*, EMPTYARG ) +IMPL_LINK( VCLXWindowImpl, OnProcessLegacyEvent, void*, EMPTYARG ) { // work on a copy of the events array - EventArray aEventsCopy; + LegacyEventArray aEventsCopy; { ::vos::OGuard aGuard( mrMutex ); - aEventsCopy = maEvents; - maEvents.clear(); + aEventsCopy = maLegacyEvents; + maLegacyEvents.clear(); - if ( !mnEventId ) + if ( !mnLegacyEventId ) // we were disposed while waiting for the mutex to lock return 1L; - mnEventId = 0; + mnLegacyEventId = 0; } { ::toolkit::ReleaseSolarMutex aReleaseSolar; - for ( EventArray::const_iterator loop = aEventsCopy.begin(); + for ( LegacyEventArray::const_iterator loop = aEventsCopy.begin(); loop != aEventsCopy.end(); ++loop ) @@ -523,6 +537,46 @@ void VCLXWindowImpl::processEvent( const ::comphelper::AnyEvent& _rEvent ) } //-------------------------------------------------------------------- +void VCLXWindowImpl::callBackAsync( const VCLXWindow::Callback& i_callback ) +{ + DBG_TESTSOLARMUTEX(); + maCallbackEvents.push_back( i_callback ); + if ( !mnCallbackEventId ) + mnCallbackEventId = Application::PostUserEvent( LINK( this, VCLXWindowImpl, OnProcessCallbacks ) ); +} + +//---------------------------------------------------------------------------------------------------------------------- +IMPL_LINK( VCLXWindowImpl, OnProcessCallbacks, void*, EMPTYARG ) +{ + // work on a copy of the callback array + CallbackArray aCallbacksCopy; + { + ::vos::OGuard aGuard( mrMutex ); + aCallbacksCopy = maCallbackEvents; + maCallbackEvents.clear(); + + if ( !mnCallbackEventId ) + // we were disposed while waiting for the mutex to lock + return 1L; + + mnCallbackEventId = 0; + } + + { + ::toolkit::ReleaseSolarMutex aReleaseSolar; + for ( CallbackArray::const_iterator loop = aCallbacksCopy.begin(); + loop != aCallbacksCopy.end(); + ++loop + ) + { + (*loop)(); + } + } + + return 0L; +} + +//-------------------------------------------------------------------- void SAL_CALL VCLXWindowImpl::acquire() { mrAntiImpl.acquire(); @@ -581,6 +635,13 @@ VCLXWindow::~VCLXWindow() } } +//---------------------------------------------------------------------------------------------------------------------- +void VCLXWindow::ImplExecuteAsyncWithoutSolarLock( const Callback& i_callback ) +{ + mpImpl->callBackAsync( i_callback ); +} + +//---------------------------------------------------------------------------------------------------------------------- ::toolkit::IAccessibleFactory& VCLXWindow::getAccessibleFactory() { return mpImpl->getAccessibleFactory().getFactory(); diff --git a/toolkit/source/awt/vclxwindows.cxx b/toolkit/source/awt/vclxwindows.cxx index 43e0e50c315d..00124b58ae93 100644 --- a/toolkit/source/awt/vclxwindows.cxx +++ b/toolkit/source/awt/vclxwindows.cxx @@ -63,6 +63,9 @@ #include <vcl/tabpage.hxx> #include <tools/diagnose_ex.h> +#include <boost/bind.hpp> +#include <boost/function.hpp> + using ::com::sun::star::uno::Any; using ::com::sun::star::uno::Reference; using ::com::sun::star::uno::makeAny; @@ -634,7 +637,13 @@ void VCLXButton::ProcessWindowEvent( const VclWindowEvent& rVclWindowEvent ) ::com::sun::star::awt::ActionEvent aEvent; aEvent.Source = (::cppu::OWeakObject*)this; aEvent.ActionCommand = maActionCommand; - maActionListeners.actionPerformed( aEvent ); + + Callback aCallback = ::boost::bind( + &ActionListenerMultiplexer::actionPerformed, + &maActionListeners, + aEvent + ); + ImplExecuteAsyncWithoutSolarLock( aCallback ); } } break; |