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: eventqueue.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_slideshow.hxx"
35 #include <canvas/debug.hxx>
36 #include <tools/diagnose_ex.h>
37 #include <canvas/verbosetrace.hxx>
39 #include <comphelper/anytostring.hxx>
40 #include <cppuhelper/exc_hlp.hxx>
43 #include <eventqueue.hxx>
44 #include <slideshowexceptions.hxx>
46 #include <boost/shared_ptr.hpp>
50 using namespace ::com::sun::star
;
56 bool EventQueue::EventEntry::operator<( const EventEntry
& rEvent
) const
58 // negate comparison, we want priority queue to be sorted
59 // in increasing order of activation times
60 return this->nTime
> rEvent
.nTime
;
64 EventQueue::EventQueue(
65 boost::shared_ptr
<canvas::tools::ElapsedTime
> const & pPresTimer
)
74 EventQueue::~EventQueue()
76 // add in all that have been added explicitly for this round:
77 EventEntryVector::const_iterator
const iEnd( maNextEvents
.end() );
78 for ( EventEntryVector::const_iterator
iPos( maNextEvents
.begin() );
79 iPos
!= iEnd
; ++iPos
)
83 EventEntryVector().swap( maNextEvents
);
85 // dispose event queue
86 while( !maEvents
.empty() )
90 maEvents
.top().pEvent
->dispose();
92 catch (uno::Exception
&)
94 OSL_ENSURE( false, rtl::OUStringToOString(
95 comphelper::anyToString(
96 cppu::getCaughtException() ),
97 RTL_TEXTENCODING_UTF8
).getStr() );
103 bool EventQueue::addEvent( const EventSharedPtr
& rEvent
)
105 ::osl::MutexGuard
aGuard( maMutex
);
107 ENSURE_OR_RETURN( rEvent
,
108 "EventQueue::addEvent: event ptr NULL" );
112 // A seemingly obvious optimization cannot be used here,
113 // because it breaks assumed order of notification: zero
114 // timeout events could be fired() immediately, but that
115 // would not unwind the stack and furthermore changes
116 // order of notification
119 maEvents
.push( EventEntry( rEvent
, rEvent
->getActivationTime(
120 mpTimer
->getElapsedTime()) ) );
124 bool EventQueue::addEventForNextRound( EventSharedPtr
const& rEvent
)
126 ::osl::MutexGuard
aGuard( maMutex
);
128 ENSURE_OR_RETURN( rEvent
.get() != NULL
,
129 "EventQueue::addEvent: event ptr NULL" );
130 maNextEvents
.push_back(
131 EventEntry( rEvent
, rEvent
->getActivationTime(
132 mpTimer
->getElapsedTime()) ) );
136 bool EventQueue::addEventWhenQueueIsEmpty (const EventSharedPtr
& rpEvent
)
138 ::osl::MutexGuard
aGuard( maMutex
);
141 rpEvent
.get() != NULL
,
142 "EventQueue::addEvent: event ptr NULL");
144 maNextNextEvents
.push(
147 rpEvent
->getActivationTime(mpTimer
->getElapsedTime())));
152 void EventQueue::forceEmpty()
154 ::osl::MutexGuard
aGuard( maMutex
);
159 void EventQueue::process()
161 ::osl::MutexGuard
aGuard( maMutex
);
166 void EventQueue::process_( bool bFireAllEvents
)
168 VERBOSE_TRACE( "EventQueue: heartbeat" );
170 // add in all that have been added explicitly for this round:
171 EventEntryVector::const_iterator
const iEnd( maNextEvents
.end() );
172 for ( EventEntryVector::const_iterator
iPos( maNextEvents
.begin() );
173 iPos
!= iEnd
; ++iPos
) {
174 maEvents
.push(*iPos
);
176 EventEntryVector().swap( maNextEvents
);
178 // perform topmost, ready-to-execute event
179 // =======================================
181 const double nCurrTime( mpTimer
->getElapsedTime() );
183 // When maEvents does not contain any events that are due now
184 // then process one event from maNextNextEvents.
185 if (!maNextNextEvents
.empty()
187 && (maEvents
.empty() || maEvents
.top().nTime
> nCurrTime
))
189 const EventEntry
aEvent (maNextNextEvents
.top());
190 maNextNextEvents
.pop();
191 maEvents
.push(aEvent
);
194 // process ready/elapsed events. Note that the 'perceived'
195 // current time remains constant for this loop, thus we're
196 // processing only those events which where ready when we
197 // entered this method.
198 while( !maEvents
.empty() &&
199 (bFireAllEvents
|| maEvents
.top().nTime
<= nCurrTime
) )
201 EventEntry
event( maEvents
.top() );
204 // only process event, if it is still 'charged',
205 // i.e. the fire() call effects something. This is
206 // used when e.g. having events registered at multiple
207 // places, which should fire only once: after the
208 // initial fire() call, those events become inactive
209 // and return false on isCharged. This frees us from
210 // the need to prune queues of those inactive shells.
211 if( event
.pEvent
->isCharged() )
215 #if OSL_DEBUG_LEVEL > 0
216 VERBOSE_TRACE( "Firing event: unknown (0x%X), timeout was: %f",
218 event
.pEvent
->getActivationTime(0.0) );
221 event
.pEvent
->fire();
223 catch( uno::RuntimeException
& )
227 catch( uno::Exception
& )
229 // catch anything here, we don't want
230 // to leave this scope under _any_
231 // circumstance. Although, do _not_
232 // reinsert an activity that threw
235 // NOTE: we explicitely don't catch(...) here,
236 // since this will also capture segmentation
237 // violations and the like. In such a case, we
238 // still better let our clients now...
240 rtl::OUStringToOString(
241 comphelper::anyToString( cppu::getCaughtException() ),
242 RTL_TEXTENCODING_UTF8
).getStr() );
244 catch( SlideShowException
& )
246 // catch anything here, we don't want
247 // to leave this scope under _any_
248 // circumstance. Although, do _not_
249 // reinsert an activity that threw
252 // NOTE: we explicitely don't catch(...) here,
253 // since this will also capture segmentation
254 // violations and the like. In such a case, we
255 // still better let our clients now...
256 OSL_TRACE( "::presentation::internal::EventQueue: Event threw a SlideShowException, action might not have been fully performed" );
261 #if OSL_DEBUG_LEVEL > 0
262 VERBOSE_TRACE( "Ignoring discharged event: unknown (0x%X), timeout was: %f",
264 event
.pEvent
->getActivationTime(0.0) );
270 bool EventQueue::isEmpty() const
272 ::osl::MutexGuard
aGuard( maMutex
);
274 return maEvents
.empty() && maNextEvents
.empty() && maNextNextEvents
.empty();
277 double EventQueue::nextTimeout() const
279 ::osl::MutexGuard
aGuard( maMutex
);
281 // return time for next entry (if any)
282 double nTimeout (::std::numeric_limits
<double>::max());
283 const double nCurrentTime (mpTimer
->getElapsedTime());
284 if ( ! maEvents
.empty())
285 nTimeout
= maEvents
.top().nTime
- nCurrentTime
;
286 if ( ! maNextEvents
.empty())
287 nTimeout
= ::std::min(nTimeout
, maNextEvents
.front().nTime
- nCurrentTime
);
288 if ( ! maNextNextEvents
.empty())
289 nTimeout
= ::std::min(nTimeout
, maNextNextEvents
.top().nTime
- nCurrentTime
);
294 void EventQueue::clear()
296 ::osl::MutexGuard
aGuard( maMutex
);
298 // TODO(P1): Maybe a plain vector and vector.swap will
299 // be faster here. Profile.
300 maEvents
= ImplQueueType();