1*b1cdbd2cSJim Jagielski /************************************************************** 2*b1cdbd2cSJim Jagielski * 3*b1cdbd2cSJim Jagielski * Licensed to the Apache Software Foundation (ASF) under one 4*b1cdbd2cSJim Jagielski * or more contributor license agreements. See the NOTICE file 5*b1cdbd2cSJim Jagielski * distributed with this work for additional information 6*b1cdbd2cSJim Jagielski * regarding copyright ownership. The ASF licenses this file 7*b1cdbd2cSJim Jagielski * to you under the Apache License, Version 2.0 (the 8*b1cdbd2cSJim Jagielski * "License"); you may not use this file except in compliance 9*b1cdbd2cSJim Jagielski * with the License. You may obtain a copy of the License at 10*b1cdbd2cSJim Jagielski * 11*b1cdbd2cSJim Jagielski * http://www.apache.org/licenses/LICENSE-2.0 12*b1cdbd2cSJim Jagielski * 13*b1cdbd2cSJim Jagielski * Unless required by applicable law or agreed to in writing, 14*b1cdbd2cSJim Jagielski * software distributed under the License is distributed on an 15*b1cdbd2cSJim Jagielski * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16*b1cdbd2cSJim Jagielski * KIND, either express or implied. See the License for the 17*b1cdbd2cSJim Jagielski * specific language governing permissions and limitations 18*b1cdbd2cSJim Jagielski * under the License. 19*b1cdbd2cSJim Jagielski * 20*b1cdbd2cSJim Jagielski *************************************************************/ 21*b1cdbd2cSJim Jagielski 22*b1cdbd2cSJim Jagielski 23*b1cdbd2cSJim Jagielski 24*b1cdbd2cSJim Jagielski // MARKER(update_precomp.py): autogen include statement, do not remove 25*b1cdbd2cSJim Jagielski #include "precompiled_comphelper.hxx" 26*b1cdbd2cSJim Jagielski #include <comphelper/asyncnotification.hxx> 27*b1cdbd2cSJim Jagielski #include <osl/diagnose.h> 28*b1cdbd2cSJim Jagielski #include <osl/mutex.hxx> 29*b1cdbd2cSJim Jagielski #include <osl/conditn.hxx> 30*b1cdbd2cSJim Jagielski #include <comphelper/guarding.hxx> 31*b1cdbd2cSJim Jagielski 32*b1cdbd2cSJim Jagielski #include <deque> 33*b1cdbd2cSJim Jagielski #include <set> 34*b1cdbd2cSJim Jagielski #include <functional> 35*b1cdbd2cSJim Jagielski #include <algorithm> 36*b1cdbd2cSJim Jagielski 37*b1cdbd2cSJim Jagielski //........................................................................ 38*b1cdbd2cSJim Jagielski namespace comphelper 39*b1cdbd2cSJim Jagielski { 40*b1cdbd2cSJim Jagielski //........................................................................ 41*b1cdbd2cSJim Jagielski 42*b1cdbd2cSJim Jagielski //==================================================================== 43*b1cdbd2cSJim Jagielski //= AnyEvent 44*b1cdbd2cSJim Jagielski //==================================================================== 45*b1cdbd2cSJim Jagielski //-------------------------------------------------------------------- AnyEvent()46*b1cdbd2cSJim Jagielski AnyEvent::AnyEvent() 47*b1cdbd2cSJim Jagielski :m_refCount( 0 ) 48*b1cdbd2cSJim Jagielski { 49*b1cdbd2cSJim Jagielski } 50*b1cdbd2cSJim Jagielski 51*b1cdbd2cSJim Jagielski //-------------------------------------------------------------------- ~AnyEvent()52*b1cdbd2cSJim Jagielski AnyEvent::~AnyEvent() 53*b1cdbd2cSJim Jagielski { 54*b1cdbd2cSJim Jagielski } 55*b1cdbd2cSJim Jagielski 56*b1cdbd2cSJim Jagielski //-------------------------------------------------------------------- acquire()57*b1cdbd2cSJim Jagielski oslInterlockedCount SAL_CALL AnyEvent::acquire() 58*b1cdbd2cSJim Jagielski { 59*b1cdbd2cSJim Jagielski return osl_incrementInterlockedCount( &m_refCount ); 60*b1cdbd2cSJim Jagielski } 61*b1cdbd2cSJim Jagielski 62*b1cdbd2cSJim Jagielski //-------------------------------------------------------------------- release()63*b1cdbd2cSJim Jagielski oslInterlockedCount SAL_CALL AnyEvent::release() 64*b1cdbd2cSJim Jagielski { 65*b1cdbd2cSJim Jagielski if ( 0 == osl_decrementInterlockedCount( &m_refCount ) ) 66*b1cdbd2cSJim Jagielski { 67*b1cdbd2cSJim Jagielski delete this; 68*b1cdbd2cSJim Jagielski return 0; 69*b1cdbd2cSJim Jagielski } 70*b1cdbd2cSJim Jagielski return m_refCount; 71*b1cdbd2cSJim Jagielski } 72*b1cdbd2cSJim Jagielski 73*b1cdbd2cSJim Jagielski //==================================================================== 74*b1cdbd2cSJim Jagielski //= ProcessableEvent 75*b1cdbd2cSJim Jagielski //==================================================================== 76*b1cdbd2cSJim Jagielski struct ProcessableEvent 77*b1cdbd2cSJim Jagielski { 78*b1cdbd2cSJim Jagielski AnyEventRef aEvent; 79*b1cdbd2cSJim Jagielski ::rtl::Reference< IEventProcessor > xProcessor; 80*b1cdbd2cSJim Jagielski ProcessableEventcomphelper::ProcessableEvent81*b1cdbd2cSJim Jagielski ProcessableEvent( const AnyEventRef& _rEvent, const ::rtl::Reference< IEventProcessor >& _xProcessor ) 82*b1cdbd2cSJim Jagielski :aEvent( _rEvent ) 83*b1cdbd2cSJim Jagielski ,xProcessor( _xProcessor ) 84*b1cdbd2cSJim Jagielski { 85*b1cdbd2cSJim Jagielski } 86*b1cdbd2cSJim Jagielski ProcessableEventcomphelper::ProcessableEvent87*b1cdbd2cSJim Jagielski ProcessableEvent( const ProcessableEvent& _rRHS ) 88*b1cdbd2cSJim Jagielski :aEvent( _rRHS.aEvent ) 89*b1cdbd2cSJim Jagielski ,xProcessor( _rRHS.xProcessor ) 90*b1cdbd2cSJim Jagielski { 91*b1cdbd2cSJim Jagielski } 92*b1cdbd2cSJim Jagielski operator =comphelper::ProcessableEvent93*b1cdbd2cSJim Jagielski ProcessableEvent& operator=( const ProcessableEvent& _rRHS ) 94*b1cdbd2cSJim Jagielski { 95*b1cdbd2cSJim Jagielski aEvent = _rRHS.aEvent; 96*b1cdbd2cSJim Jagielski xProcessor = _rRHS.xProcessor; 97*b1cdbd2cSJim Jagielski return *this; 98*b1cdbd2cSJim Jagielski } 99*b1cdbd2cSJim Jagielski }; 100*b1cdbd2cSJim Jagielski 101*b1cdbd2cSJim Jagielski //==================================================================== 102*b1cdbd2cSJim Jagielski typedef ::std::deque< ProcessableEvent > EventQueue; 103*b1cdbd2cSJim Jagielski 104*b1cdbd2cSJim Jagielski //==================================================================== 105*b1cdbd2cSJim Jagielski struct EqualProcessor : public ::std::unary_function< ProcessableEvent, bool > 106*b1cdbd2cSJim Jagielski { 107*b1cdbd2cSJim Jagielski const ::rtl::Reference< IEventProcessor >& rProcessor; EqualProcessorcomphelper::EqualProcessor108*b1cdbd2cSJim Jagielski EqualProcessor( const ::rtl::Reference< IEventProcessor >& _rProcessor ) :rProcessor( _rProcessor ) { } 109*b1cdbd2cSJim Jagielski operator ()comphelper::EqualProcessor110*b1cdbd2cSJim Jagielski bool operator()( const ProcessableEvent& _rEvent ) 111*b1cdbd2cSJim Jagielski { 112*b1cdbd2cSJim Jagielski return _rEvent.xProcessor.get() == rProcessor.get(); 113*b1cdbd2cSJim Jagielski } 114*b1cdbd2cSJim Jagielski }; 115*b1cdbd2cSJim Jagielski 116*b1cdbd2cSJim Jagielski //==================================================================== 117*b1cdbd2cSJim Jagielski //= EventNotifierImpl 118*b1cdbd2cSJim Jagielski //==================================================================== 119*b1cdbd2cSJim Jagielski struct EventNotifierImpl 120*b1cdbd2cSJim Jagielski { 121*b1cdbd2cSJim Jagielski ::osl::Mutex aMutex; 122*b1cdbd2cSJim Jagielski oslInterlockedCount m_refCount; 123*b1cdbd2cSJim Jagielski ::osl::Condition aPendingActions; 124*b1cdbd2cSJim Jagielski EventQueue aEvents; 125*b1cdbd2cSJim Jagielski ::std::set< ::rtl::Reference< IEventProcessor > > 126*b1cdbd2cSJim Jagielski m_aDeadProcessors; 127*b1cdbd2cSJim Jagielski EventNotifierImplcomphelper::EventNotifierImpl128*b1cdbd2cSJim Jagielski EventNotifierImpl() 129*b1cdbd2cSJim Jagielski :m_refCount( 0 ) 130*b1cdbd2cSJim Jagielski { 131*b1cdbd2cSJim Jagielski } 132*b1cdbd2cSJim Jagielski 133*b1cdbd2cSJim Jagielski private: 134*b1cdbd2cSJim Jagielski EventNotifierImpl( const EventNotifierImpl& ); // never implemented 135*b1cdbd2cSJim Jagielski EventNotifierImpl& operator=( const EventNotifierImpl& ); // never implemented 136*b1cdbd2cSJim Jagielski }; 137*b1cdbd2cSJim Jagielski 138*b1cdbd2cSJim Jagielski //==================================================================== 139*b1cdbd2cSJim Jagielski //= AsyncEventNotifier 140*b1cdbd2cSJim Jagielski //==================================================================== 141*b1cdbd2cSJim Jagielski //-------------------------------------------------------------------- AsyncEventNotifier()142*b1cdbd2cSJim Jagielski AsyncEventNotifier::AsyncEventNotifier() 143*b1cdbd2cSJim Jagielski :m_pImpl( new EventNotifierImpl ) 144*b1cdbd2cSJim Jagielski { 145*b1cdbd2cSJim Jagielski } 146*b1cdbd2cSJim Jagielski 147*b1cdbd2cSJim Jagielski //-------------------------------------------------------------------- ~AsyncEventNotifier()148*b1cdbd2cSJim Jagielski AsyncEventNotifier::~AsyncEventNotifier() 149*b1cdbd2cSJim Jagielski { 150*b1cdbd2cSJim Jagielski } 151*b1cdbd2cSJim Jagielski 152*b1cdbd2cSJim Jagielski //-------------------------------------------------------------------- removeEventsForProcessor(const::rtl::Reference<IEventProcessor> & _xProcessor)153*b1cdbd2cSJim Jagielski void AsyncEventNotifier::removeEventsForProcessor( const ::rtl::Reference< IEventProcessor >& _xProcessor ) 154*b1cdbd2cSJim Jagielski { 155*b1cdbd2cSJim Jagielski ::osl::MutexGuard aGuard( m_pImpl->aMutex ); 156*b1cdbd2cSJim Jagielski 157*b1cdbd2cSJim Jagielski // remove all events for this processor 158*b1cdbd2cSJim Jagielski ::std::remove_if( m_pImpl->aEvents.begin(), m_pImpl->aEvents.end(), EqualProcessor( _xProcessor ) ); 159*b1cdbd2cSJim Jagielski 160*b1cdbd2cSJim Jagielski // and just in case that an event for exactly this processor has just been 161*b1cdbd2cSJim Jagielski // popped from the queue, but not yet processed: remember it: 162*b1cdbd2cSJim Jagielski m_pImpl->m_aDeadProcessors.insert( _xProcessor ); 163*b1cdbd2cSJim Jagielski } 164*b1cdbd2cSJim Jagielski 165*b1cdbd2cSJim Jagielski //-------------------------------------------------------------------- terminate()166*b1cdbd2cSJim Jagielski void SAL_CALL AsyncEventNotifier::terminate() 167*b1cdbd2cSJim Jagielski { 168*b1cdbd2cSJim Jagielski ::osl::MutexGuard aGuard( m_pImpl->aMutex ); 169*b1cdbd2cSJim Jagielski 170*b1cdbd2cSJim Jagielski // remember the termination request 171*b1cdbd2cSJim Jagielski AsyncEventNotifier_TBASE::terminate(); 172*b1cdbd2cSJim Jagielski 173*b1cdbd2cSJim Jagielski // awake the thread 174*b1cdbd2cSJim Jagielski m_pImpl->aPendingActions.set(); 175*b1cdbd2cSJim Jagielski } 176*b1cdbd2cSJim Jagielski 177*b1cdbd2cSJim Jagielski //-------------------------------------------------------------------- addEvent(const AnyEventRef & _rEvent,const::rtl::Reference<IEventProcessor> & _xProcessor)178*b1cdbd2cSJim Jagielski void AsyncEventNotifier::addEvent( const AnyEventRef& _rEvent, const ::rtl::Reference< IEventProcessor >& _xProcessor ) 179*b1cdbd2cSJim Jagielski { 180*b1cdbd2cSJim Jagielski ::osl::MutexGuard aGuard( m_pImpl->aMutex ); 181*b1cdbd2cSJim Jagielski 182*b1cdbd2cSJim Jagielski OSL_TRACE( "AsyncEventNotifier(%p): adding %p\n", this, _rEvent.get() ); 183*b1cdbd2cSJim Jagielski // remember this event 184*b1cdbd2cSJim Jagielski m_pImpl->aEvents.push_back( ProcessableEvent( _rEvent, _xProcessor ) ); 185*b1cdbd2cSJim Jagielski 186*b1cdbd2cSJim Jagielski // awake the thread 187*b1cdbd2cSJim Jagielski m_pImpl->aPendingActions.set(); 188*b1cdbd2cSJim Jagielski } 189*b1cdbd2cSJim Jagielski 190*b1cdbd2cSJim Jagielski //-------------------------------------------------------------------- run()191*b1cdbd2cSJim Jagielski void AsyncEventNotifier::run() 192*b1cdbd2cSJim Jagielski { 193*b1cdbd2cSJim Jagielski acquire(); 194*b1cdbd2cSJim Jagielski 195*b1cdbd2cSJim Jagielski // keep us alive, in case we're terminated in the mid of the following 196*b1cdbd2cSJim Jagielski ::rtl::Reference< AsyncEventNotifier > xKeepAlive( this ); 197*b1cdbd2cSJim Jagielski 198*b1cdbd2cSJim Jagielski do 199*b1cdbd2cSJim Jagielski { 200*b1cdbd2cSJim Jagielski AnyEventRef aNextEvent; 201*b1cdbd2cSJim Jagielski ::rtl::Reference< IEventProcessor > xNextProcessor; 202*b1cdbd2cSJim Jagielski 203*b1cdbd2cSJim Jagielski ::osl::ClearableMutexGuard aGuard( m_pImpl->aMutex ); 204*b1cdbd2cSJim Jagielski while ( m_pImpl->aEvents.size() > 0 ) 205*b1cdbd2cSJim Jagielski { 206*b1cdbd2cSJim Jagielski ProcessableEvent aEvent( m_pImpl->aEvents.front() ); 207*b1cdbd2cSJim Jagielski aNextEvent = aEvent.aEvent; 208*b1cdbd2cSJim Jagielski xNextProcessor = aEvent.xProcessor; 209*b1cdbd2cSJim Jagielski m_pImpl->aEvents.pop_front(); 210*b1cdbd2cSJim Jagielski 211*b1cdbd2cSJim Jagielski OSL_TRACE( "AsyncEventNotifier(%p): popping %p\n", this, aNextEvent.get() ); 212*b1cdbd2cSJim Jagielski 213*b1cdbd2cSJim Jagielski if ( !aNextEvent.get() ) 214*b1cdbd2cSJim Jagielski continue; 215*b1cdbd2cSJim Jagielski 216*b1cdbd2cSJim Jagielski // process the event, but only if it's processor did not die inbetween 217*b1cdbd2cSJim Jagielski ::std::set< ::rtl::Reference< IEventProcessor > >::iterator deadPos = m_pImpl->m_aDeadProcessors.find( xNextProcessor ); 218*b1cdbd2cSJim Jagielski if ( deadPos != m_pImpl->m_aDeadProcessors.end() ) 219*b1cdbd2cSJim Jagielski { 220*b1cdbd2cSJim Jagielski m_pImpl->m_aDeadProcessors.erase( xNextProcessor ); 221*b1cdbd2cSJim Jagielski xNextProcessor.clear(); 222*b1cdbd2cSJim Jagielski OSL_TRACE( "AsyncEventNotifier(%p): removing %p\n", this, aNextEvent.get() ); 223*b1cdbd2cSJim Jagielski } 224*b1cdbd2cSJim Jagielski 225*b1cdbd2cSJim Jagielski // if there was a termination request (->terminate), respect it 226*b1cdbd2cSJim Jagielski if ( !schedule() ) 227*b1cdbd2cSJim Jagielski return; 228*b1cdbd2cSJim Jagielski 229*b1cdbd2cSJim Jagielski { 230*b1cdbd2cSJim Jagielski ::comphelper::MutexRelease aReleaseOnce( m_pImpl->aMutex ); 231*b1cdbd2cSJim Jagielski if ( xNextProcessor.get() ) 232*b1cdbd2cSJim Jagielski xNextProcessor->processEvent( *aNextEvent.get() ); 233*b1cdbd2cSJim Jagielski } 234*b1cdbd2cSJim Jagielski } 235*b1cdbd2cSJim Jagielski 236*b1cdbd2cSJim Jagielski // if there was a termination request (->terminate), respect it 237*b1cdbd2cSJim Jagielski if ( !schedule() ) 238*b1cdbd2cSJim Jagielski return; 239*b1cdbd2cSJim Jagielski 240*b1cdbd2cSJim Jagielski // wait for new events to process 241*b1cdbd2cSJim Jagielski aGuard.clear(); 242*b1cdbd2cSJim Jagielski m_pImpl->aPendingActions.reset(); 243*b1cdbd2cSJim Jagielski m_pImpl->aPendingActions.wait(); 244*b1cdbd2cSJim Jagielski } 245*b1cdbd2cSJim Jagielski while ( sal_True ); 246*b1cdbd2cSJim Jagielski } 247*b1cdbd2cSJim Jagielski 248*b1cdbd2cSJim Jagielski //-------------------------------------------------------------------- onTerminated()249*b1cdbd2cSJim Jagielski void SAL_CALL AsyncEventNotifier::onTerminated() 250*b1cdbd2cSJim Jagielski { 251*b1cdbd2cSJim Jagielski AsyncEventNotifier_TBASE::onTerminated(); 252*b1cdbd2cSJim Jagielski // when we were started (->run), we aquired ourself. Release this now 253*b1cdbd2cSJim Jagielski // that we were finally terminated 254*b1cdbd2cSJim Jagielski release(); 255*b1cdbd2cSJim Jagielski } 256*b1cdbd2cSJim Jagielski 257*b1cdbd2cSJim Jagielski //-------------------------------------------------------------------- acquire()258*b1cdbd2cSJim Jagielski oslInterlockedCount SAL_CALL AsyncEventNotifier::acquire() 259*b1cdbd2cSJim Jagielski { 260*b1cdbd2cSJim Jagielski return osl_incrementInterlockedCount( &m_pImpl->m_refCount ); 261*b1cdbd2cSJim Jagielski } 262*b1cdbd2cSJim Jagielski 263*b1cdbd2cSJim Jagielski //-------------------------------------------------------------------- release()264*b1cdbd2cSJim Jagielski oslInterlockedCount SAL_CALL AsyncEventNotifier::release() 265*b1cdbd2cSJim Jagielski { 266*b1cdbd2cSJim Jagielski if ( 0 == osl_decrementInterlockedCount( &m_pImpl->m_refCount ) ) 267*b1cdbd2cSJim Jagielski { 268*b1cdbd2cSJim Jagielski delete this; 269*b1cdbd2cSJim Jagielski return 0; 270*b1cdbd2cSJim Jagielski } 271*b1cdbd2cSJim Jagielski return m_pImpl->m_refCount; 272*b1cdbd2cSJim Jagielski } 273*b1cdbd2cSJim Jagielski 274*b1cdbd2cSJim Jagielski //........................................................................ 275*b1cdbd2cSJim Jagielski } // namespace comphelper 276*b1cdbd2cSJim Jagielski //........................................................................ 277*b1cdbd2cSJim Jagielski 278