summaryrefslogtreecommitdiff
path: root/toolkit
diff options
context:
space:
mode:
authorFrank Schoenheit [fs] <frank.schoenheit@sun.com>2010-05-06 12:09:28 +0200
committerFrank Schoenheit [fs] <frank.schoenheit@sun.com>2010-05-06 12:09:28 +0200
commita7c84375db517769035080c8fed33b2f303fc42f (patch)
tree0183eae4e175fc12c7ecd8a67a66d723f1aced66 /toolkit
parent119f78a4d99618ae1e788d70cd8aab012cf81d34 (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.
Diffstat (limited to 'toolkit')
-rw-r--r--toolkit/inc/toolkit/awt/vclxwindow.hxx18
-rw-r--r--toolkit/source/awt/vclxwindow.cxx99
-rw-r--r--toolkit/source/awt/vclxwindows.cxx11
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;