LibreOffice Module vcl (master) 1
scheduler.cxx
Go to the documentation of this file.
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 <sal/config.h>
21
22#include <cassert>
23#include <cstdlib>
24#include <exception>
25#include <typeinfo>
26
27#include <com/sun/star/uno/Exception.hpp>
28#include <sal/log.hxx>
29#include <sal/types.h>
30#include <svdata.hxx>
31#include <tools/time.hxx>
32#include <tools/debug.hxx>
35#include <vcl/TaskStopwatch.hxx>
36#include <vcl/scheduler.hxx>
37#include <vcl/idle.hxx>
38#include <saltimer.hxx>
39#include <salinst.hxx>
41#include <schedulerimpl.hxx>
42
43namespace {
44
45template< typename charT, typename traits >
46std::basic_ostream<charT, traits> & operator <<(
47 std::basic_ostream<charT, traits> & stream, const Task& task )
48{
49 stream << "a: " << task.IsActive() << " p: " << static_cast<int>(task.GetPriority());
50 const char *name = task.GetDebugName();
51 if( nullptr == name )
52 return stream << " (nullptr)";
53 else
54 return stream << " " << name;
55}
56
64template< typename charT, typename traits >
65std::basic_ostream<charT, traits> & operator <<(
66 std::basic_ostream<charT, traits> & stream, const Timer& timer )
67{
68 bool bIsIdle = (dynamic_cast<const Idle*>( &timer ) != nullptr);
69 stream << (bIsIdle ? "Idle " : "Timer")
70 << " a: " << timer.IsActive() << " p: " << static_cast<int>(timer.GetPriority());
71 const char *name = timer.GetDebugName();
72 if ( nullptr == name )
73 stream << " (nullptr)";
74 else
75 stream << " " << name;
76 if ( !bIsIdle )
77 stream << " " << timer.GetTimeout() << "ms";
78 stream << " (" << &timer << ")";
79 return stream;
80}
81
82template< typename charT, typename traits >
83std::basic_ostream<charT, traits> & operator <<(
84 std::basic_ostream<charT, traits> & stream, const Idle& idle )
85{
86 return stream << static_cast<const Timer*>( &idle );
87}
88
89template< typename charT, typename traits >
90std::basic_ostream<charT, traits> & operator <<(
91 std::basic_ostream<charT, traits> & stream, const ImplSchedulerData& data )
92{
93 stream << " i: " << data.mbInScheduler;
94 return stream;
95}
96
97} // end anonymous namespace
98
100
102{
103 ImplSVData* pSVData = ImplGetSVData();
104 assert( pSVData != nullptr );
105 ImplSchedulerContext &rSchedCtx = pSVData->maSchedCtx;
106
108
109 SchedulerGuard aSchedulerGuard;
110
111 int nTaskPriority = 0;
112#if OSL_DEBUG_LEVEL > 0
113 sal_uInt32 nTasks = 0;
114 for (nTaskPriority = 0; nTaskPriority < PRIO_COUNT; ++nTaskPriority)
115 {
116 ImplSchedulerData* pSchedulerData = rSchedCtx.mpFirstSchedulerData[nTaskPriority];
117 while ( pSchedulerData )
118 {
119 ++nTasks;
120 pSchedulerData = pSchedulerData->mpNext;
121 }
122 }
123 SAL_INFO( "vcl.schedule.deinit",
124 "DeInit the scheduler - pending tasks: " << nTasks );
125
126 // clean up all the sfx::SfxItemDisruptor_Impl Idles
127 Unlock();
129 Lock();
130#endif
131 rSchedCtx.mbActive = false;
132
133 assert( nullptr == rSchedCtx.mpSchedulerStack );
134
135 if (rSchedCtx.mpSalTimer) rSchedCtx.mpSalTimer->Stop();
136 delete rSchedCtx.mpSalTimer;
137 rSchedCtx.mpSalTimer = nullptr;
138
139#if OSL_DEBUG_LEVEL > 0
140 sal_uInt32 nActiveTasks = 0, nIgnoredTasks = 0;
141#endif
142 nTaskPriority = 0;
143 ImplSchedulerData* pSchedulerData = nullptr;
144
145next_priority:
146 pSchedulerData = rSchedCtx.mpFirstSchedulerData[nTaskPriority];
147 while ( pSchedulerData )
148 {
149 Task *pTask = pSchedulerData->mpTask;
150 if ( pTask )
151 {
152 if ( pTask->mbActive )
153 {
154#if OSL_DEBUG_LEVEL > 0
155 const char *sIgnored = "";
156 ++nActiveTasks;
157 // TODO: shutdown these timers before Scheduler de-init
158 // TODO: remove Task from static object
159 if ( pTask->GetDebugName() && ( false
160 || !strcmp( pTask->GetDebugName(), "desktop::Desktop m_firstRunTimer" )
161 || !strcmp( pTask->GetDebugName(), "DrawWorkStartupTimer" )
162 || !strcmp( pTask->GetDebugName(), "editeng::ImpEditEngine aOnlineSpellTimer" )
163 || !strcmp( pTask->GetDebugName(), "ImplHandleMouseMsg SalData::mpMouseLeaveTimer" )
164 || !strcmp( pTask->GetDebugName(), "sc ScModule IdleTimer" )
165 || !strcmp( pTask->GetDebugName(), "sd::CacheConfiguration maReleaseTimer" )
166 || !strcmp( pTask->GetDebugName(), "svtools::GraphicCache maReleaseTimer" )
167 || !strcmp( pTask->GetDebugName(), "svtools::GraphicObject mpSwapOutTimer" )
168 || !strcmp( pTask->GetDebugName(), "svx OLEObjCache pTimer UnloadCheck" )
169 || !strcmp( pTask->GetDebugName(), "vcl SystemDependentDataBuffer aSystemDependentDataBuffer" )
170 ))
171 {
172 sIgnored = " (ignored)";
173 ++nIgnoredTasks;
174 }
175 const Timer *timer = dynamic_cast<Timer*>( pTask );
176 if ( timer )
177 SAL_WARN( "vcl.schedule.deinit", "DeInit task: " << *timer << sIgnored );
178 else
179 SAL_WARN( "vcl.schedule.deinit", "DeInit task: " << *pTask << sIgnored );
180#endif
181 pTask->mbActive = false;
182 }
183 pTask->mpSchedulerData = nullptr;
184 pTask->SetStatic();
185 }
186 ImplSchedulerData* pDeleteSchedulerData = pSchedulerData;
187 pSchedulerData = pSchedulerData->mpNext;
188 delete pDeleteSchedulerData;
189 }
190
191 ++nTaskPriority;
192 if (nTaskPriority < PRIO_COUNT)
193 goto next_priority;
194
195#if OSL_DEBUG_LEVEL > 0
196 SAL_INFO( "vcl.schedule.deinit", "DeInit the scheduler - finished" );
197 SAL_WARN_IF( 0 != nActiveTasks, "vcl.schedule.deinit", "DeInit active tasks: "
198 << nActiveTasks << " (ignored: " << nIgnoredTasks << ")" );
199// assert( nIgnoredTasks == nActiveTasks );
200#endif
201
202 for (nTaskPriority = 0; nTaskPriority < PRIO_COUNT; ++nTaskPriority)
203 {
204 rSchedCtx.mpFirstSchedulerData[nTaskPriority] = nullptr;
205 rSchedCtx.mpLastSchedulerData[nTaskPriority] = nullptr;
206 }
208}
209
211{
212 ImplSVData* pSVData = ImplGetSVData();
213 assert( pSVData != nullptr );
214 pSVData->maSchedCtx.maMutex.lock();
215}
216
218{
219 ImplSVData* pSVData = ImplGetSVData();
220 assert( pSVData != nullptr );
221 pSVData->maSchedCtx.maMutex.unlock();
222}
223
231void Scheduler::ImplStartTimer(sal_uInt64 nMS, bool bForce, sal_uInt64 nTime)
232{
233 ImplSVData* pSVData = ImplGetSVData();
234 ImplSchedulerContext &rSchedCtx = pSVData->maSchedCtx;
235 if ( !rSchedCtx.mbActive )
236 return;
237
238 if (!rSchedCtx.mpSalTimer)
239 {
240 rSchedCtx.mnTimerStart = 0;
242 rSchedCtx.mpSalTimer = pSVData->mpDefInst->CreateSalTimer();
244 }
245
246 assert(SAL_MAX_UINT64 - nMS >= nTime);
247
248 sal_uInt64 nProposedTimeout = nTime + nMS;
249 sal_uInt64 nCurTimeout = ( rSchedCtx.mnTimerPeriod == InfiniteTimeoutMs )
250 ? SAL_MAX_UINT64 : rSchedCtx.mnTimerStart + rSchedCtx.mnTimerPeriod;
251
252 // Only if smaller timeout, to avoid skipping.
253 // Force instant wakeup on 0ms, if the previous period was not 0ms
254 if (bForce || nProposedTimeout < nCurTimeout || (!nMS && rSchedCtx.mnTimerPeriod))
255 {
256 SAL_INFO( "vcl.schedule", " Starting scheduler system timer (" << nMS << "ms)" );
257 rSchedCtx.mnTimerStart = nTime;
258 rSchedCtx.mnTimerPeriod = nMS;
259 rSchedCtx.mpSalTimer->Start( nMS );
260 }
261}
262
263static bool g_bDeterministicMode = false;
264
265void Scheduler::SetDeterministicMode(bool bDeterministic)
266{
267 g_bDeterministicMode = bDeterministic;
268}
269
271{
273}
274
276 const sal_uInt64 nMinPeriod,
277 const bool bForce, const sal_uInt64 nTime )
278{
279 if ( InfiniteTimeoutMs == nMinPeriod )
280 {
281 SAL_INFO("vcl.schedule", " Stopping system timer");
282 if ( rSchedCtx.mpSalTimer )
283 rSchedCtx.mpSalTimer->Stop();
284 rSchedCtx.mnTimerPeriod = nMinPeriod;
285 }
286 else
287 Scheduler::ImplStartTimer( nMinPeriod, bForce, nTime );
288}
289
291 ImplSchedulerData * const pSchedulerData)
292{
293 assert(pSchedulerData->mpTask);
294 pSchedulerData->mePriority = pSchedulerData->mpTask->GetPriority();
295 pSchedulerData->mpNext = nullptr;
296
297 const int nTaskPriority = static_cast<int>(pSchedulerData->mePriority);
298 if (!rSchedCtx.mpLastSchedulerData[nTaskPriority])
299 {
300 rSchedCtx.mpFirstSchedulerData[nTaskPriority] = pSchedulerData;
301 rSchedCtx.mpLastSchedulerData[nTaskPriority] = pSchedulerData;
302 }
303 else
304 {
305 rSchedCtx.mpLastSchedulerData[nTaskPriority]->mpNext = pSchedulerData;
306 rSchedCtx.mpLastSchedulerData[nTaskPriority] = pSchedulerData;
307 }
308}
309
311 ImplSchedulerContext &rSchedCtx, ImplSchedulerData * const pPrevSchedulerData,
312 const ImplSchedulerData * const pSchedulerData, const int nTaskPriority)
313{
314 assert( pSchedulerData );
315 if ( pPrevSchedulerData )
316 assert( pPrevSchedulerData->mpNext == pSchedulerData );
317 else
318 assert(rSchedCtx.mpFirstSchedulerData[nTaskPriority] == pSchedulerData);
319
320 ImplSchedulerData * const pSchedulerDataNext = pSchedulerData->mpNext;
321 if ( pPrevSchedulerData )
322 pPrevSchedulerData->mpNext = pSchedulerDataNext;
323 else
324 rSchedCtx.mpFirstSchedulerData[nTaskPriority] = pSchedulerDataNext;
325 if ( !pSchedulerDataNext )
326 rSchedCtx.mpLastSchedulerData[nTaskPriority] = pPrevSchedulerData;
327 return pSchedulerDataNext;
328}
329
331{
332 ImplSVData *pSVData = ImplGetSVData();
333 ImplSchedulerContext &rSchedCtx = pSVData->maSchedCtx;
334
336
337 SchedulerGuard aSchedulerGuard;
338 if ( !rSchedCtx.mbActive || InfiniteTimeoutMs == rSchedCtx.mnTimerPeriod )
339 return;
340
341 sal_uInt64 nTime = tools::Time::GetSystemTicks();
342 // Allow for decimals, so subtract in the compare (needed at least on iOS)
343 if ( nTime < rSchedCtx.mnTimerStart + rSchedCtx.mnTimerPeriod -1)
344 {
345 int nSleep = rSchedCtx.mnTimerStart + rSchedCtx.mnTimerPeriod - nTime;
346 UpdateSystemTimer(rSchedCtx, nSleep, true, nTime);
347 return;
348 }
349
350 ImplSchedulerData* pSchedulerData = nullptr;
351 ImplSchedulerData* pPrevSchedulerData = nullptr;
352 ImplSchedulerData *pMostUrgent = nullptr;
353 ImplSchedulerData *pPrevMostUrgent = nullptr;
354 int nMostUrgentPriority = 0;
355 sal_uInt64 nMinPeriod = InfiniteTimeoutMs;
356 sal_uInt64 nReadyPeriod = InfiniteTimeoutMs;
357 unsigned nTasks = 0;
358 int nTaskPriority = 0;
359
360 for (; nTaskPriority < PRIO_COUNT; ++nTaskPriority)
361 {
362 pSchedulerData = rSchedCtx.mpFirstSchedulerData[nTaskPriority];
363 pPrevSchedulerData = nullptr;
364 while (pSchedulerData)
365 {
366 ++nTasks;
367 const Timer *timer = dynamic_cast<Timer*>( pSchedulerData->mpTask );
368 if ( timer )
369 SAL_INFO( "vcl.schedule", tools::Time::GetSystemTicks() << " "
370 << pSchedulerData << " " << *pSchedulerData << " " << *timer );
371 else if ( pSchedulerData->mpTask )
372 SAL_INFO( "vcl.schedule", tools::Time::GetSystemTicks() << " "
373 << pSchedulerData << " " << *pSchedulerData
374 << " " << *pSchedulerData->mpTask );
375 else
376 SAL_INFO( "vcl.schedule", tools::Time::GetSystemTicks() << " "
377 << pSchedulerData << " " << *pSchedulerData << " (to be deleted)" );
378
379 // Should the Task be released from scheduling?
380 assert(!pSchedulerData->mbInScheduler);
381 if (!pSchedulerData->mpTask || !pSchedulerData->mpTask->IsActive())
382 {
383 ImplSchedulerData * const pSchedulerDataNext =
384 DropSchedulerData(rSchedCtx, pPrevSchedulerData, pSchedulerData, nTaskPriority);
385 if ( pSchedulerData->mpTask )
386 pSchedulerData->mpTask->mpSchedulerData = nullptr;
387 delete pSchedulerData;
388 pSchedulerData = pSchedulerDataNext;
389 continue;
390 }
391
392 assert(pSchedulerData->mpTask);
393 if (pSchedulerData->mpTask->IsActive())
394 {
395 nReadyPeriod = pSchedulerData->mpTask->UpdateMinPeriod( nTime );
396 if (ImmediateTimeoutMs == nReadyPeriod)
397 {
398 if (!pMostUrgent)
399 {
400 pPrevMostUrgent = pPrevSchedulerData;
401 pMostUrgent = pSchedulerData;
402 nMostUrgentPriority = nTaskPriority;
403 }
404 else
405 {
406 nMinPeriod = ImmediateTimeoutMs;
407 break;
408 }
409 }
410 else if (nMinPeriod > nReadyPeriod)
411 nMinPeriod = nReadyPeriod;
412 }
413
414 pPrevSchedulerData = pSchedulerData;
415 pSchedulerData = pSchedulerData->mpNext;
416 }
417
418 if (ImmediateTimeoutMs == nMinPeriod)
419 break;
420 }
421
422 // Delay invoking tasks with idle priorities as long as there are user input or repaint events
423 // in the OS event queue. This will often effectively compress such events and repaint only
424 // once at the end, improving performance in cases such as repeated zooming with a complex document.
425 if ( pMostUrgent && pMostUrgent->mePriority >= TaskPriority::HIGH_IDLE
427 {
428 SAL_INFO( "vcl.schedule", tools::Time::GetSystemTicks()
429 << " idle priority task " << pMostUrgent << " delayed, system events pending" );
430 pMostUrgent = nullptr;
431 nMinPeriod = 0;
432 }
433
434 if (InfiniteTimeoutMs != nMinPeriod)
435 SAL_INFO("vcl.schedule",
436 "Calculated minimum timeout as " << nMinPeriod << " of " << nTasks << " tasks");
437 UpdateSystemTimer(rSchedCtx, nMinPeriod, true, nTime);
438
439 if ( !pMostUrgent )
440 return;
441
442 SAL_INFO( "vcl.schedule", tools::Time::GetSystemTicks() << " "
443 << pMostUrgent << " invoke-in " << *pMostUrgent->mpTask );
444
445 Task *pTask = pMostUrgent->mpTask;
446
447 comphelper::ProfileZone aZone( pTask->GetDebugName() );
448
449 // prepare Scheduler object for deletion after handling
450 pTask->SetDeletionFlags();
451
452 assert(!pMostUrgent->mbInScheduler);
453 pMostUrgent->mbInScheduler = true;
454
455 // always push the stack, as we don't traverse the whole list to push later
456 DropSchedulerData(rSchedCtx, pPrevMostUrgent, pMostUrgent, nMostUrgentPriority);
457 pMostUrgent->mpNext = rSchedCtx.mpSchedulerStack;
458 rSchedCtx.mpSchedulerStack = pMostUrgent;
459 rSchedCtx.mpSchedulerStackTop = pMostUrgent;
460
461 // invoke the task
462 Unlock();
463 /*
464 * Current policy is that scheduler tasks aren't allowed to throw an exception.
465 * Because otherwise the exception is caught somewhere totally unrelated.
466 * TODO Ideally we could capture a proper backtrace and feed this into breakpad,
467 * which is do-able, but requires writing some assembly.
468 * See also SalUserEventList::DispatchUserEvents
469 */
470 try
471 {
472 pTask->Invoke();
473 }
474 catch (css::uno::Exception&)
475 {
476 TOOLS_WARN_EXCEPTION("vcl.schedule", "Uncaught");
477 std::abort();
478 }
479 catch (std::exception& e)
480 {
481 SAL_WARN("vcl.schedule", "Uncaught " << typeid(e).name() << " " << e.what());
482 std::abort();
483 }
484 catch (...)
485 {
486 SAL_WARN("vcl.schedule", "Uncaught exception during Task::Invoke()!");
487 std::abort();
488 }
489 Lock();
490
491 assert(pMostUrgent->mbInScheduler);
492 pMostUrgent->mbInScheduler = false;
493
494 SAL_INFO( "vcl.schedule", tools::Time::GetSystemTicks() << " "
495 << pMostUrgent << " invoke-out" );
496
497 // pop the scheduler stack
498 pSchedulerData = rSchedCtx.mpSchedulerStack;
499 assert(pSchedulerData == pMostUrgent);
500 rSchedCtx.mpSchedulerStack = pSchedulerData->mpNext;
501
502 // coverity[check_after_deref : FALSE] - pMostUrgent->mpTask is initially pMostUrgent->mpTask, but Task::Invoke can clear it
503 const bool bTaskAlive = pMostUrgent->mpTask && pMostUrgent->mpTask->IsActive();
504 if (!bTaskAlive)
505 {
506 if (pMostUrgent->mpTask)
507 pMostUrgent->mpTask->mpSchedulerData = nullptr;
508 delete pMostUrgent;
509 }
510 else
511 AppendSchedulerData(rSchedCtx, pMostUrgent);
512
513 // this just happens for nested calls, which renders all accounting
514 // invalid, so we just enforce a rescheduling!
515 if (rSchedCtx.mpSchedulerStackTop != pSchedulerData)
516 {
517 UpdateSystemTimer( rSchedCtx, ImmediateTimeoutMs, true,
519 }
520 else if (bTaskAlive)
521 {
522 pMostUrgent->mnUpdateTime = nTime;
523 nReadyPeriod = pMostUrgent->mpTask->UpdateMinPeriod( nTime );
524 if ( nMinPeriod > nReadyPeriod )
525 nMinPeriod = nReadyPeriod;
526 UpdateSystemTimer( rSchedCtx, nMinPeriod, false, nTime );
527 }
528}
529
531{
533}
534
535void Task::StartTimer( sal_uInt64 nMS )
536{
538}
539
541{
542 mbActive = false;
543}
544
545void Task::Start(const bool bStartTimer)
546{
547 ImplSVData *const pSVData = ImplGetSVData();
548 ImplSchedulerContext &rSchedCtx = pSVData->maSchedCtx;
549
550 SchedulerGuard aSchedulerGuard;
551 if ( !rSchedCtx.mbActive )
552 return;
553
554 // is the task scheduled in the correct priority queue?
555 // if not we have to get a new data object, as we don't want to traverse
556 // the whole list to move the data to the correct list, as the task list
557 // is just single linked.
558 // Task priority doesn't change that often AFAIK, or we might need to
559 // start caching ImplSchedulerData objects.
561 {
562 mpSchedulerData->mpTask = nullptr;
563 mpSchedulerData = nullptr;
564 }
565 mbActive = true;
566
567 if ( !mpSchedulerData )
568 {
569 // insert Task
570 ImplSchedulerData* pSchedulerData = new ImplSchedulerData;
571 pSchedulerData->mpTask = this;
572 pSchedulerData->mbInScheduler = false;
573 // mePriority is set in AppendSchedulerData
574 mpSchedulerData = pSchedulerData;
575
576 AppendSchedulerData( rSchedCtx, pSchedulerData );
577 SAL_INFO( "vcl.schedule", tools::Time::GetSystemTicks()
578 << " " << mpSchedulerData << " added " << *this );
579 }
580 else
581 SAL_INFO( "vcl.schedule", tools::Time::GetSystemTicks()
582 << " " << mpSchedulerData << " restarted " << *this );
583
585
586 if (bStartTimer)
588}
589
591{
593 << " " << mpSchedulerData << " stopped " << *this );
594 mbActive = false;
595}
596
598{
599 // you don't actually need to call Stop() before but Start() after, but we
600 // can't check that and don't know when Start() should be called.
601 SAL_WARN_IF(mpSchedulerData && mbActive, "vcl.schedule",
602 "Stop the task before changing the priority, as it will just "
603 "change after the task was scheduled with the old prio!");
604 mePriority = ePriority;
605}
606
607Task& Task::operator=( const Task& rTask )
608{
609 if(this == &rTask)
610 return *this;
611
612 if ( IsActive() )
613 Stop();
614
615 mbActive = false;
616 mePriority = rTask.mePriority;
617
618 if ( rTask.IsActive() )
619 Start();
620
621 return *this;
622}
623
624Task::Task( const char *pDebugName )
625 : mpSchedulerData( nullptr )
626 , mpDebugName( pDebugName )
627 , mePriority( TaskPriority::DEFAULT )
628 , mbActive( false )
629 , mbStatic( false )
630{
631 assert(mpDebugName);
632}
633
634Task::Task( const Task& rTask )
635 : mpSchedulerData( nullptr )
636 , mpDebugName( rTask.mpDebugName )
637 , mePriority( rTask.mePriority )
638 , mbActive( false )
639 , mbStatic( false )
640{
641 assert(mpDebugName);
642 if ( rTask.IsActive() )
643 Start();
644}
645
646Task::~Task() COVERITY_NOEXCEPT_FALSE
647{
648 if ( !IsStatic() )
649 {
650 SchedulerGuard aSchedulerGuard;
651 if ( mpSchedulerData )
652 mpSchedulerData->mpTask = nullptr;
653 }
654 else
655 assert(nullptr == mpSchedulerData || utl::ConfigManager::IsFuzzing());
656}
657
658/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
std::ostream & operator<<(std::ostream &rStrm, const glm::mat4 &rMatrix)
static bool AnyInput(VclInputFlags nType=VCL_INPUT_ANY)
Determine if there are any pending input events.
Definition: svapp.cxx:623
An idle is a timer to be scheduled immediately.
Definition: idle.hxx:35
virtual SalTimer * CreateSalTimer()=0
void SetCallback(SALTIMERPROC pProc)
Definition: saltimer.hxx:46
virtual void Start(sal_uInt64 nMS)=0
virtual void Stop()=0
static void SetDeterministicMode(bool bDeterministic)
Control the deterministic mode.
Definition: scheduler.cxx:265
static void Lock()
Definition: scheduler.cxx:210
static bool GetDeterministicMode()
Return the current state of deterministic mode.
Definition: scheduler.cxx:270
static void ImplDeInitScheduler()
Definition: scheduler.cxx:101
static void CallbackTaskScheduling()
System timer callback function, which processes one LO task.
Definition: scheduler.cxx:330
static constexpr sal_uInt64 InfiniteTimeoutMs
Definition: scheduler.hxx:44
static constexpr sal_uInt64 ImmediateTimeoutMs
Definition: scheduler.hxx:43
static void Wakeup()
Wakes up the scheduler.
Definition: scheduler.cxx:530
static void UpdateSystemTimer(ImplSchedulerContext &rSchedCtx, sal_uInt64 nMinPeriod, bool bForce, sal_uInt64 nTime)
Definition: scheduler.cxx:275
static void ProcessEventsToIdle()
Process all events until none is pending.
Definition: svapp.cxx:502
static void Unlock()
Definition: scheduler.cxx:217
static void ImplStartTimer(sal_uInt64 nMS, bool bForce, sal_uInt64 nTime)
Start a new timer if we need to for nMS duration.
Definition: scheduler.cxx:231
static constexpr unsigned int nDefaultTimeSlice
static unsigned int m_nTimeSlice
Definition: task.hxx:43
bool IsActive() const
Definition: task.hxx:101
virtual sal_uInt64 UpdateMinPeriod(sal_uInt64 nTimeNow) const =0
How long (in MS) until the Task is ready to be dispatched?
bool mbActive
Currently in the scheduler.
Definition: task.hxx:50
bool IsStatic() const
Definition: task.hxx:110
void SetPriority(TaskPriority ePriority)
Definition: scheduler.cxx:597
void Stop()
Definition: scheduler.cxx:590
virtual ~Task() COVERITY_NOEXCEPT_FALSE
Definition: scheduler.cxx:646
const char * GetDebugName() const
Definition: task.hxx:82
const char * mpDebugName
Useful for debugging.
Definition: task.hxx:48
ImplSchedulerData * mpSchedulerData
Pointer to the element in scheduler list.
Definition: task.hxx:47
TaskPriority mePriority
Task priority.
Definition: task.hxx:49
Task & operator=(const Task &rTask)
Definition: scheduler.cxx:607
TaskPriority GetPriority() const
Definition: task.hxx:80
virtual void Start(bool bStartTimer=true)
Schedules the task for execution.
Definition: scheduler.cxx:545
friend struct ImplSchedulerData
Definition: task.hxx:45
void SetStatic()
This function must be called for static tasks, so the Task destructor ignores the scheduler mutex,...
Definition: task.hxx:109
Task(const char *pDebugName)
Definition: scheduler.cxx:624
virtual void Invoke()=0
virtual void SetDeletionFlags()
Definition: scheduler.cxx:540
static void StartTimer(sal_uInt64 nMS)
Definition: scheduler.cxx:535
Definition: timer.hxx:27
sal_uInt64 GetTimeout() const
Definition: timer.hxx:60
static sal_uInt64 GetSystemTicks()
static bool IsFuzzing()
#define DBG_TESTSOLARMUTEX()
#define TOOLS_WARN_EXCEPTION(area, stream)
Reference< XOutputStream > stream
const char * name
#define SAL_INFO_IF(condition, area, stream)
#define SAL_WARN_IF(condition, area, stream)
#define SAL_WARN(area, stream)
#define SAL_INFO(area, stream)
if(aStr !=aBuf) UpdateName_Impl(m_xFollowLb.get()
static void AppendSchedulerData(ImplSchedulerContext &rSchedCtx, ImplSchedulerData *const pSchedulerData)
Definition: scheduler.cxx:290
static bool g_bDeterministicMode
Definition: scheduler.cxx:263
static ImplSchedulerData * DropSchedulerData(ImplSchedulerContext &rSchedCtx, ImplSchedulerData *const pPrevSchedulerData, const ImplSchedulerData *const pSchedulerData, const int nTaskPriority)
Definition: scheduler.cxx:310
bool mbActive
ImplSchedulerContext maSchedCtx
Definition: svdata.hxx:399
SalInstance * mpDefInst
Definition: svdata.hxx:392
ImplSchedulerData * mpLastSchedulerData[PRIO_COUNT]
last item of each mpFirstSchedulerData list
Definition: svdata.hxx:376
bool mbActive
is the scheduler active?
Definition: svdata.hxx:384
ImplSchedulerData * mpFirstSchedulerData[PRIO_COUNT]
list of all active tasks per priority
Definition: svdata.hxx:375
ImplSchedulerData * mpSchedulerStack
stack of invoked tasks
Definition: svdata.hxx:377
SalTimer * mpSalTimer
interface to sal event loop / system timer
Definition: svdata.hxx:379
sal_uInt64 mnTimerStart
start time of the timer
Definition: svdata.hxx:380
std::mutex maMutex
the "scheduler mutex" (see vcl/README.scheduler)
Definition: svdata.hxx:382
sal_uInt64 mnTimerPeriod
current timer period
Definition: svdata.hxx:381
ImplSchedulerData * mpSchedulerStackTop
top most stack entry to detect needed rescheduling during pop
Definition: svdata.hxx:378
sal_uInt64 mnUpdateTime
Last Update Time.
ImplSchedulerData * mpNext
Pointer to the next element in list.
bool mbInScheduler
Is the Task currently processed / on the stack?
Task * mpTask
Pointer to VCL Task instance.
TaskPriority mePriority
Task priority.
ImplSVData * ImplGetSVData()
Definition: svdata.cxx:76
#define PRIO_COUNT
Definition: task.hxx:40
TaskPriority
Definition: task.hxx:28
@ HIGH_IDLE
Important idle events to be run before processing drawing events.
#define SAL_MAX_UINT64