1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_slideshow.hxx"
30 
31 // must be first
32 #include <canvas/debug.hxx>
33 #include <canvas/verbosetrace.hxx>
34 
35 #include <comphelper/anytostring.hxx>
36 #include <cppuhelper/exc_hlp.hxx>
37 
38 #include "slideshowexceptions.hxx"
39 #include "activity.hxx"
40 #include "activitiesqueue.hxx"
41 
42 #include <boost/bind.hpp>
43 #include <algorithm>
44 
45 
46 using namespace ::com::sun::star;
47 
48 namespace slideshow
49 {
50     namespace internal
51     {
52         ActivitiesQueue::ActivitiesQueue(
53           const ::boost::shared_ptr< ::canvas::tools::ElapsedTime >& pPresTimer ) :
54             mpTimer( pPresTimer ),
55             maCurrentActivitiesWaiting(),
56             maCurrentActivitiesReinsert(),
57             maDequeuedActivities()
58         {
59         }
60 
61         ActivitiesQueue::~ActivitiesQueue()
62         {
63             // dispose all queue entries
64             try
65             {
66                 std::for_each( maCurrentActivitiesWaiting.begin(),
67                                maCurrentActivitiesWaiting.end(),
68                                boost::mem_fn( &Disposable::dispose ) );
69                 std::for_each( maCurrentActivitiesReinsert.begin(),
70                                maCurrentActivitiesReinsert.end(),
71                                boost::mem_fn( &Disposable::dispose ) );
72             }
73             catch (uno::Exception &)
74             {
75                 OSL_ENSURE( false, rtl::OUStringToOString(
76                                 comphelper::anyToString(
77                                     cppu::getCaughtException() ),
78                                 RTL_TEXTENCODING_UTF8 ).getStr() );
79             }
80         }
81 
82         bool ActivitiesQueue::addActivity( const ActivitySharedPtr& pActivity )
83         {
84             OSL_ENSURE( pActivity, "ActivitiesQueue::addActivity: activity ptr NULL" );
85 
86             if( !pActivity )
87                 return false;
88 
89             // add entry to waiting list
90             maCurrentActivitiesWaiting.push_back( pActivity );
91 
92             return true;
93         }
94 
95         void ActivitiesQueue::process()
96         {
97             VERBOSE_TRACE( "ActivitiesQueue: outer loop heartbeat" );
98 
99             // accumulate time lag for all activities, and lag time
100             // base if necessary:
101             ActivityQueue::const_iterator iPos(
102                 maCurrentActivitiesWaiting.begin() );
103             const ActivityQueue::const_iterator iEnd(
104                 maCurrentActivitiesWaiting.end() );
105             double fLag = 0.0;
106             for ( ; iPos != iEnd; ++iPos )
107                 fLag = std::max<double>( fLag, (*iPos)->calcTimeLag() );
108             if (fLag > 0.0)
109             {
110                 mpTimer->adjustTimer( -fLag );
111             }
112 
113             // process list of activities
114             while( !maCurrentActivitiesWaiting.empty() )
115             {
116                 // process topmost activity
117                 ActivitySharedPtr pActivity( maCurrentActivitiesWaiting.front() );
118                 maCurrentActivitiesWaiting.pop_front();
119 
120                 bool bReinsert( false );
121 
122                 try
123                 {
124                     // fire up activity
125                     bReinsert = pActivity->perform();
126                 }
127                 catch( uno::RuntimeException& )
128                 {
129                     throw;
130                 }
131                 catch( uno::Exception& )
132                 {
133                     // catch anything here, we don't want
134                     // to leave this scope under _any_
135                     // circumstance. Although, do _not_
136                     // reinsert an activity that threw
137                     // once.
138 
139                     // NOTE: we explicitely don't catch(...) here,
140                     // since this will also capture segmentation
141                     // violations and the like. In such a case, we
142                     // still better let our clients now...
143                     OSL_ENSURE( false,
144                                 rtl::OUStringToOString(
145                                     comphelper::anyToString( cppu::getCaughtException() ),
146                                     RTL_TEXTENCODING_UTF8 ).getStr() );
147                 }
148                 catch( SlideShowException& )
149                 {
150                     // catch anything here, we don't want
151                     // to leave this scope under _any_
152                     // circumstance. Although, do _not_
153                     // reinsert an activity that threw
154                     // once.
155 
156                     // NOTE: we explicitely don't catch(...) here,
157                     // since this will also capture segmentation
158                     // violations and the like. In such a case, we
159                     // still better let our clients now...
160                     OSL_TRACE( "::presentation::internal::ActivitiesQueue: Activity threw a SlideShowException, removing from ring" );
161                 }
162 
163                 if( bReinsert )
164                     maCurrentActivitiesReinsert.push_back( pActivity );
165                 else
166                     maDequeuedActivities.push_back( pActivity );
167 
168                 VERBOSE_TRACE( "ActivitiesQueue: inner loop heartbeat" );
169             }
170 
171             if( !maCurrentActivitiesReinsert.empty() )
172             {
173                 // reinsert all processed, but not finished
174                 // activities back to waiting queue. With swap(),
175                 // we kill two birds with one stone: we reuse the
176                 // list nodes, and we clear the
177                 // maCurrentActivitiesReinsert list
178                 maCurrentActivitiesWaiting.swap( maCurrentActivitiesReinsert );
179             }
180         }
181 
182         void ActivitiesQueue::processDequeued()
183         {
184             // notify all dequeued activities from last round
185             ::std::for_each( maDequeuedActivities.begin(),
186                              maDequeuedActivities.end(),
187                              ::boost::mem_fn( &Activity::dequeued ) );
188             maDequeuedActivities.clear();
189         }
190 
191         bool ActivitiesQueue::isEmpty() const
192         {
193             return maCurrentActivitiesWaiting.empty() && maCurrentActivitiesReinsert.empty();
194         }
195 
196         void ActivitiesQueue::clear()
197         {
198             // dequeue all entries:
199             std::for_each( maCurrentActivitiesWaiting.begin(),
200                            maCurrentActivitiesWaiting.end(),
201                            boost::mem_fn( &Activity::dequeued ) );
202             ActivityQueue().swap( maCurrentActivitiesWaiting );
203 
204             std::for_each( maCurrentActivitiesReinsert.begin(),
205                            maCurrentActivitiesReinsert.end(),
206                            boost::mem_fn( &Activity::dequeued ) );
207             ActivityQueue().swap( maCurrentActivitiesReinsert );
208         }
209     }
210 }
211