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_sd.hxx"
26 
27 #include "tools/TimerBasedTaskExecution.hxx"
28 #include "tools/AsynchronousTask.hxx"
29 #include <tools/time.hxx>
30 #include <osl/diagnose.h>
31 #include <boost/weak_ptr.hpp>
32 
33 #undef VERBOSE
34 
35 namespace sd { namespace tools {
36 
37 /** Used by the shared_ptr instead of the private destructor.
38 */
39 class TimerBasedTaskExecution::Deleter
40 {
41 public:
operator ()(TimerBasedTaskExecution * pObject)42     void operator() (TimerBasedTaskExecution* pObject)
43     {
44         delete pObject;
45     }
46 };
47 
48 
49 
50 
Create(const::boost::shared_ptr<AsynchronousTask> & rpTask,sal_uInt32 nMillisecondsBetweenSteps,sal_uInt32 nMaxTimePerStep)51 ::boost::shared_ptr<TimerBasedTaskExecution> TimerBasedTaskExecution::Create (
52     const ::boost::shared_ptr<AsynchronousTask>& rpTask,
53     sal_uInt32 nMillisecondsBetweenSteps,
54     sal_uInt32 nMaxTimePerStep)
55 {
56     ::boost::shared_ptr<TimerBasedTaskExecution> pExecution(
57         new TimerBasedTaskExecution(rpTask,nMillisecondsBetweenSteps,nMaxTimePerStep),
58         Deleter());
59     // Let the new object have a shared_ptr to itself, so that it can
60     // release itself when the AsynchronousTask has been executed
61     // completely.
62     pExecution->SetSelf(pExecution);
63     return pExecution;
64 }
65 
66 
67 
68 
Release(void)69 void TimerBasedTaskExecution::Release (void)
70 {
71     maTimer.Stop();
72     mpSelf.reset();
73 }
74 
75 
76 
77 
78 //static
ReleaseTask(const::boost::weak_ptr<TimerBasedTaskExecution> & rpExecution)79 void TimerBasedTaskExecution::ReleaseTask (
80     const ::boost::weak_ptr<TimerBasedTaskExecution>& rpExecution)
81 {
82     if ( ! rpExecution.expired())
83     {
84         try
85         {
86             ::boost::shared_ptr<tools::TimerBasedTaskExecution> pExecution (rpExecution);
87             pExecution->Release();
88         }
89         catch (::boost::bad_weak_ptr)
90         {
91             // When a bad_weak_ptr has been thrown then the object pointed
92             // to by rpTask has been released right after we checked that it
93             // still existed.  Too bad, but that means, that we have nothing
94             // more do.
95         }
96     }
97 }
98 
99 
100 
101 
TimerBasedTaskExecution(const::boost::shared_ptr<AsynchronousTask> & rpTask,sal_uInt32 nMillisecondsBetweenSteps,sal_uInt32 nMaxTimePerStep)102 TimerBasedTaskExecution::TimerBasedTaskExecution (
103     const ::boost::shared_ptr<AsynchronousTask>& rpTask,
104     sal_uInt32 nMillisecondsBetweenSteps,
105     sal_uInt32 nMaxTimePerStep)
106     : mpTask(rpTask),
107       maTimer(),
108       mpSelf(),
109       mnMaxTimePerStep(nMaxTimePerStep)
110 {
111     Link aLink(LINK(this,TimerBasedTaskExecution,TimerCallback));
112     maTimer.SetTimeoutHdl(aLink);
113     maTimer.SetTimeout(nMillisecondsBetweenSteps);
114     maTimer.Start();
115 }
116 
117 
118 
119 
~TimerBasedTaskExecution(void)120 TimerBasedTaskExecution::~TimerBasedTaskExecution (void)
121 {
122     maTimer.Stop();
123 }
124 
125 
126 
127 
SetSelf(const::boost::shared_ptr<TimerBasedTaskExecution> & rpSelf)128 void TimerBasedTaskExecution::SetSelf (
129     const ::boost::shared_ptr<TimerBasedTaskExecution>& rpSelf)
130 {
131     if (mpTask.get() != NULL)
132         mpSelf = rpSelf;
133 }
134 
135 
136 
137 
IMPL_LINK(TimerBasedTaskExecution,TimerCallback,Timer *,EMPTYARG)138 IMPL_LINK(TimerBasedTaskExecution,TimerCallback, Timer*,EMPTYARG)
139 {
140     if (mpTask.get() != NULL)
141     {
142         if (mpTask->HasNextStep())
143         {
144             // Execute as many steps as fit into the time span of length
145             // mnMaxTimePerStep.  Note that the last step may take longer
146             // than allowed.
147             sal_uInt32 nStartTime (Time().GetMSFromTime());
148 #ifdef VERBOSE
149             OSL_TRACE("starting TimerBasedTaskExecution at %d", nStartTime);
150 #endif
151             do
152             {
153                 mpTask->RunNextStep();
154                 sal_uInt32 nDuration (Time().GetMSFromTime()-nStartTime);
155 #ifdef VERBOSE
156             OSL_TRACE("executed step in %d", nDuration);
157 #endif
158                 if (nDuration > mnMaxTimePerStep)
159                     break;
160             }
161             while (mpTask->HasNextStep());
162 #ifdef VERBOSE
163             OSL_TRACE("TimerBasedTaskExecution sleeping");
164 #endif
165             maTimer.Start();
166         }
167         else
168             mpSelf.reset();
169     }
170 
171     return 0;
172 }
173 
174 
175 } } // end of namespace ::sd::tools
176 
177