merge the formfield patch from ooo-build
[ooovba.git] / slideshow / source / engine / eventqueue.cxx
blob087d4d5d7c0596fc67c2e5b0256b80f2aa9d9a22
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: eventqueue.cxx,v $
10 * $Revision: 1.15 $
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"
34 // must be first
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>
42 #include <event.hxx>
43 #include <eventqueue.hxx>
44 #include <slideshowexceptions.hxx>
46 #include <boost/shared_ptr.hpp>
47 #include <limits>
50 using namespace ::com::sun::star;
52 namespace slideshow
54 namespace internal
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 )
66 : maMutex(),
67 maEvents(),
68 maNextEvents(),
69 maNextNextEvents(),
70 mpTimer( 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 )
81 maEvents.push(*iPos);
83 EventEntryVector().swap( maNextEvents );
85 // dispose event queue
86 while( !maEvents.empty() )
88 try
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() );
99 maEvents.pop();
103 bool EventQueue::addEvent( const EventSharedPtr& rEvent )
105 ::osl::MutexGuard aGuard( maMutex );
107 ENSURE_OR_RETURN( rEvent,
108 "EventQueue::addEvent: event ptr NULL" );
110 // prepare entry
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
118 // add entry
119 maEvents.push( EventEntry( rEvent, rEvent->getActivationTime(
120 mpTimer->getElapsedTime()) ) );
121 return true;
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()) ) );
133 return true;
136 bool EventQueue::addEventWhenQueueIsEmpty (const EventSharedPtr& rpEvent)
138 ::osl::MutexGuard aGuard( maMutex );
140 ENSURE_OR_RETURN(
141 rpEvent.get() != NULL,
142 "EventQueue::addEvent: event ptr NULL");
144 maNextNextEvents.push(
145 EventEntry(
146 rpEvent,
147 rpEvent->getActivationTime(mpTimer->getElapsedTime())));
149 return true;
152 void EventQueue::forceEmpty()
154 ::osl::MutexGuard aGuard( maMutex );
156 process_(true);
159 void EventQueue::process()
161 ::osl::MutexGuard aGuard( maMutex );
163 process_(false);
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()
186 && !bFireAllEvents
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() );
202 maEvents.pop();
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",
217 event.pEvent.get(),
218 event.pEvent->getActivationTime(0.0) );
219 #endif
221 event.pEvent->fire();
223 catch( uno::RuntimeException& )
225 throw;
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
233 // once.
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...
239 OSL_ENSURE( false,
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
250 // once.
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" );
259 else
261 #if OSL_DEBUG_LEVEL > 0
262 VERBOSE_TRACE( "Ignoring discharged event: unknown (0x%X), timeout was: %f",
263 event.pEvent.get(),
264 event.pEvent->getActivationTime(0.0) );
265 #endif
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);
291 return nTimeout;
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();