| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| *************************************************************/ |
| |
| |
| |
| // MARKER(update_precomp.py): autogen include statement, do not remove |
| #include "precompiled_slideshow.hxx" |
| |
| // must be first |
| #include <canvas/debug.hxx> |
| #include <canvas/verbosetrace.hxx> |
| |
| #include <comphelper/anytostring.hxx> |
| #include <cppuhelper/exc_hlp.hxx> |
| |
| #include "slideshowexceptions.hxx" |
| #include "activity.hxx" |
| #include "activitiesqueue.hxx" |
| |
| #include <boost/bind.hpp> |
| #include <algorithm> |
| |
| |
| using namespace ::com::sun::star; |
| |
| namespace slideshow |
| { |
| namespace internal |
| { |
| ActivitiesQueue::ActivitiesQueue( |
| const ::boost::shared_ptr< ::canvas::tools::ElapsedTime >& pPresTimer ) : |
| mpTimer( pPresTimer ), |
| maCurrentActivitiesWaiting(), |
| maCurrentActivitiesReinsert(), |
| maDequeuedActivities() |
| { |
| } |
| |
| ActivitiesQueue::~ActivitiesQueue() |
| { |
| // dispose all queue entries |
| try |
| { |
| std::for_each( maCurrentActivitiesWaiting.begin(), |
| maCurrentActivitiesWaiting.end(), |
| boost::mem_fn( &Disposable::dispose ) ); |
| std::for_each( maCurrentActivitiesReinsert.begin(), |
| maCurrentActivitiesReinsert.end(), |
| boost::mem_fn( &Disposable::dispose ) ); |
| } |
| catch (uno::Exception &) |
| { |
| OSL_ENSURE( false, rtl::OUStringToOString( |
| comphelper::anyToString( |
| cppu::getCaughtException() ), |
| RTL_TEXTENCODING_UTF8 ).getStr() ); |
| } |
| } |
| |
| bool ActivitiesQueue::addActivity( const ActivitySharedPtr& pActivity ) |
| { |
| OSL_ENSURE( pActivity, "ActivitiesQueue::addActivity: activity ptr NULL" ); |
| |
| if( !pActivity ) |
| return false; |
| |
| // add entry to waiting list |
| maCurrentActivitiesWaiting.push_back( pActivity ); |
| |
| return true; |
| } |
| |
| void ActivitiesQueue::process() |
| { |
| VERBOSE_TRACE( "ActivitiesQueue: outer loop heartbeat" ); |
| |
| // accumulate time lag for all activities, and lag time |
| // base if necessary: |
| ActivityQueue::const_iterator iPos( |
| maCurrentActivitiesWaiting.begin() ); |
| const ActivityQueue::const_iterator iEnd( |
| maCurrentActivitiesWaiting.end() ); |
| double fLag = 0.0; |
| for ( ; iPos != iEnd; ++iPos ) |
| fLag = std::max<double>( fLag, (*iPos)->calcTimeLag() ); |
| if (fLag > 0.0) |
| { |
| mpTimer->adjustTimer( -fLag ); |
| } |
| |
| // process list of activities |
| while( !maCurrentActivitiesWaiting.empty() ) |
| { |
| // process topmost activity |
| ActivitySharedPtr pActivity( maCurrentActivitiesWaiting.front() ); |
| maCurrentActivitiesWaiting.pop_front(); |
| |
| bool bReinsert( false ); |
| |
| try |
| { |
| // fire up activity |
| bReinsert = pActivity->perform(); |
| } |
| catch( uno::RuntimeException& ) |
| { |
| throw; |
| } |
| catch( uno::Exception& ) |
| { |
| // catch anything here, we don't want |
| // to leave this scope under _any_ |
| // circumstance. Although, do _not_ |
| // reinsert an activity that threw |
| // once. |
| |
| // NOTE: we explicitely don't catch(...) here, |
| // since this will also capture segmentation |
| // violations and the like. In such a case, we |
| // still better let our clients now... |
| OSL_ENSURE( false, |
| rtl::OUStringToOString( |
| comphelper::anyToString( cppu::getCaughtException() ), |
| RTL_TEXTENCODING_UTF8 ).getStr() ); |
| } |
| catch( SlideShowException& ) |
| { |
| // catch anything here, we don't want |
| // to leave this scope under _any_ |
| // circumstance. Although, do _not_ |
| // reinsert an activity that threw |
| // once. |
| |
| // NOTE: we explicitely don't catch(...) here, |
| // since this will also capture segmentation |
| // violations and the like. In such a case, we |
| // still better let our clients now... |
| OSL_TRACE( "::presentation::internal::ActivitiesQueue: Activity threw a SlideShowException, removing from ring" ); |
| } |
| |
| if( bReinsert ) |
| maCurrentActivitiesReinsert.push_back( pActivity ); |
| else |
| maDequeuedActivities.push_back( pActivity ); |
| |
| VERBOSE_TRACE( "ActivitiesQueue: inner loop heartbeat" ); |
| } |
| |
| if( !maCurrentActivitiesReinsert.empty() ) |
| { |
| // reinsert all processed, but not finished |
| // activities back to waiting queue. With swap(), |
| // we kill two birds with one stone: we reuse the |
| // list nodes, and we clear the |
| // maCurrentActivitiesReinsert list |
| maCurrentActivitiesWaiting.swap( maCurrentActivitiesReinsert ); |
| } |
| } |
| |
| void ActivitiesQueue::processDequeued() |
| { |
| // notify all dequeued activities from last round |
| ::std::for_each( maDequeuedActivities.begin(), |
| maDequeuedActivities.end(), |
| ::boost::mem_fn( &Activity::dequeued ) ); |
| maDequeuedActivities.clear(); |
| } |
| |
| bool ActivitiesQueue::isEmpty() const |
| { |
| return maCurrentActivitiesWaiting.empty() && maCurrentActivitiesReinsert.empty(); |
| } |
| |
| void ActivitiesQueue::clear() |
| { |
| // dequeue all entries: |
| std::for_each( maCurrentActivitiesWaiting.begin(), |
| maCurrentActivitiesWaiting.end(), |
| boost::mem_fn( &Activity::dequeued ) ); |
| ActivityQueue().swap( maCurrentActivitiesWaiting ); |
| |
| std::for_each( maCurrentActivitiesReinsert.begin(), |
| maCurrentActivitiesReinsert.end(), |
| boost::mem_fn( &Activity::dequeued ) ); |
| ActivityQueue().swap( maCurrentActivitiesReinsert ); |
| } |
| } |
| } |