1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 23 24 // MARKER(update_precomp.py): autogen include statement, do not remove 25 #include "precompiled_slideshow.hxx" 26 27 // must be first 28 #include <canvas/debug.hxx> 29 #include <canvas/verbosetrace.hxx> 30 31 #include <comphelper/anytostring.hxx> 32 #include <cppuhelper/exc_hlp.hxx> 33 34 #include "slideshowexceptions.hxx" 35 #include "activity.hxx" 36 #include "activitiesqueue.hxx" 37 38 #include <boost/bind.hpp> 39 #include <algorithm> 40 41 42 using namespace ::com::sun::star; 43 44 namespace slideshow 45 { 46 namespace internal 47 { ActivitiesQueue(const::boost::shared_ptr<::canvas::tools::ElapsedTime> & pPresTimer)48 ActivitiesQueue::ActivitiesQueue( 49 const ::boost::shared_ptr< ::canvas::tools::ElapsedTime >& pPresTimer ) : 50 mpTimer( pPresTimer ), 51 maCurrentActivitiesWaiting(), 52 maCurrentActivitiesReinsert(), 53 maDequeuedActivities() 54 { 55 } 56 ~ActivitiesQueue()57 ActivitiesQueue::~ActivitiesQueue() 58 { 59 // dispose all queue entries 60 try 61 { 62 std::for_each( maCurrentActivitiesWaiting.begin(), 63 maCurrentActivitiesWaiting.end(), 64 boost::mem_fn( &Disposable::dispose ) ); 65 std::for_each( maCurrentActivitiesReinsert.begin(), 66 maCurrentActivitiesReinsert.end(), 67 boost::mem_fn( &Disposable::dispose ) ); 68 } 69 catch (uno::Exception &) 70 { 71 OSL_ENSURE( false, rtl::OUStringToOString( 72 comphelper::anyToString( 73 cppu::getCaughtException() ), 74 RTL_TEXTENCODING_UTF8 ).getStr() ); 75 } 76 } 77 addActivity(const ActivitySharedPtr & pActivity)78 bool ActivitiesQueue::addActivity( const ActivitySharedPtr& pActivity ) 79 { 80 OSL_ENSURE( pActivity, "ActivitiesQueue::addActivity: activity ptr NULL" ); 81 82 if( !pActivity ) 83 return false; 84 85 // add entry to waiting list 86 maCurrentActivitiesWaiting.push_back( pActivity ); 87 88 return true; 89 } 90 process()91 void ActivitiesQueue::process() 92 { 93 VERBOSE_TRACE( "ActivitiesQueue: outer loop heartbeat" ); 94 95 // accumulate time lag for all activities, and lag time 96 // base if necessary: 97 ActivityQueue::const_iterator iPos( 98 maCurrentActivitiesWaiting.begin() ); 99 const ActivityQueue::const_iterator iEnd( 100 maCurrentActivitiesWaiting.end() ); 101 double fLag = 0.0; 102 for ( ; iPos != iEnd; ++iPos ) 103 fLag = std::max<double>( fLag, (*iPos)->calcTimeLag() ); 104 if (fLag > 0.0) 105 { 106 mpTimer->adjustTimer( -fLag ); 107 } 108 109 // process list of activities 110 while( !maCurrentActivitiesWaiting.empty() ) 111 { 112 // process topmost activity 113 ActivitySharedPtr pActivity( maCurrentActivitiesWaiting.front() ); 114 maCurrentActivitiesWaiting.pop_front(); 115 116 bool bReinsert( false ); 117 118 try 119 { 120 // fire up activity 121 bReinsert = pActivity->perform(); 122 } 123 catch( uno::RuntimeException& ) 124 { 125 throw; 126 } 127 catch( uno::Exception& ) 128 { 129 // catch anything here, we don't want 130 // to leave this scope under _any_ 131 // circumstance. Although, do _not_ 132 // reinsert an activity that threw 133 // once. 134 135 // NOTE: we explicitly don't catch(...) here, 136 // since this will also capture segmentation 137 // violations and the like. In such a case, we 138 // still better let our clients now... 139 OSL_ENSURE( false, 140 rtl::OUStringToOString( 141 comphelper::anyToString( cppu::getCaughtException() ), 142 RTL_TEXTENCODING_UTF8 ).getStr() ); 143 } 144 catch( SlideShowException& ) 145 { 146 // catch anything here, we don't want 147 // to leave this scope under _any_ 148 // circumstance. Although, do _not_ 149 // reinsert an activity that threw 150 // once. 151 152 // NOTE: we explicitly don't catch(...) here, 153 // since this will also capture segmentation 154 // violations and the like. In such a case, we 155 // still better let our clients now... 156 OSL_TRACE( "::presentation::internal::ActivitiesQueue: Activity threw a SlideShowException, removing from ring" ); 157 } 158 159 if( bReinsert ) 160 maCurrentActivitiesReinsert.push_back( pActivity ); 161 else 162 maDequeuedActivities.push_back( pActivity ); 163 164 VERBOSE_TRACE( "ActivitiesQueue: inner loop heartbeat" ); 165 } 166 167 if( !maCurrentActivitiesReinsert.empty() ) 168 { 169 // reinsert all processed, but not finished 170 // activities back to waiting queue. With swap(), 171 // we kill two birds with one stone: we reuse the 172 // list nodes, and we clear the 173 // maCurrentActivitiesReinsert list 174 maCurrentActivitiesWaiting.swap( maCurrentActivitiesReinsert ); 175 } 176 } 177 processDequeued()178 void ActivitiesQueue::processDequeued() 179 { 180 // notify all dequeued activities from last round 181 ::std::for_each( maDequeuedActivities.begin(), 182 maDequeuedActivities.end(), 183 ::boost::mem_fn( &Activity::dequeued ) ); 184 maDequeuedActivities.clear(); 185 } 186 isEmpty() const187 bool ActivitiesQueue::isEmpty() const 188 { 189 return maCurrentActivitiesWaiting.empty() && maCurrentActivitiesReinsert.empty(); 190 } 191 clear()192 void ActivitiesQueue::clear() 193 { 194 // dequeue all entries: 195 std::for_each( maCurrentActivitiesWaiting.begin(), 196 maCurrentActivitiesWaiting.end(), 197 boost::mem_fn( &Activity::dequeued ) ); 198 ActivityQueue().swap( maCurrentActivitiesWaiting ); 199 200 std::for_each( maCurrentActivitiesReinsert.begin(), 201 maCurrentActivitiesReinsert.end(), 202 boost::mem_fn( &Activity::dequeued ) ); 203 ActivityQueue().swap( maCurrentActivitiesReinsert ); 204 } 205 } 206 } 207