Line data Source code
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 : #include <svdata.hxx>
21 : #include <tools/time.hxx>
22 : #include <vcl/scheduler.hxx>
23 : #include <vcl/timer.hxx>
24 : #include <saltimer.hxx>
25 :
26 : #define MAX_TIMER_PERIOD SAL_MAX_UINT64
27 :
28 26833139 : void ImplSchedulerData::Invoke()
29 : {
30 26833139 : if (mbDelete || mbInScheduler )
31 26833139 : return;
32 :
33 : // prepare Scheduler Object for deletion after handling
34 26833139 : mpScheduler->SetDeletionFlags();
35 :
36 : // invoke it
37 26833139 : mbInScheduler = true;
38 26833139 : mpScheduler->Invoke();
39 26833139 : mbInScheduler = false;
40 : }
41 :
42 26865091 : ImplSchedulerData *ImplSchedulerData::GetMostImportantTask( bool bTimer )
43 : {
44 26865091 : ImplSVData* pSVData = ImplGetSVData();
45 26865091 : ImplSchedulerData *pMostUrgent = NULL;
46 :
47 117177592 : for ( ImplSchedulerData *pSchedulerData = pSVData->mpFirstSchedulerData; pSchedulerData; pSchedulerData = pSchedulerData->mpNext )
48 : {
49 270907286 : if ( !pSchedulerData->mpScheduler || pSchedulerData->mbDelete || pSchedulerData->mnUpdateStack >= pSVData->mnUpdateStack
50 180590718 : || !pSchedulerData->mpScheduler->ReadyForSchedule( bTimer ) || !pSchedulerData->mpScheduler->IsActive())
51 54401283 : continue;
52 35911218 : if (!pMostUrgent)
53 26833139 : pMostUrgent = pSchedulerData;
54 : else
55 : {
56 : // Find the highest priority.
57 : // If the priority of the current task is higher (numerical value is lower) than
58 : // the priority of the most urgent, the current task gets the new most urgent.
59 9078079 : if ( pSchedulerData->mpScheduler->GetPriority() < pMostUrgent->mpScheduler->GetPriority() )
60 13703 : pMostUrgent = pSchedulerData;
61 : }
62 : }
63 :
64 26865091 : return pMostUrgent;
65 : }
66 :
67 26810188 : void Scheduler::SetDeletionFlags()
68 : {
69 26810188 : mpSchedulerData->mbDelete = true;
70 26810188 : mbActive = false;
71 26810188 : }
72 :
73 361 : void Scheduler::ImplDeInitScheduler()
74 : {
75 361 : ImplSVData* pSVData = ImplGetSVData();
76 361 : ImplSchedulerData* pSchedulerData = pSVData->mpFirstSchedulerData;
77 361 : if (pSVData->mpSalTimer)
78 : {
79 326 : pSVData->mpSalTimer->Stop();
80 : }
81 :
82 361 : if ( pSchedulerData )
83 : {
84 4660 : do
85 : {
86 4660 : ImplSchedulerData* pTempSchedulerData = pSchedulerData;
87 4660 : if ( pSchedulerData->mpScheduler )
88 : {
89 512 : pSchedulerData->mpScheduler->mbActive = false;
90 512 : pSchedulerData->mpScheduler->mpSchedulerData = NULL;
91 : }
92 4660 : pSchedulerData = pSchedulerData->mpNext;
93 4660 : delete pTempSchedulerData;
94 : }
95 : while ( pSchedulerData );
96 :
97 251 : pSVData->mpFirstSchedulerData = NULL;
98 251 : pSVData->mnTimerPeriod = 0;
99 : }
100 :
101 361 : delete pSVData->mpSalTimer;
102 361 : pSVData->mpSalTimer = 0;
103 361 : }
104 :
105 13383082 : void Scheduler::CallbackTaskScheduling(bool ignore)
106 : {
107 : // this function is for the saltimer callback
108 : (void)ignore;
109 13383082 : Scheduler::ProcessTaskScheduling( true );
110 13383082 : }
111 :
112 26865091 : void Scheduler::ProcessTaskScheduling( bool bTimer )
113 : {
114 : // process all pending Tasks
115 : // if bTimer True, only handle timer
116 26865091 : ImplSchedulerData* pSchedulerData = NULL;
117 26865091 : ImplSchedulerData* pPrevSchedulerData = NULL;
118 26865091 : ImplSVData* pSVData = ImplGetSVData();
119 26865091 : sal_uInt64 nTime = tools::Time::GetSystemTicks();
120 26865091 : sal_uInt64 nMinPeriod = MAX_TIMER_PERIOD;
121 26865091 : pSVData->mnUpdateStack++;
122 :
123 : // tdf#91727 - NB. bTimer is ultimately not used
124 26865091 : if ((pSchedulerData = ImplSchedulerData::GetMostImportantTask(bTimer)))
125 : {
126 26833139 : pSchedulerData->mnUpdateTime = nTime;
127 26833139 : pSchedulerData->Invoke();
128 : }
129 :
130 26865091 : pSchedulerData = pSVData->mpFirstSchedulerData;
131 144046542 : while ( pSchedulerData )
132 : {
133 90316360 : if( pSchedulerData->mbInScheduler )
134 : {
135 269 : pPrevSchedulerData = pSchedulerData;
136 269 : pSchedulerData = pSchedulerData->mpNext;
137 : }
138 : // Should Task be released from scheduling?
139 90316091 : else if ( pSchedulerData->mbDelete )
140 : {
141 74346 : if ( pPrevSchedulerData )
142 73944 : pPrevSchedulerData->mpNext = pSchedulerData->mpNext;
143 : else
144 402 : pSVData->mpFirstSchedulerData = pSchedulerData->mpNext;
145 74346 : if ( pSchedulerData->mpScheduler )
146 42157 : pSchedulerData->mpScheduler->mpSchedulerData = NULL;
147 74346 : ImplSchedulerData* pTempSchedulerData = pSchedulerData;
148 74346 : pSchedulerData = pSchedulerData->mpNext;
149 74346 : delete pTempSchedulerData;
150 : }
151 : else
152 : {
153 90241745 : pSchedulerData->mnUpdateStack = 0;
154 90241745 : nMinPeriod = pSchedulerData->mpScheduler->UpdateMinPeriod( nMinPeriod, nTime );
155 90241745 : pPrevSchedulerData = pSchedulerData;
156 90241745 : pSchedulerData = pSchedulerData->mpNext;
157 : }
158 : }
159 :
160 : // delete clock if no more timers available
161 26865091 : if ( !pSVData->mpFirstSchedulerData )
162 : {
163 375 : if ( pSVData->mpSalTimer )
164 288 : pSVData->mpSalTimer->Stop();
165 375 : pSVData->mnTimerPeriod = MAX_TIMER_PERIOD;
166 : }
167 : else
168 : {
169 26864716 : Timer::ImplStartTimer( pSVData, nMinPeriod );
170 : }
171 26865091 : pSVData->mnUpdateStack--;
172 26865091 : }
173 :
174 248545 : void Scheduler::SetPriority( SchedulerPriority ePriority )
175 : {
176 248545 : mePriority = ePriority;
177 248545 : }
178 :
179 27151046 : void Scheduler::Start()
180 : {
181 : // Mark timer active
182 27151046 : mbActive = true;
183 :
184 27151046 : ImplSVData* pSVData = ImplGetSVData();
185 27151046 : if ( !mpSchedulerData )
186 : {
187 : // insert Scheduler
188 79054 : mpSchedulerData = new ImplSchedulerData;
189 79054 : mpSchedulerData->mpScheduler = this;
190 79054 : mpSchedulerData->mbInScheduler = false;
191 :
192 : // insert last due to SFX!
193 79054 : ImplSchedulerData* pPrev = NULL;
194 79054 : ImplSchedulerData* pData = pSVData->mpFirstSchedulerData;
195 1755164 : while ( pData )
196 : {
197 1597056 : pPrev = pData;
198 1597056 : pData = pData->mpNext;
199 : }
200 79054 : mpSchedulerData->mpNext = NULL;
201 79054 : if ( pPrev )
202 78560 : pPrev->mpNext = mpSchedulerData;
203 : else
204 494 : pSVData->mpFirstSchedulerData = mpSchedulerData;
205 : }
206 27151046 : mpSchedulerData->mbDelete = false;
207 27151046 : mpSchedulerData->mnUpdateTime = tools::Time::GetSystemTicks();
208 27151046 : mpSchedulerData->mnUpdateStack = pSVData->mnUpdateStack;
209 27151046 : }
210 :
211 677754 : void Scheduler::Stop()
212 : {
213 677754 : mbActive = false;
214 :
215 677754 : if ( mpSchedulerData )
216 300051 : mpSchedulerData->mbDelete = true;
217 677754 : }
218 :
219 51 : Scheduler& Scheduler::operator=( const Scheduler& rScheduler )
220 : {
221 51 : if ( IsActive() )
222 9 : Stop();
223 :
224 51 : mbActive = false;
225 51 : mePriority = rScheduler.mePriority;
226 :
227 51 : if ( rScheduler.IsActive() )
228 11 : Start();
229 :
230 51 : return *this;
231 : }
232 :
233 501559 : Scheduler::Scheduler(const sal_Char *pDebugName):
234 : mpSchedulerData(NULL),
235 : mpDebugName(pDebugName),
236 : mePriority(SchedulerPriority::HIGH),
237 501559 : mbActive(false)
238 : {
239 501559 : }
240 :
241 421 : Scheduler::Scheduler( const Scheduler& rScheduler ):
242 : mpSchedulerData(NULL),
243 : mpDebugName(rScheduler.mpDebugName),
244 : mePriority(rScheduler.mePriority),
245 421 : mbActive(false)
246 : {
247 421 : if ( rScheduler.IsActive() )
248 29 : Start();
249 421 : }
250 :
251 474772 : Scheduler::~Scheduler()
252 : {
253 474772 : if ( mpSchedulerData )
254 : {
255 36371 : mpSchedulerData->mbDelete = true;
256 36371 : mpSchedulerData->mpScheduler = NULL;
257 : }
258 474772 : }
259 :
|