1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: asyncnotification.cxx,v $
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>
44 //........................................................................
47 //........................................................................
49 //====================================================================
51 //====================================================================
52 //--------------------------------------------------------------------
58 //--------------------------------------------------------------------
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
) )
80 //====================================================================
82 //====================================================================
83 struct ProcessableEvent
86 ::rtl::Reference
< IEventProcessor
> xProcessor
;
88 ProcessableEvent( const AnyEventRef
& _rEvent
, const ::rtl::Reference
< IEventProcessor
>& _xProcessor
)
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
;
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
129 oslInterlockedCount m_refCount
;
130 ::osl::Condition aPendingActions
;
132 ::std::set
< ::rtl::Reference
< IEventProcessor
> >
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();
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
) );
194 m_pImpl
->aPendingActions
.set();
197 //--------------------------------------------------------------------
198 void AsyncEventNotifier::run()
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() )
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
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
247 // wait for new events to process
249 m_pImpl
->aPendingActions
.reset();
250 m_pImpl
->aPendingActions
.wait();
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
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
) )
278 return m_pImpl
->m_refCount
;
281 //........................................................................
282 } // namespace comphelper
283 //........................................................................