merge the formfield patch from ooo-build
[ooovba.git] / comphelper / source / misc / asyncnotification.cxx
blob4914f41cf9753da456a03de31590f2697d00ce58
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: asyncnotification.cxx,v $
10 * $Revision: 1.9 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_comphelper.hxx"
33 #include <comphelper/asyncnotification.hxx>
34 #include <osl/diagnose.h>
35 #include <osl/mutex.hxx>
36 #include <osl/conditn.hxx>
37 #include <comphelper/guarding.hxx>
39 #include <deque>
40 #include <set>
41 #include <functional>
42 #include <algorithm>
44 //........................................................................
45 namespace comphelper
47 //........................................................................
49 //====================================================================
50 //= AnyEvent
51 //====================================================================
52 //--------------------------------------------------------------------
53 AnyEvent::AnyEvent()
54 :m_refCount( 0 )
58 //--------------------------------------------------------------------
59 AnyEvent::~AnyEvent()
63 //--------------------------------------------------------------------
64 oslInterlockedCount SAL_CALL AnyEvent::acquire()
66 return osl_incrementInterlockedCount( &m_refCount );
69 //--------------------------------------------------------------------
70 oslInterlockedCount SAL_CALL AnyEvent::release()
72 if ( 0 == osl_decrementInterlockedCount( &m_refCount ) )
74 delete this;
75 return 0;
77 return m_refCount;
80 //====================================================================
81 //= ProcessableEvent
82 //====================================================================
83 struct ProcessableEvent
85 AnyEventRef aEvent;
86 ::rtl::Reference< IEventProcessor > xProcessor;
88 ProcessableEvent( const AnyEventRef& _rEvent, const ::rtl::Reference< IEventProcessor >& _xProcessor )
89 :aEvent( _rEvent )
90 ,xProcessor( _xProcessor )
94 ProcessableEvent( const ProcessableEvent& _rRHS )
95 :aEvent( _rRHS.aEvent )
96 ,xProcessor( _rRHS.xProcessor )
100 ProcessableEvent& operator=( const ProcessableEvent& _rRHS )
102 aEvent = _rRHS.aEvent;
103 xProcessor = _rRHS.xProcessor;
104 return *this;
108 //====================================================================
109 typedef ::std::deque< ProcessableEvent > EventQueue;
111 //====================================================================
112 struct EqualProcessor : public ::std::unary_function< ProcessableEvent, bool >
114 const ::rtl::Reference< IEventProcessor >& rProcessor;
115 EqualProcessor( const ::rtl::Reference< IEventProcessor >& _rProcessor ) :rProcessor( _rProcessor ) { }
117 bool operator()( const ProcessableEvent& _rEvent )
119 return _rEvent.xProcessor.get() == rProcessor.get();
123 //====================================================================
124 //= EventNotifierImpl
125 //====================================================================
126 struct EventNotifierImpl
128 ::osl::Mutex aMutex;
129 oslInterlockedCount m_refCount;
130 ::osl::Condition aPendingActions;
131 EventQueue aEvents;
132 ::std::set< ::rtl::Reference< IEventProcessor > >
133 m_aDeadProcessors;
135 EventNotifierImpl()
136 :m_refCount( 0 )
140 private:
141 EventNotifierImpl( const EventNotifierImpl& ); // never implemented
142 EventNotifierImpl& operator=( const EventNotifierImpl& ); // never implemented
145 //====================================================================
146 //= AsyncEventNotifier
147 //====================================================================
148 //--------------------------------------------------------------------
149 AsyncEventNotifier::AsyncEventNotifier()
150 :m_pImpl( new EventNotifierImpl )
154 //--------------------------------------------------------------------
155 AsyncEventNotifier::~AsyncEventNotifier()
159 //--------------------------------------------------------------------
160 void AsyncEventNotifier::removeEventsForProcessor( const ::rtl::Reference< IEventProcessor >& _xProcessor )
162 ::osl::MutexGuard aGuard( m_pImpl->aMutex );
164 // remove all events for this processor
165 ::std::remove_if( m_pImpl->aEvents.begin(), m_pImpl->aEvents.end(), EqualProcessor( _xProcessor ) );
167 // and just in case that an event for exactly this processor has just been
168 // popped from the queue, but not yet processed: remember it:
169 m_pImpl->m_aDeadProcessors.insert( _xProcessor );
172 //--------------------------------------------------------------------
173 void SAL_CALL AsyncEventNotifier::terminate()
175 ::osl::MutexGuard aGuard( m_pImpl->aMutex );
177 // remember the termination request
178 AsyncEventNotifier_TBASE::terminate();
180 // awake the thread
181 m_pImpl->aPendingActions.set();
184 //--------------------------------------------------------------------
185 void AsyncEventNotifier::addEvent( const AnyEventRef& _rEvent, const ::rtl::Reference< IEventProcessor >& _xProcessor )
187 ::osl::MutexGuard aGuard( m_pImpl->aMutex );
189 OSL_TRACE( "AsyncEventNotifier(%p): adding %p\n", this, _rEvent.get() );
190 // remember this event
191 m_pImpl->aEvents.push_back( ProcessableEvent( _rEvent, _xProcessor ) );
193 // awake the thread
194 m_pImpl->aPendingActions.set();
197 //--------------------------------------------------------------------
198 void AsyncEventNotifier::run()
200 acquire();
202 // keep us alive, in case we're terminated in the mid of the following
203 ::rtl::Reference< AsyncEventNotifier > xKeepAlive( this );
207 AnyEventRef aNextEvent;
208 ::rtl::Reference< IEventProcessor > xNextProcessor;
210 ::osl::ClearableMutexGuard aGuard( m_pImpl->aMutex );
211 while ( m_pImpl->aEvents.size() > 0 )
213 ProcessableEvent aEvent( m_pImpl->aEvents.front() );
214 aNextEvent = aEvent.aEvent;
215 xNextProcessor = aEvent.xProcessor;
216 m_pImpl->aEvents.pop_front();
218 OSL_TRACE( "AsyncEventNotifier(%p): popping %p\n", this, aNextEvent.get() );
220 if ( !aNextEvent.get() )
221 continue;
223 // process the event, but only if it's processor did not die inbetween
224 ::std::set< ::rtl::Reference< IEventProcessor > >::iterator deadPos = m_pImpl->m_aDeadProcessors.find( xNextProcessor );
225 if ( deadPos != m_pImpl->m_aDeadProcessors.end() )
227 m_pImpl->m_aDeadProcessors.erase( xNextProcessor );
228 xNextProcessor.clear();
229 OSL_TRACE( "AsyncEventNotifier(%p): removing %p\n", this, aNextEvent.get() );
232 // if there was a termination request (->terminate), respect it
233 if ( !schedule() )
234 return;
237 ::comphelper::MutexRelease aReleaseOnce( m_pImpl->aMutex );
238 if ( xNextProcessor.get() )
239 xNextProcessor->processEvent( *aNextEvent.get() );
243 // if there was a termination request (->terminate), respect it
244 if ( !schedule() )
245 return;
247 // wait for new events to process
248 aGuard.clear();
249 m_pImpl->aPendingActions.reset();
250 m_pImpl->aPendingActions.wait();
252 while ( sal_True );
255 //--------------------------------------------------------------------
256 void SAL_CALL AsyncEventNotifier::onTerminated()
258 AsyncEventNotifier_TBASE::onTerminated();
259 // when we were started (->run), we aquired ourself. Release this now
260 // that we were finally terminated
261 release();
264 //--------------------------------------------------------------------
265 oslInterlockedCount SAL_CALL AsyncEventNotifier::acquire()
267 return osl_incrementInterlockedCount( &m_pImpl->m_refCount );
270 //--------------------------------------------------------------------
271 oslInterlockedCount SAL_CALL AsyncEventNotifier::release()
273 if ( 0 == osl_decrementInterlockedCount( &m_pImpl->m_refCount ) )
275 delete this;
276 return 0;
278 return m_pImpl->m_refCount;
281 //........................................................................
282 } // namespace comphelper
283 //........................................................................