1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 .
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
)
33 // prepare Scheduler Object for deletion after handling
34 mpScheduler
->SetDeletionFlags();
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())
53 pMostUrgent
= pSchedulerData
;
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
;
67 void Scheduler::SetDeletionFlags()
69 mpSchedulerData
->mbDelete
= true;
73 void Scheduler::ImplDeInitScheduler()
75 ImplSVData
* pSVData
= ImplGetSVData();
76 ImplSchedulerData
* pSchedulerData
= pSVData
->mpFirstSchedulerData
;
77 if (pSVData
->mpSalTimer
)
79 pSVData
->mpSalTimer
->Stop();
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
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
;
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
;
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
;
169 Timer::ImplStartTimer( pSVData
, nMinPeriod
);
171 pSVData
->mnUpdateStack
--;
174 void Scheduler::SetPriority( SchedulerPriority ePriority
)
176 mePriority
= ePriority
;
179 void Scheduler::Start()
184 ImplSVData
* pSVData
= ImplGetSVData();
185 if ( !mpSchedulerData
)
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
;
198 pData
= pData
->mpNext
;
200 mpSchedulerData
->mpNext
= NULL
;
202 pPrev
->mpNext
= mpSchedulerData
;
204 pSVData
->mpFirstSchedulerData
= mpSchedulerData
;
206 mpSchedulerData
->mbDelete
= false;
207 mpSchedulerData
->mnUpdateTime
= tools::Time::GetSystemTicks();
208 mpSchedulerData
->mnUpdateStack
= pSVData
->mnUpdateStack
;
211 void Scheduler::Stop()
215 if ( mpSchedulerData
)
216 mpSchedulerData
->mbDelete
= true;
219 Scheduler
& Scheduler::operator=( const Scheduler
& rScheduler
)
225 mePriority
= rScheduler
.mePriority
;
227 if ( rScheduler
.IsActive() )
233 Scheduler::Scheduler(const sal_Char
*pDebugName
):
234 mpSchedulerData(NULL
),
235 mpDebugName(pDebugName
),
236 mePriority(SchedulerPriority::HIGH
),
241 Scheduler::Scheduler( const Scheduler
& rScheduler
):
242 mpSchedulerData(NULL
),
243 mpDebugName(rScheduler
.mpDebugName
),
244 mePriority(rScheduler
.mePriority
),
247 if ( rScheduler
.IsActive() )
251 Scheduler::~Scheduler()
253 if ( mpSchedulerData
)
255 mpSchedulerData
->mbDelete
= true;
256 mpSchedulerData
->mpScheduler
= NULL
;