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>
33 #include <tools/diagnose_ex.h>
34 #include <unotools/configmgr.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 
43 namespace {
44 
45 template< typename charT, typename traits >
46 std::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 
64 template< typename charT, typename traits >
65 std::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 
82 template< typename charT, typename traits >
83 std::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 
89 template< typename charT, typename traits >
90 std::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 
145 next_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  }
207  rSchedCtx.mnTimerPeriod = InfiniteTimeoutMs;
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 
231 void 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;
241  rSchedCtx.mnTimerPeriod = InfiniteTimeoutMs;
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 
264 {
265  // this function is for the saltimer callback
267 }
268 
269 static bool g_bDeterministicMode = false;
270 
271 void Scheduler::SetDeterministicMode(bool bDeterministic)
272 {
273  g_bDeterministicMode = bDeterministic;
274 }
275 
277 {
278  return g_bDeterministicMode;
279 }
280 
282  const sal_uInt64 nMinPeriod,
283  const bool bForce, const sal_uInt64 nTime )
284 {
285  if ( InfiniteTimeoutMs == nMinPeriod )
286  {
287  SAL_INFO("vcl.schedule", " Stopping system timer");
288  if ( rSchedCtx.mpSalTimer )
289  rSchedCtx.mpSalTimer->Stop();
290  rSchedCtx.mnTimerPeriod = nMinPeriod;
291  }
292  else
293  Scheduler::ImplStartTimer( nMinPeriod, bForce, nTime );
294 }
295 
297  ImplSchedulerData * const pSchedulerData)
298 {
299  assert(pSchedulerData->mpTask);
300  pSchedulerData->mePriority = pSchedulerData->mpTask->GetPriority();
301  pSchedulerData->mpNext = nullptr;
302 
303  const int nTaskPriority = static_cast<int>(pSchedulerData->mePriority);
304  if (!rSchedCtx.mpLastSchedulerData[nTaskPriority])
305  {
306  rSchedCtx.mpFirstSchedulerData[nTaskPriority] = pSchedulerData;
307  rSchedCtx.mpLastSchedulerData[nTaskPriority] = pSchedulerData;
308  }
309  else
310  {
311  rSchedCtx.mpLastSchedulerData[nTaskPriority]->mpNext = pSchedulerData;
312  rSchedCtx.mpLastSchedulerData[nTaskPriority] = pSchedulerData;
313  }
314 }
315 
317  ImplSchedulerContext &rSchedCtx, ImplSchedulerData * const pPrevSchedulerData,
318  const ImplSchedulerData * const pSchedulerData, const int nTaskPriority)
319 {
320  assert( pSchedulerData );
321  if ( pPrevSchedulerData )
322  assert( pPrevSchedulerData->mpNext == pSchedulerData );
323  else
324  assert(rSchedCtx.mpFirstSchedulerData[nTaskPriority] == pSchedulerData);
325 
326  ImplSchedulerData * const pSchedulerDataNext = pSchedulerData->mpNext;
327  if ( pPrevSchedulerData )
328  pPrevSchedulerData->mpNext = pSchedulerDataNext;
329  else
330  rSchedCtx.mpFirstSchedulerData[nTaskPriority] = pSchedulerDataNext;
331  if ( !pSchedulerDataNext )
332  rSchedCtx.mpLastSchedulerData[nTaskPriority] = pPrevSchedulerData;
333  return pSchedulerDataNext;
334 }
335 
337 {
338  ImplSVData *pSVData = ImplGetSVData();
339  ImplSchedulerContext &rSchedCtx = pSVData->maSchedCtx;
340 
342 
343  SchedulerGuard aSchedulerGuard;
344  if ( !rSchedCtx.mbActive || InfiniteTimeoutMs == rSchedCtx.mnTimerPeriod )
345  return false;
346 
347  sal_uInt64 nTime = tools::Time::GetSystemTicks();
348  // Allow for decimals, so subtract in the compare (needed at least on iOS)
349  if ( nTime < rSchedCtx.mnTimerStart + rSchedCtx.mnTimerPeriod -1)
350  {
351  int nSleep = rSchedCtx.mnTimerStart + rSchedCtx.mnTimerPeriod - nTime;
352  UpdateSystemTimer(rSchedCtx, nSleep, true, nTime);
353  return false;
354  }
355 
356  ImplSchedulerData* pSchedulerData = nullptr;
357  ImplSchedulerData* pPrevSchedulerData = nullptr;
358  ImplSchedulerData *pMostUrgent = nullptr;
359  ImplSchedulerData *pPrevMostUrgent = nullptr;
360  int nMostUrgentPriority = 0;
361  sal_uInt64 nMinPeriod = InfiniteTimeoutMs;
362  sal_uInt64 nReadyPeriod = InfiniteTimeoutMs;
363  unsigned nTasks = 0;
364  int nTaskPriority = 0;
365 
366  for (; nTaskPriority < PRIO_COUNT; ++nTaskPriority)
367  {
368  pSchedulerData = rSchedCtx.mpFirstSchedulerData[nTaskPriority];
369  pPrevSchedulerData = nullptr;
370  while (pSchedulerData)
371  {
372  ++nTasks;
373  const Timer *timer = dynamic_cast<Timer*>( pSchedulerData->mpTask );
374  if ( timer )
375  SAL_INFO( "vcl.schedule", tools::Time::GetSystemTicks() << " "
376  << pSchedulerData << " " << *pSchedulerData << " " << *timer );
377  else if ( pSchedulerData->mpTask )
378  SAL_INFO( "vcl.schedule", tools::Time::GetSystemTicks() << " "
379  << pSchedulerData << " " << *pSchedulerData
380  << " " << *pSchedulerData->mpTask );
381  else
382  SAL_INFO( "vcl.schedule", tools::Time::GetSystemTicks() << " "
383  << pSchedulerData << " " << *pSchedulerData << " (to be deleted)" );
384 
385  // Should the Task be released from scheduling?
386  assert(!pSchedulerData->mbInScheduler);
387  if (!pSchedulerData->mpTask || !pSchedulerData->mpTask->IsActive())
388  {
389  ImplSchedulerData * const pSchedulerDataNext =
390  DropSchedulerData(rSchedCtx, pPrevSchedulerData, pSchedulerData, nTaskPriority);
391  if ( pSchedulerData->mpTask )
392  pSchedulerData->mpTask->mpSchedulerData = nullptr;
393  delete pSchedulerData;
394  pSchedulerData = pSchedulerDataNext;
395  continue;
396  }
397 
398  assert(pSchedulerData->mpTask);
399  if (pSchedulerData->mpTask->IsActive())
400  {
401  nReadyPeriod = pSchedulerData->mpTask->UpdateMinPeriod( nTime );
402  if (ImmediateTimeoutMs == nReadyPeriod)
403  {
404  if (!pMostUrgent)
405  {
406  pPrevMostUrgent = pPrevSchedulerData;
407  pMostUrgent = pSchedulerData;
408  nMostUrgentPriority = nTaskPriority;
409  }
410  else
411  {
412  nMinPeriod = ImmediateTimeoutMs;
413  break;
414  }
415  }
416  else if (nMinPeriod > nReadyPeriod)
417  nMinPeriod = nReadyPeriod;
418  }
419 
420  pPrevSchedulerData = pSchedulerData;
421  pSchedulerData = pSchedulerData->mpNext;
422  }
423 
424  if (ImmediateTimeoutMs == nMinPeriod)
425  break;
426  }
427 
428  if ( InfiniteTimeoutMs != nMinPeriod )
429  SAL_INFO("vcl.schedule", "Calculated minimum timeout as " << nMinPeriod
430  << " of " << nTasks << " tasks" );
431  UpdateSystemTimer( rSchedCtx, nMinPeriod, true, nTime );
432 
433  if ( pMostUrgent )
434  {
435  SAL_INFO( "vcl.schedule", tools::Time::GetSystemTicks() << " "
436  << pMostUrgent << " invoke-in " << *pMostUrgent->mpTask );
437 
438  Task *pTask = pMostUrgent->mpTask;
439 
440  comphelper::ProfileZone aZone( pTask->GetDebugName() );
441 
442  // prepare Scheduler object for deletion after handling
443  pTask->SetDeletionFlags();
444 
445  assert(!pMostUrgent->mbInScheduler);
446  pMostUrgent->mbInScheduler = true;
447 
448  // always push the stack, as we don't traverse the whole list to push later
449  DropSchedulerData(rSchedCtx, pPrevMostUrgent, pMostUrgent, nMostUrgentPriority);
450  pMostUrgent->mpNext = rSchedCtx.mpSchedulerStack;
451  rSchedCtx.mpSchedulerStack = pMostUrgent;
452  rSchedCtx.mpSchedulerStackTop = pMostUrgent;
453 
454  // invoke the task
455  Unlock();
456  /*
457  * Current policy is that scheduler tasks aren't allowed to throw an exception.
458  * Because otherwise the exception is caught somewhere totally unrelated.
459  * TODO Ideally we could capture a proper backtrace and feed this into breakpad,
460  * which is do-able, but requires writing some assembly.
461  * See also SalUserEventList::DispatchUserEvents
462  */
463  try
464  {
465  pTask->Invoke();
466  }
467  catch (css::uno::Exception&)
468  {
469  TOOLS_WARN_EXCEPTION("vcl.schedule", "Uncaught");
470  std::abort();
471  }
472  catch (std::exception& e)
473  {
474  SAL_WARN("vcl.schedule", "Uncaught " << typeid(e).name() << " " << e.what());
475  std::abort();
476  }
477  catch (...)
478  {
479  SAL_WARN("vcl.schedule", "Uncaught exception during Task::Invoke()!");
480  std::abort();
481  }
482  Lock();
483 
484  assert(pMostUrgent->mbInScheduler);
485  pMostUrgent->mbInScheduler = false;
486 
487  SAL_INFO( "vcl.schedule", tools::Time::GetSystemTicks() << " "
488  << pMostUrgent << " invoke-out" );
489 
490  // pop the scheduler stack
491  pSchedulerData = rSchedCtx.mpSchedulerStack;
492  assert(pSchedulerData == pMostUrgent);
493  rSchedCtx.mpSchedulerStack = pSchedulerData->mpNext;
494 
495  const bool bTaskAlive = pMostUrgent->mpTask && pMostUrgent->mpTask->IsActive();
496  if (!bTaskAlive)
497  {
498  if (pMostUrgent->mpTask)
499  pMostUrgent->mpTask->mpSchedulerData = nullptr;
500  delete pMostUrgent;
501  }
502  else
503  AppendSchedulerData(rSchedCtx, pMostUrgent);
504 
505  // this just happens for nested calls, which renders all accounting
506  // invalid, so we just enforce a rescheduling!
507  if (rSchedCtx.mpSchedulerStackTop != pSchedulerData)
508  {
509  UpdateSystemTimer( rSchedCtx, ImmediateTimeoutMs, true,
511  }
512  else if (bTaskAlive)
513  {
514  pMostUrgent->mnUpdateTime = nTime;
515  nReadyPeriod = pMostUrgent->mpTask->UpdateMinPeriod( nTime );
516  if ( nMinPeriod > nReadyPeriod )
517  nMinPeriod = nReadyPeriod;
518  UpdateSystemTimer( rSchedCtx, nMinPeriod, false, nTime );
519  }
520  }
521 
522  return !!pMostUrgent;
523 }
524 
526 {
528 }
529 
530 void Task::StartTimer( sal_uInt64 nMS )
531 {
533 }
534 
536 {
537  mbActive = false;
538 }
539 
541 {
542  ImplSVData *const pSVData = ImplGetSVData();
543  ImplSchedulerContext &rSchedCtx = pSVData->maSchedCtx;
544 
545  SchedulerGuard aSchedulerGuard;
546  if ( !rSchedCtx.mbActive )
547  return;
548 
549  // is the task scheduled in the correct priority queue?
550  // if not we have to get a new data object, as we don't want to traverse
551  // the whole list to move the data to the correct list, as the task list
552  // is just single linked.
553  // Task priority doesn't change that often AFAIK, or we might need to
554  // start caching ImplSchedulerData objects.
556  {
557  mpSchedulerData->mpTask = nullptr;
558  mpSchedulerData = nullptr;
559  }
560  mbActive = true;
561 
562  if ( !mpSchedulerData )
563  {
564  // insert Task
565  ImplSchedulerData* pSchedulerData = new ImplSchedulerData;
566  pSchedulerData->mpTask = this;
567  pSchedulerData->mbInScheduler = false;
568  // mePriority is set in AppendSchedulerData
569  mpSchedulerData = pSchedulerData;
570 
571  AppendSchedulerData( rSchedCtx, pSchedulerData );
572  SAL_INFO( "vcl.schedule", tools::Time::GetSystemTicks()
573  << " " << mpSchedulerData << " added " << *this );
574  }
575  else
576  SAL_INFO( "vcl.schedule", tools::Time::GetSystemTicks()
577  << " " << mpSchedulerData << " restarted " << *this );
578 
580 }
581 
583 {
585  << " " << mpSchedulerData << " stopped " << *this );
586  mbActive = false;
587 }
588 
590 {
591  // you don't actually need to call Stop() before but Start() after, but we
592  // can't check that and don't know when Start() should be called.
593  SAL_WARN_IF(mpSchedulerData && mbActive, "vcl.schedule",
594  "Stop the task before changing the priority, as it will just "
595  "change after the task was scheduled with the old prio!");
596  mePriority = ePriority;
597 }
598 
599 Task& Task::operator=( const Task& rTask )
600 {
601  if(this == &rTask)
602  return *this;
603 
604  if ( IsActive() )
605  Stop();
606 
607  mbActive = false;
608  mePriority = rTask.mePriority;
609 
610  if ( rTask.IsActive() )
611  Start();
612 
613  return *this;
614 }
615 
616 Task::Task( const char *pDebugName )
617  : mpSchedulerData( nullptr )
618  , mpDebugName( pDebugName )
619  , mePriority( TaskPriority::DEFAULT )
620  , mbActive( false )
621  , mbStatic( false )
622 {
623 }
624 
625 Task::Task( const Task& rTask )
626  : mpSchedulerData( nullptr )
627  , mpDebugName( rTask.mpDebugName )
628  , mePriority( rTask.mePriority )
629  , mbActive( false )
630  , mbStatic( false )
631 {
632  if ( rTask.IsActive() )
633  Start();
634 }
635 
636 Task::~Task() COVERITY_NOEXCEPT_FALSE
637 {
638  if ( !IsStatic() )
639  {
640  SchedulerGuard aSchedulerGuard;
641  if ( mpSchedulerData )
642  mpSchedulerData->mpTask = nullptr;
643  }
644  else
646 }
647 
648 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
static void Unlock()
Definition: scheduler.cxx:217
static void AppendSchedulerData(ImplSchedulerContext &rSchedCtx, ImplSchedulerData *const pSchedulerData)
Definition: scheduler.cxx:296
static void Wakeup()
Wakes up the scheduler.
Definition: scheduler.cxx:525
static void Lock()
Definition: scheduler.cxx:210
#define SAL_INFO_IF(condition, area, stream)
#define PRIO_COUNT
Definition: task.hxx:39
TaskPriority mePriority
Task priority.
void SetCallback(SALTIMERPROC pProc)
Definition: saltimer.hxx:46
SalTimer * mpSalTimer
interface to sal event loop / system timer
Definition: svdata.hxx:370
static bool ProcessTaskScheduling()
Process one pending task ahead of time with highest priority.
Definition: scheduler.cxx:336
ImplSchedulerData * mpFirstSchedulerData[PRIO_COUNT]
list of all active tasks per priority
Definition: svdata.hxx:366
sal_uInt64 mnUpdateTime
Last Update Time.
bool IsActive() const
Definition: task.hxx:90
virtual void Stop()=0
const BorderLinePrimitive2D *pCandidateB assert(pCandidateA)
ImplSchedulerData * mpSchedulerData
Pointer to the element in scheduler list.
Definition: task.hxx:46
static bool IsFuzzing()
virtual SalTimer * CreateSalTimer()=0
static unsigned int m_nTimeSlice
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
ImplSchedulerData * mpNext
Pointer to the next element in list.
bool mbActive
virtual void Start()
Definition: scheduler.cxx:540
virtual void Invoke()=0
ImplSVData * ImplGetSVData()
Definition: svdata.cxx:74
virtual void Start(sal_uInt64 nMS)=0
#define TOOLS_WARN_EXCEPTION(area, stream)
static void UpdateSystemTimer(ImplSchedulerContext &rSchedCtx, sal_uInt64 nMinPeriod, bool bForce, sal_uInt64 nTime)
Definition: scheduler.cxx:281
#define SAL_MAX_UINT64
sal_uInt64 GetTimeout() const
Definition: timer.hxx:60
Task(const char *pDebugName)
Definition: scheduler.cxx:616
TaskPriority mePriority
Task priority.
Definition: task.hxx:48
Task * mpTask
Pointer to VCL Task instance.
ImplSchedulerData * mpSchedulerStack
stack of invoked tasks
Definition: svdata.hxx:368
void SetStatic()
This function must be called for static tasks, so the Task destructor ignores the scheduler mutex...
Definition: task.hxx:98
ImplSchedulerData * mpLastSchedulerData[PRIO_COUNT]
last item of each mpFirstSchedulerData list
Definition: svdata.hxx:367
bool mbActive
Currently in the scheduler.
Definition: task.hxx:49
TaskPriority GetPriority() const
Definition: task.hxx:79
static constexpr sal_uInt64 ImmediateTimeoutMs
Definition: scheduler.hxx:43
Task & operator=(const Task &rTask)
Definition: scheduler.cxx:599
ImplSchedulerContext maSchedCtx
Definition: svdata.hxx:390
std::ostream & operator<<(std::ostream &s, ImplLayoutArgs const &rArgs)
Definition: sallayout.cxx:52
static constexpr unsigned int nDefaultTimeSlice
static bool g_bDeterministicMode
Definition: scheduler.cxx:269
static bool GetDeterministicMode()
Return the current state of deterministic mode.
Definition: scheduler.cxx:276
sal_uInt64 mnTimerStart
start time of the timer
Definition: svdata.hxx:371
static constexpr sal_uInt64 InfiniteTimeoutMs
Definition: scheduler.hxx:44
bool IsStatic() const
Definition: task.hxx:99
virtual void SetDeletionFlags()
Definition: scheduler.cxx:535
virtual ~Task() COVERITY_NOEXCEPT_FALSE
Definition: scheduler.cxx:636
void Stop()
Definition: scheduler.cxx:582
#define SAL_WARN_IF(condition, area, stream)
static void StartTimer(sal_uInt64 nMS)
Definition: scheduler.cxx:530
static void CallbackTaskScheduling()
Process one pending Timer with highest priority.
Definition: scheduler.cxx:263
#define SAL_INFO(area, stream)
bool mbActive
is the scheduler active?
Definition: svdata.hxx:375
static void SetDeterministicMode(bool bDeterministic)
Control the deterministic mode.
Definition: scheduler.cxx:271
TaskPriority
Definition: task.hxx:27
static void ProcessEventsToIdle()
Process all events until none is pending.
Definition: svapp.cxx:479
const char * name
static sal_uInt64 GetSystemTicks()
ImplSchedulerData * mpSchedulerStackTop
top most stack entry to detect needed rescheduling during pop
Definition: svdata.hxx:369
friend struct ImplSchedulerData
Definition: task.hxx:44
#define SAL_WARN(area, stream)
virtual sal_uInt64 UpdateMinPeriod(sal_uInt64 nTimeNow) const =0
How long (in MS) until the Task is ready to be dispatched?
Definition: timer.hxx:26
void SetPriority(TaskPriority ePriority)
Definition: scheduler.cxx:589
#define DBG_TESTSOLARMUTEX()
if(!pCandidateA->getEnd().equal(pCandidateB->getStart()))
sal_uInt64 mnTimerPeriod
current timer period
Definition: svdata.hxx:372
Definition: task.hxx:41
const char * GetDebugName() const
Definition: task.hxx:82
static void ImplDeInitScheduler()
Definition: scheduler.cxx:101
SalInstance * mpDefInst
Definition: svdata.hxx:383
An idle is a timer to be scheduled immediately.
Definition: idle.hxx:30
std::mutex maMutex
the "scheduler mutex" (see vcl/README.scheduler)
Definition: svdata.hxx:373
bool mbInScheduler
Is the Task currently processed / on the stack?
static ImplSchedulerData * DropSchedulerData(ImplSchedulerContext &rSchedCtx, ImplSchedulerData *const pPrevSchedulerData, const ImplSchedulerData *const pSchedulerData, const int nTaskPriority)
Definition: scheduler.cxx:316