1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_comphelper.hxx" 30 #include <comphelper/asyncnotification.hxx> 31 #include <osl/diagnose.h> 32 #include <osl/mutex.hxx> 33 #include <osl/conditn.hxx> 34 #include <comphelper/guarding.hxx> 35 36 #include <deque> 37 #include <set> 38 #include <functional> 39 #include <algorithm> 40 41 //........................................................................ 42 namespace comphelper 43 { 44 //........................................................................ 45 46 //==================================================================== 47 //= AnyEvent 48 //==================================================================== 49 //-------------------------------------------------------------------- 50 AnyEvent::AnyEvent() 51 :m_refCount( 0 ) 52 { 53 } 54 55 //-------------------------------------------------------------------- 56 AnyEvent::~AnyEvent() 57 { 58 } 59 60 //-------------------------------------------------------------------- 61 oslInterlockedCount SAL_CALL AnyEvent::acquire() 62 { 63 return osl_incrementInterlockedCount( &m_refCount ); 64 } 65 66 //-------------------------------------------------------------------- 67 oslInterlockedCount SAL_CALL AnyEvent::release() 68 { 69 if ( 0 == osl_decrementInterlockedCount( &m_refCount ) ) 70 { 71 delete this; 72 return 0; 73 } 74 return m_refCount; 75 } 76 77 //==================================================================== 78 //= ProcessableEvent 79 //==================================================================== 80 struct ProcessableEvent 81 { 82 AnyEventRef aEvent; 83 ::rtl::Reference< IEventProcessor > xProcessor; 84 85 ProcessableEvent( const AnyEventRef& _rEvent, const ::rtl::Reference< IEventProcessor >& _xProcessor ) 86 :aEvent( _rEvent ) 87 ,xProcessor( _xProcessor ) 88 { 89 } 90 91 ProcessableEvent( const ProcessableEvent& _rRHS ) 92 :aEvent( _rRHS.aEvent ) 93 ,xProcessor( _rRHS.xProcessor ) 94 { 95 } 96 97 ProcessableEvent& operator=( const ProcessableEvent& _rRHS ) 98 { 99 aEvent = _rRHS.aEvent; 100 xProcessor = _rRHS.xProcessor; 101 return *this; 102 } 103 }; 104 105 //==================================================================== 106 typedef ::std::deque< ProcessableEvent > EventQueue; 107 108 //==================================================================== 109 struct EqualProcessor : public ::std::unary_function< ProcessableEvent, bool > 110 { 111 const ::rtl::Reference< IEventProcessor >& rProcessor; 112 EqualProcessor( const ::rtl::Reference< IEventProcessor >& _rProcessor ) :rProcessor( _rProcessor ) { } 113 114 bool operator()( const ProcessableEvent& _rEvent ) 115 { 116 return _rEvent.xProcessor.get() == rProcessor.get(); 117 } 118 }; 119 120 //==================================================================== 121 //= EventNotifierImpl 122 //==================================================================== 123 struct EventNotifierImpl 124 { 125 ::osl::Mutex aMutex; 126 oslInterlockedCount m_refCount; 127 ::osl::Condition aPendingActions; 128 EventQueue aEvents; 129 ::std::set< ::rtl::Reference< IEventProcessor > > 130 m_aDeadProcessors; 131 132 EventNotifierImpl() 133 :m_refCount( 0 ) 134 { 135 } 136 137 private: 138 EventNotifierImpl( const EventNotifierImpl& ); // never implemented 139 EventNotifierImpl& operator=( const EventNotifierImpl& ); // never implemented 140 }; 141 142 //==================================================================== 143 //= AsyncEventNotifier 144 //==================================================================== 145 //-------------------------------------------------------------------- 146 AsyncEventNotifier::AsyncEventNotifier() 147 :m_pImpl( new EventNotifierImpl ) 148 { 149 } 150 151 //-------------------------------------------------------------------- 152 AsyncEventNotifier::~AsyncEventNotifier() 153 { 154 } 155 156 //-------------------------------------------------------------------- 157 void AsyncEventNotifier::removeEventsForProcessor( const ::rtl::Reference< IEventProcessor >& _xProcessor ) 158 { 159 ::osl::MutexGuard aGuard( m_pImpl->aMutex ); 160 161 // remove all events for this processor 162 ::std::remove_if( m_pImpl->aEvents.begin(), m_pImpl->aEvents.end(), EqualProcessor( _xProcessor ) ); 163 164 // and just in case that an event for exactly this processor has just been 165 // popped from the queue, but not yet processed: remember it: 166 m_pImpl->m_aDeadProcessors.insert( _xProcessor ); 167 } 168 169 //-------------------------------------------------------------------- 170 void SAL_CALL AsyncEventNotifier::terminate() 171 { 172 ::osl::MutexGuard aGuard( m_pImpl->aMutex ); 173 174 // remember the termination request 175 AsyncEventNotifier_TBASE::terminate(); 176 177 // awake the thread 178 m_pImpl->aPendingActions.set(); 179 } 180 181 //-------------------------------------------------------------------- 182 void AsyncEventNotifier::addEvent( const AnyEventRef& _rEvent, const ::rtl::Reference< IEventProcessor >& _xProcessor ) 183 { 184 ::osl::MutexGuard aGuard( m_pImpl->aMutex ); 185 186 OSL_TRACE( "AsyncEventNotifier(%p): adding %p\n", this, _rEvent.get() ); 187 // remember this event 188 m_pImpl->aEvents.push_back( ProcessableEvent( _rEvent, _xProcessor ) ); 189 190 // awake the thread 191 m_pImpl->aPendingActions.set(); 192 } 193 194 //-------------------------------------------------------------------- 195 void AsyncEventNotifier::run() 196 { 197 acquire(); 198 199 // keep us alive, in case we're terminated in the mid of the following 200 ::rtl::Reference< AsyncEventNotifier > xKeepAlive( this ); 201 202 do 203 { 204 AnyEventRef aNextEvent; 205 ::rtl::Reference< IEventProcessor > xNextProcessor; 206 207 ::osl::ClearableMutexGuard aGuard( m_pImpl->aMutex ); 208 while ( m_pImpl->aEvents.size() > 0 ) 209 { 210 ProcessableEvent aEvent( m_pImpl->aEvents.front() ); 211 aNextEvent = aEvent.aEvent; 212 xNextProcessor = aEvent.xProcessor; 213 m_pImpl->aEvents.pop_front(); 214 215 OSL_TRACE( "AsyncEventNotifier(%p): popping %p\n", this, aNextEvent.get() ); 216 217 if ( !aNextEvent.get() ) 218 continue; 219 220 // process the event, but only if it's processor did not die inbetween 221 ::std::set< ::rtl::Reference< IEventProcessor > >::iterator deadPos = m_pImpl->m_aDeadProcessors.find( xNextProcessor ); 222 if ( deadPos != m_pImpl->m_aDeadProcessors.end() ) 223 { 224 m_pImpl->m_aDeadProcessors.erase( xNextProcessor ); 225 xNextProcessor.clear(); 226 OSL_TRACE( "AsyncEventNotifier(%p): removing %p\n", this, aNextEvent.get() ); 227 } 228 229 // if there was a termination request (->terminate), respect it 230 if ( !schedule() ) 231 return; 232 233 { 234 ::comphelper::MutexRelease aReleaseOnce( m_pImpl->aMutex ); 235 if ( xNextProcessor.get() ) 236 xNextProcessor->processEvent( *aNextEvent.get() ); 237 } 238 } 239 240 // if there was a termination request (->terminate), respect it 241 if ( !schedule() ) 242 return; 243 244 // wait for new events to process 245 aGuard.clear(); 246 m_pImpl->aPendingActions.reset(); 247 m_pImpl->aPendingActions.wait(); 248 } 249 while ( sal_True ); 250 } 251 252 //-------------------------------------------------------------------- 253 void SAL_CALL AsyncEventNotifier::onTerminated() 254 { 255 AsyncEventNotifier_TBASE::onTerminated(); 256 // when we were started (->run), we aquired ourself. Release this now 257 // that we were finally terminated 258 release(); 259 } 260 261 //-------------------------------------------------------------------- 262 oslInterlockedCount SAL_CALL AsyncEventNotifier::acquire() 263 { 264 return osl_incrementInterlockedCount( &m_pImpl->m_refCount ); 265 } 266 267 //-------------------------------------------------------------------- 268 oslInterlockedCount SAL_CALL AsyncEventNotifier::release() 269 { 270 if ( 0 == osl_decrementInterlockedCount( &m_pImpl->m_refCount ) ) 271 { 272 delete this; 273 return 0; 274 } 275 return m_pImpl->m_refCount; 276 } 277 278 //........................................................................ 279 } // namespace comphelper 280 //........................................................................ 281 282