1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ 2 /* 3 * This file is part of the LibreOffice project. 4 * 5 * This Source Code Form is subject to the terms of the Mozilla Public 6 * License, v. 2.0. If a copy of the MPL was not distributed with this 7 * file, You can obtain one at http://mozilla.org/MPL/2.0/. 8 * 9 * This file incorporates work covered by the following license notice: 10 * 11 * Licensed to the Apache Software Foundation (ASF) under one or more 12 * contributor license agreements. See the NOTICE file distributed 13 * with this work for additional information regarding copyright 14 * ownership. The ASF licenses this file to you under the Apache 15 * License, Version 2.0 (the "License"); you may not use this file 16 * except in compliance with the License. You may obtain a copy of 17 * the License at http://www.apache.org/licenses/LICENSE-2.0 . 18 */ 19 20 21 #include <tools/diagnose_ex.h> 22 #include <osl/diagnose.h> 23 #include <sal/log.hxx> 24 25 #include <slideshowexceptions.hxx> 26 #include <activity.hxx> 27 #include <activitiesqueue.hxx> 28 29 #include <algorithm> 30 #include <memory> 31 32 33 using namespace ::com::sun::star; 34 35 namespace slideshow::internal 36 { ActivitiesQueue(const std::shared_ptr<::canvas::tools::ElapsedTime> & pPresTimer)37 ActivitiesQueue::ActivitiesQueue( 38 const std::shared_ptr< ::canvas::tools::ElapsedTime >& pPresTimer ) : 39 mpTimer( pPresTimer ), 40 maCurrentActivitiesWaiting(), 41 maCurrentActivitiesReinsert(), 42 maDequeuedActivities() 43 { 44 } 45 ~ActivitiesQueue()46 ActivitiesQueue::~ActivitiesQueue() 47 { 48 // dispose all queue entries 49 try 50 { 51 for( const auto& pActivity : maCurrentActivitiesWaiting ) 52 pActivity->dispose(); 53 for( const auto& pActivity : maCurrentTailActivitiesWaiting ) 54 pActivity->dispose(); 55 for( const auto& pActivity : maCurrentActivitiesReinsert ) 56 pActivity->dispose(); 57 } 58 catch (const uno::Exception&) 59 { 60 TOOLS_WARN_EXCEPTION("slideshow", ""); 61 } 62 } 63 addActivity(const ActivitySharedPtr & pActivity)64 bool ActivitiesQueue::addActivity( const ActivitySharedPtr& pActivity ) 65 { 66 OSL_ENSURE( pActivity, "ActivitiesQueue::addActivity: activity ptr NULL" ); 67 68 if( !pActivity ) 69 return false; 70 71 // add entry to waiting list 72 maCurrentActivitiesWaiting.push_back( pActivity ); 73 74 return true; 75 } 76 addTailActivity(const ActivitySharedPtr & pActivity)77 bool ActivitiesQueue::addTailActivity(const ActivitySharedPtr &pActivity) 78 { 79 OSL_ENSURE( pActivity, "ActivitiesQueue::addTailActivity: activity ptr NULL" ); 80 81 if( !pActivity ) 82 return false; 83 84 // Activities that should be processed last are kept in a different 85 // ActivityQueue, and later appended to the end of the maCurrentActivitiesWaiting 86 // on the beginning of ActivitiesQueue::process() 87 maCurrentTailActivitiesWaiting.push_back( pActivity ); 88 89 return true; 90 } 91 process()92 void ActivitiesQueue::process() 93 { 94 SAL_INFO("slideshow.verbose", "ActivitiesQueue: outer loop heartbeat" ); 95 96 // If there are activities to be processed last append them to the end of the ActivitiesQueue 97 maCurrentActivitiesWaiting.insert( maCurrentActivitiesWaiting.end(), 98 maCurrentTailActivitiesWaiting.begin(), 99 maCurrentTailActivitiesWaiting.end() ); 100 maCurrentTailActivitiesWaiting.clear(); 101 102 // accumulate time lag for all activities, and lag time 103 // base if necessary: 104 double fLag = 0.0; 105 for ( const auto& rxActivity : maCurrentActivitiesWaiting ) 106 fLag = std::max<double>( fLag, rxActivity->calcTimeLag() ); 107 if (fLag > 0.0) 108 { 109 mpTimer->adjustTimer( -fLag ); 110 } 111 112 // process list of activities 113 while( !maCurrentActivitiesWaiting.empty() ) 114 { 115 // process topmost activity 116 ActivitySharedPtr pActivity( maCurrentActivitiesWaiting.front() ); 117 maCurrentActivitiesWaiting.pop_front(); 118 119 bool bReinsert( false ); 120 121 try 122 { 123 // fire up activity 124 bReinsert = pActivity->perform(); 125 } 126 catch( uno::RuntimeException& ) 127 { 128 throw; 129 } 130 catch( uno::Exception& ) 131 { 132 // catch anything here, we don't want 133 // to leave this scope under _any_ 134 // circumstance. Although, do _not_ 135 // reinsert an activity that threw 136 // once. 137 138 // NOTE: we explicitly don't catch(...) here, 139 // since this will also capture segmentation 140 // violations and the like. In such a case, we 141 // still better let our clients now... 142 TOOLS_WARN_EXCEPTION( "slideshow", "" ); 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 SAL_WARN("slideshow", "::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 SAL_INFO("slideshow.verbose", "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 for( const auto& pActivity : maDequeuedActivities ) 182 pActivity->dequeued(); 183 maDequeuedActivities.clear(); 184 } 185 isEmpty() const186 bool ActivitiesQueue::isEmpty() const 187 { 188 return maCurrentActivitiesWaiting.empty() && maCurrentActivitiesReinsert.empty(); 189 } 190 clear()191 void ActivitiesQueue::clear() 192 { 193 // dequeue all entries: 194 for( const auto& pActivity : maCurrentActivitiesWaiting ) 195 pActivity->dequeued(); 196 ActivityQueue().swap( maCurrentActivitiesWaiting ); 197 198 for( const auto& pActivity : maCurrentActivitiesReinsert ) 199 pActivity->dequeued(); 200 ActivityQueue().swap( maCurrentActivitiesReinsert ); 201 } 202 } 203 204 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ 205