Branch libreoffice-5-0-4
[LibreOffice.git] / vcl / source / app / scheduler.cxx
blobc3cea781e6b892a6d1ab9c6f8d09aa978db0a421
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <svdata.hxx>
21 #include <tools/time.hxx>
22 #include <vcl/scheduler.hxx>
23 #include <vcl/timer.hxx>
24 #include <saltimer.hxx>
26 #define MAX_TIMER_PERIOD SAL_MAX_UINT64
28 void ImplSchedulerData::Invoke()
30 if (mbDelete || mbInScheduler )
31 return;
33 // prepare Scheduler Object for deletion after handling
34 mpScheduler->SetDeletionFlags();
36 // invoke it
37 mbInScheduler = true;
38 mpScheduler->Invoke();
39 mbInScheduler = false;
42 ImplSchedulerData *ImplSchedulerData::GetMostImportantTask( bool bTimer )
44 ImplSVData* pSVData = ImplGetSVData();
45 ImplSchedulerData *pMostUrgent = NULL;
47 for ( ImplSchedulerData *pSchedulerData = pSVData->mpFirstSchedulerData; pSchedulerData; pSchedulerData = pSchedulerData->mpNext )
49 if ( !pSchedulerData->mpScheduler || pSchedulerData->mbDelete || pSchedulerData->mnUpdateStack >= pSVData->mnUpdateStack
50 || !pSchedulerData->mpScheduler->ReadyForSchedule( bTimer ) || !pSchedulerData->mpScheduler->IsActive())
51 continue;
52 if (!pMostUrgent)
53 pMostUrgent = pSchedulerData;
54 else
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 if ( pSchedulerData->mpScheduler->GetPriority() < pMostUrgent->mpScheduler->GetPriority() )
60 pMostUrgent = pSchedulerData;
64 return pMostUrgent;
67 void Scheduler::SetDeletionFlags()
69 mpSchedulerData->mbDelete = true;
70 mbActive = false;
73 void Scheduler::ImplDeInitScheduler()
75 ImplSVData* pSVData = ImplGetSVData();
76 ImplSchedulerData* pSchedulerData = pSVData->mpFirstSchedulerData;
77 if (pSVData->mpSalTimer)
79 pSVData->mpSalTimer->Stop();
82 if ( pSchedulerData )
86 ImplSchedulerData* pTempSchedulerData = pSchedulerData;
87 if ( pSchedulerData->mpScheduler )
89 pSchedulerData->mpScheduler->mbActive = false;
90 pSchedulerData->mpScheduler->mpSchedulerData = NULL;
92 pSchedulerData = pSchedulerData->mpNext;
93 delete pTempSchedulerData;
95 while ( pSchedulerData );
97 pSVData->mpFirstSchedulerData = NULL;
98 pSVData->mnTimerPeriod = 0;
101 delete pSVData->mpSalTimer;
102 pSVData->mpSalTimer = 0;
105 void Scheduler::CallbackTaskScheduling(bool ignore)
107 // this function is for the saltimer callback
108 (void)ignore;
109 Scheduler::ProcessTaskScheduling( true );
112 void Scheduler::ProcessTaskScheduling( bool bTimer )
114 // process all pending Tasks
115 // if bTimer True, only handle timer
116 ImplSchedulerData* pSchedulerData = NULL;
117 ImplSchedulerData* pPrevSchedulerData = NULL;
118 ImplSVData* pSVData = ImplGetSVData();
119 sal_uInt64 nTime = tools::Time::GetSystemTicks();
120 sal_uInt64 nMinPeriod = MAX_TIMER_PERIOD;
121 pSVData->mnUpdateStack++;
123 // tdf#91727 - NB. bTimer is ultimately not used
124 if ((pSchedulerData = ImplSchedulerData::GetMostImportantTask(bTimer)))
126 pSchedulerData->mnUpdateTime = nTime;
127 pSchedulerData->Invoke();
130 pSchedulerData = pSVData->mpFirstSchedulerData;
131 while ( pSchedulerData )
133 if( pSchedulerData->mbInScheduler )
135 pPrevSchedulerData = pSchedulerData;
136 pSchedulerData = pSchedulerData->mpNext;
138 // Should Task be released from scheduling?
139 else if ( pSchedulerData->mbDelete )
141 if ( pPrevSchedulerData )
142 pPrevSchedulerData->mpNext = pSchedulerData->mpNext;
143 else
144 pSVData->mpFirstSchedulerData = pSchedulerData->mpNext;
145 if ( pSchedulerData->mpScheduler )
146 pSchedulerData->mpScheduler->mpSchedulerData = NULL;
147 ImplSchedulerData* pTempSchedulerData = pSchedulerData;
148 pSchedulerData = pSchedulerData->mpNext;
149 delete pTempSchedulerData;
151 else
153 pSchedulerData->mnUpdateStack = 0;
154 nMinPeriod = pSchedulerData->mpScheduler->UpdateMinPeriod( nMinPeriod, nTime );
155 pPrevSchedulerData = pSchedulerData;
156 pSchedulerData = pSchedulerData->mpNext;
160 // delete clock if no more timers available
161 if ( !pSVData->mpFirstSchedulerData )
163 if ( pSVData->mpSalTimer )
164 pSVData->mpSalTimer->Stop();
165 pSVData->mnTimerPeriod = MAX_TIMER_PERIOD;
167 else
169 Timer::ImplStartTimer( pSVData, nMinPeriod );
171 pSVData->mnUpdateStack--;
174 void Scheduler::SetPriority( SchedulerPriority ePriority )
176 mePriority = ePriority;
179 void Scheduler::Start()
181 // Mark timer active
182 mbActive = true;
184 ImplSVData* pSVData = ImplGetSVData();
185 if ( !mpSchedulerData )
187 // insert Scheduler
188 mpSchedulerData = new ImplSchedulerData;
189 mpSchedulerData->mpScheduler = this;
190 mpSchedulerData->mbInScheduler = false;
192 // insert last due to SFX!
193 ImplSchedulerData* pPrev = NULL;
194 ImplSchedulerData* pData = pSVData->mpFirstSchedulerData;
195 while ( pData )
197 pPrev = pData;
198 pData = pData->mpNext;
200 mpSchedulerData->mpNext = NULL;
201 if ( pPrev )
202 pPrev->mpNext = mpSchedulerData;
203 else
204 pSVData->mpFirstSchedulerData = mpSchedulerData;
206 mpSchedulerData->mbDelete = false;
207 mpSchedulerData->mnUpdateTime = tools::Time::GetSystemTicks();
208 mpSchedulerData->mnUpdateStack = pSVData->mnUpdateStack;
211 void Scheduler::Stop()
213 mbActive = false;
215 if ( mpSchedulerData )
216 mpSchedulerData->mbDelete = true;
219 Scheduler& Scheduler::operator=( const Scheduler& rScheduler )
221 if ( IsActive() )
222 Stop();
224 mbActive = false;
225 mePriority = rScheduler.mePriority;
227 if ( rScheduler.IsActive() )
228 Start();
230 return *this;
233 Scheduler::Scheduler(const sal_Char *pDebugName):
234 mpSchedulerData(NULL),
235 mpDebugName(pDebugName),
236 mePriority(SchedulerPriority::HIGH),
237 mbActive(false)
241 Scheduler::Scheduler( const Scheduler& rScheduler ):
242 mpSchedulerData(NULL),
243 mpDebugName(rScheduler.mpDebugName),
244 mePriority(rScheduler.mePriority),
245 mbActive(false)
247 if ( rScheduler.IsActive() )
248 Start();
251 Scheduler::~Scheduler()
253 if ( mpSchedulerData )
255 mpSchedulerData->mbDelete = true;
256 mpSchedulerData->mpScheduler = NULL;