1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2000, 2010 Oracle and/or its affiliates.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * This file is part of OpenOffice.org.
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.
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).
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.
26 ************************************************************************/
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>
41 //........................................................................
44 //........................................................................
46 //====================================================================
48 //====================================================================
49 //--------------------------------------------------------------------
55 //--------------------------------------------------------------------
60 //--------------------------------------------------------------------
61 oslInterlockedCount SAL_CALL
AnyEvent::acquire()
63 return osl_incrementInterlockedCount( &m_refCount
);
66 //--------------------------------------------------------------------
67 oslInterlockedCount SAL_CALL
AnyEvent::release()
69 if ( 0 == osl_decrementInterlockedCount( &m_refCount
) )
77 //====================================================================
79 //====================================================================
80 struct ProcessableEvent
83 ::rtl::Reference
< IEventProcessor
> xProcessor
;
85 ProcessableEvent( const AnyEventRef
& _rEvent
, const ::rtl::Reference
< IEventProcessor
>& _xProcessor
)
87 ,xProcessor( _xProcessor
)
91 ProcessableEvent( const ProcessableEvent
& _rRHS
)
92 :aEvent( _rRHS
.aEvent
)
93 ,xProcessor( _rRHS
.xProcessor
)
97 ProcessableEvent
& operator=( const ProcessableEvent
& _rRHS
)
99 aEvent
= _rRHS
.aEvent
;
100 xProcessor
= _rRHS
.xProcessor
;
105 //====================================================================
106 typedef ::std::deque
< ProcessableEvent
> EventQueue
;
108 //====================================================================
109 struct EqualProcessor
: public ::std::unary_function
< ProcessableEvent
, bool >
111 const ::rtl::Reference
< IEventProcessor
>& rProcessor
;
112 EqualProcessor( const ::rtl::Reference
< IEventProcessor
>& _rProcessor
) :rProcessor( _rProcessor
) { }
114 bool operator()( const ProcessableEvent
& _rEvent
)
116 return _rEvent
.xProcessor
.get() == rProcessor
.get();
120 //====================================================================
121 //= EventNotifierImpl
122 //====================================================================
123 struct EventNotifierImpl
126 oslInterlockedCount m_refCount
;
127 ::osl::Condition aPendingActions
;
129 ::std::set
< ::rtl::Reference
< IEventProcessor
> >
138 EventNotifierImpl( const EventNotifierImpl
& ); // never implemented
139 EventNotifierImpl
& operator=( const EventNotifierImpl
& ); // never implemented
142 //====================================================================
143 //= AsyncEventNotifier
144 //====================================================================
145 //--------------------------------------------------------------------
146 AsyncEventNotifier::AsyncEventNotifier()
147 :m_pImpl( new EventNotifierImpl
)
151 //--------------------------------------------------------------------
152 AsyncEventNotifier::~AsyncEventNotifier()
156 //--------------------------------------------------------------------
157 void AsyncEventNotifier::removeEventsForProcessor( const ::rtl::Reference
< IEventProcessor
>& _xProcessor
)
159 ::osl::MutexGuard
aGuard( m_pImpl
->aMutex
);
161 // remove all events for this processor
162 ::std::remove_if( m_pImpl
->aEvents
.begin(), m_pImpl
->aEvents
.end(), EqualProcessor( _xProcessor
) );
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
);
169 //--------------------------------------------------------------------
170 void SAL_CALL
AsyncEventNotifier::terminate()
172 ::osl::MutexGuard
aGuard( m_pImpl
->aMutex
);
174 // remember the termination request
175 AsyncEventNotifier_TBASE::terminate();
178 m_pImpl
->aPendingActions
.set();
181 //--------------------------------------------------------------------
182 void AsyncEventNotifier::addEvent( const AnyEventRef
& _rEvent
, const ::rtl::Reference
< IEventProcessor
>& _xProcessor
)
184 ::osl::MutexGuard
aGuard( m_pImpl
->aMutex
);
186 OSL_TRACE( "AsyncEventNotifier(%p): adding %p\n", this, _rEvent
.get() );
187 // remember this event
188 m_pImpl
->aEvents
.push_back( ProcessableEvent( _rEvent
, _xProcessor
) );
191 m_pImpl
->aPendingActions
.set();
194 //--------------------------------------------------------------------
195 void AsyncEventNotifier::run()
199 // keep us alive, in case we're terminated in the mid of the following
200 ::rtl::Reference
< AsyncEventNotifier
> xKeepAlive( this );
204 AnyEventRef aNextEvent
;
205 ::rtl::Reference
< IEventProcessor
> xNextProcessor
;
207 ::osl::ClearableMutexGuard
aGuard( m_pImpl
->aMutex
);
208 while ( m_pImpl
->aEvents
.size() > 0 )
210 ProcessableEvent
aEvent( m_pImpl
->aEvents
.front() );
211 aNextEvent
= aEvent
.aEvent
;
212 xNextProcessor
= aEvent
.xProcessor
;
213 m_pImpl
->aEvents
.pop_front();
215 OSL_TRACE( "AsyncEventNotifier(%p): popping %p\n", this, aNextEvent
.get() );
217 if ( !aNextEvent
.get() )
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() )
224 m_pImpl
->m_aDeadProcessors
.erase( xNextProcessor
);
225 xNextProcessor
.clear();
226 OSL_TRACE( "AsyncEventNotifier(%p): removing %p\n", this, aNextEvent
.get() );
229 // if there was a termination request (->terminate), respect it
234 ::comphelper::MutexRelease
aReleaseOnce( m_pImpl
->aMutex
);
235 if ( xNextProcessor
.get() )
236 xNextProcessor
->processEvent( *aNextEvent
.get() );
240 // if there was a termination request (->terminate), respect it
244 // wait for new events to process
246 m_pImpl
->aPendingActions
.reset();
247 m_pImpl
->aPendingActions
.wait();
252 //--------------------------------------------------------------------
253 void SAL_CALL
AsyncEventNotifier::onTerminated()
255 AsyncEventNotifier_TBASE::onTerminated();
256 // when we were started (->run), we aquired ourself. Release this now
257 // that we were finally terminated
261 //--------------------------------------------------------------------
262 oslInterlockedCount SAL_CALL
AsyncEventNotifier::acquire()
264 return osl_incrementInterlockedCount( &m_pImpl
->m_refCount
);
267 //--------------------------------------------------------------------
268 oslInterlockedCount SAL_CALL
AsyncEventNotifier::release()
270 if ( 0 == osl_decrementInterlockedCount( &m_pImpl
->m_refCount
) )
275 return m_pImpl
->m_refCount
;
278 //........................................................................
279 } // namespace comphelper
280 //........................................................................