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