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 .
20 #include <sal/config.h>
27 #include <com/sun/star/uno/Exception.hpp>
28 #include <sal/log.hxx>
29 #include <sal/types.h>
31 #include <tools/time.hxx>
32 #include <tools/debug.hxx>
33 #include <comphelper/diagnose_ex.hxx>
34 #include <comphelper/configuration.hxx>
35 #include <vcl/TaskStopwatch.hxx>
36 #include <vcl/scheduler.hxx>
37 #include <vcl/idle.hxx>
38 #include <saltimer.hxx>
39 #include <salinst.hxx>
40 #include <comphelper/profilezone.hxx>
41 #include <schedulerimpl.hxx>
45 template< typename charT
, typename traits
>
46 std::basic_ostream
<charT
, traits
> & operator <<(
47 std::basic_ostream
<charT
, traits
> & stream
, const Task
& task
)
49 stream
<< "a: " << task
.IsActive() << " p: " << static_cast<int>(task
.GetPriority());
50 const char *name
= task
.GetDebugName();
52 return stream
<< " (nullptr)";
54 return stream
<< " " << name
;
58 * clang won't compile this in the Timer.hxx header, even with a class Idle
59 * forward definition, due to the incomplete Idle type in the template.
60 * Currently the code is just used in the Scheduler, so we keep it local.
62 * @see http://clang.llvm.org/compatibility.html#undep_incomplete
64 template< typename charT
, typename traits
>
65 std::basic_ostream
<charT
, traits
> & operator <<(
66 std::basic_ostream
<charT
, traits
> & stream
, const Timer
& timer
)
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)";
75 stream
<< " " << name
;
77 stream
<< " " << timer
.GetTimeout() << "ms";
78 stream
<< " (" << &timer
<< ")";
82 template< typename charT
, typename traits
>
83 std::basic_ostream
<charT
, traits
> & operator <<(
84 std::basic_ostream
<charT
, traits
> & stream
, const Idle
& idle
)
86 return stream
<< static_cast<const Timer
*>( &idle
);
89 template< typename charT
, typename traits
>
90 std::basic_ostream
<charT
, traits
> & operator <<(
91 std::basic_ostream
<charT
, traits
> & stream
, const ImplSchedulerData
& data
)
93 stream
<< " i: " << data
.mbInScheduler
;
97 } // end anonymous namespace
99 unsigned int TaskStopwatch::m_nTimeSlice
= TaskStopwatch::nDefaultTimeSlice
;
101 void Scheduler::ImplDeInitScheduler()
103 ImplSVData
* pSVData
= ImplGetSVData();
104 assert( pSVData
!= nullptr );
105 ImplSchedulerContext
&rSchedCtx
= pSVData
->maSchedCtx
;
107 DBG_TESTSOLARMUTEX();
109 SchedulerGuard aSchedulerGuard
;
111 int nTaskPriority
= 0;
112 #if OSL_DEBUG_LEVEL > 0
113 sal_uInt32 nTasks
= 0;
114 for (nTaskPriority
= 0; nTaskPriority
< PRIO_COUNT
; ++nTaskPriority
)
116 ImplSchedulerData
* pSchedulerData
= rSchedCtx
.mpFirstSchedulerData
[nTaskPriority
];
117 while ( pSchedulerData
)
120 pSchedulerData
= pSchedulerData
->mpNext
;
123 SAL_INFO( "vcl.schedule.deinit",
124 "DeInit the scheduler - pending tasks: " << nTasks
);
126 // clean up all Idles
128 ProcessEventsToIdle();
131 rSchedCtx
.mbActive
= false;
133 assert( nullptr == rSchedCtx
.mpSchedulerStack
|| (!rSchedCtx
.mpSchedulerStack
->mpTask
&& !rSchedCtx
.mpSchedulerStack
->mpNext
) );
135 if (rSchedCtx
.mpSalTimer
) rSchedCtx
.mpSalTimer
->Stop();
136 delete rSchedCtx
.mpSalTimer
;
137 rSchedCtx
.mpSalTimer
= nullptr;
139 #if OSL_DEBUG_LEVEL > 0
140 sal_uInt32 nActiveTasks
= 0, nIgnoredTasks
= 0;
143 ImplSchedulerData
* pSchedulerData
= nullptr;
146 pSchedulerData
= rSchedCtx
.mpFirstSchedulerData
[nTaskPriority
];
147 while ( pSchedulerData
)
149 Task
*pTask
= pSchedulerData
->mpTask
;
152 if ( pTask
->mbActive
)
154 #if OSL_DEBUG_LEVEL > 0
155 const char *sIgnored
= "";
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(), "sc ScModule IdleTimer" )
164 || !strcmp( pTask
->GetDebugName(), "sd::CacheConfiguration maReleaseTimer" )
165 || !strcmp( pTask
->GetDebugName(), "svtools::GraphicCache maReleaseTimer" )
166 || !strcmp( pTask
->GetDebugName(), "svtools::GraphicObject mpSwapOutTimer" )
167 || !strcmp( pTask
->GetDebugName(), "svx OLEObjCache pTimer UnloadCheck" )
168 || !strcmp( pTask
->GetDebugName(), "vcl SystemDependentDataBuffer aSystemDependentDataBuffer" )
171 sIgnored
= " (ignored)";
174 const Timer
*timer
= dynamic_cast<Timer
*>( pTask
);
176 SAL_WARN( "vcl.schedule.deinit", "DeInit task: " << *timer
<< sIgnored
);
178 SAL_WARN( "vcl.schedule.deinit", "DeInit task: " << *pTask
<< sIgnored
);
180 pTask
->mbActive
= false;
182 pTask
->mpSchedulerData
= nullptr;
185 ImplSchedulerData
* pDeleteSchedulerData
= pSchedulerData
;
186 pSchedulerData
= pSchedulerData
->mpNext
;
187 delete pDeleteSchedulerData
;
191 if (nTaskPriority
< PRIO_COUNT
)
194 #if OSL_DEBUG_LEVEL > 0
195 SAL_INFO( "vcl.schedule.deinit", "DeInit the scheduler - finished" );
196 SAL_WARN_IF( 0 != nActiveTasks
, "vcl.schedule.deinit", "DeInit active tasks: "
197 << nActiveTasks
<< " (ignored: " << nIgnoredTasks
<< ")" );
198 // assert( nIgnoredTasks == nActiveTasks );
201 for (nTaskPriority
= 0; nTaskPriority
< PRIO_COUNT
; ++nTaskPriority
)
203 rSchedCtx
.mpFirstSchedulerData
[nTaskPriority
] = nullptr;
204 rSchedCtx
.mpLastSchedulerData
[nTaskPriority
] = nullptr;
206 rSchedCtx
.mnTimerPeriod
= InfiniteTimeoutMs
;
209 void Scheduler::Lock()
211 ImplSVData
* pSVData
= ImplGetSVData();
212 assert( pSVData
!= nullptr );
213 pSVData
->maSchedCtx
.maMutex
.lock();
216 void Scheduler::Unlock()
218 ImplSVData
* pSVData
= ImplGetSVData();
219 assert( pSVData
!= nullptr );
220 pSVData
->maSchedCtx
.maMutex
.unlock();
224 * Start a new timer if we need to for nMS duration.
226 * if this is longer than the existing duration we're
227 * waiting for, do nothing - unless bForce - which means
228 * to reset the minimum period; used by the scheduled itself.
230 void Scheduler::ImplStartTimer(sal_uInt64 nMS
, bool bForce
, sal_uInt64 nTime
)
232 ImplSVData
* pSVData
= ImplGetSVData();
233 ImplSchedulerContext
&rSchedCtx
= pSVData
->maSchedCtx
;
234 if ( !rSchedCtx
.mbActive
)
237 if (!rSchedCtx
.mpSalTimer
)
239 rSchedCtx
.mnTimerStart
= 0;
240 rSchedCtx
.mnTimerPeriod
= InfiniteTimeoutMs
;
241 rSchedCtx
.mpSalTimer
= pSVData
->mpDefInst
->CreateSalTimer();
242 rSchedCtx
.mpSalTimer
->SetCallback(Scheduler::CallbackTaskScheduling
);
245 assert(SAL_MAX_UINT64
- nMS
>= nTime
);
247 sal_uInt64 nProposedTimeout
= nTime
+ nMS
;
248 sal_uInt64 nCurTimeout
= ( rSchedCtx
.mnTimerPeriod
== InfiniteTimeoutMs
)
249 ? SAL_MAX_UINT64
: rSchedCtx
.mnTimerStart
+ rSchedCtx
.mnTimerPeriod
;
251 // Only if smaller timeout, to avoid skipping.
252 // Force instant wakeup on 0ms, if the previous period was not 0ms
253 if (bForce
|| nProposedTimeout
< nCurTimeout
|| (!nMS
&& rSchedCtx
.mnTimerPeriod
))
255 SAL_INFO( "vcl.schedule", " Starting scheduler system timer (" << nMS
<< "ms)" );
256 rSchedCtx
.mnTimerStart
= nTime
;
257 rSchedCtx
.mnTimerPeriod
= nMS
;
258 rSchedCtx
.mpSalTimer
->Start( nMS
);
262 static bool g_bDeterministicMode
= false;
264 void Scheduler::SetDeterministicMode(bool bDeterministic
)
266 g_bDeterministicMode
= bDeterministic
;
269 bool Scheduler::GetDeterministicMode()
271 return g_bDeterministicMode
;
274 Scheduler::IdlesLockGuard::IdlesLockGuard()
276 ImplSVData
* pSVData
= ImplGetSVData();
277 ImplSchedulerContext
& rSchedCtx
= pSVData
->maSchedCtx
;
278 osl_atomic_increment(&rSchedCtx
.mnIdlesLockCount
);
279 if (!Application::IsMainThread())
281 // Make sure that main thread has reached the main message loop, so no idles are executing.
282 // It is important to ensure this, because e.g. ProcessEventsToIdle could be executed in a
283 // nested event loop, while an active processed idle in the main thread is waiting for some
284 // condition to proceed. Only main thread returning to Application::Execute guarantees that
285 // the flag really took effect.
286 pSVData
->m_inExecuteCondtion
.reset();
287 // Put an empty event to the application's queue, to make sure that it loops through the
288 // code that sets the condition, even when there's no other events in the queue
289 Application::PostUserEvent({});
290 SolarMutexReleaser releaser
;
291 pSVData
->m_inExecuteCondtion
.wait();
295 Scheduler::IdlesLockGuard::~IdlesLockGuard()
297 ImplSchedulerContext
& rSchedCtx
= ImplGetSVData()->maSchedCtx
;
298 osl_atomic_decrement(&rSchedCtx
.mnIdlesLockCount
);
301 inline void Scheduler::UpdateSystemTimer( ImplSchedulerContext
&rSchedCtx
,
302 const sal_uInt64 nMinPeriod
,
303 const bool bForce
, const sal_uInt64 nTime
)
305 if ( InfiniteTimeoutMs
== nMinPeriod
)
307 SAL_INFO("vcl.schedule", " Stopping system timer");
308 if ( rSchedCtx
.mpSalTimer
)
309 rSchedCtx
.mpSalTimer
->Stop();
310 rSchedCtx
.mnTimerPeriod
= nMinPeriod
;
313 Scheduler::ImplStartTimer( nMinPeriod
, bForce
, nTime
);
316 static void AppendSchedulerData( ImplSchedulerContext
&rSchedCtx
,
317 ImplSchedulerData
* const pSchedulerData
)
319 assert(pSchedulerData
->mpTask
);
320 pSchedulerData
->mePriority
= pSchedulerData
->mpTask
->GetPriority();
321 pSchedulerData
->mpNext
= nullptr;
323 const int nTaskPriority
= static_cast<int>(pSchedulerData
->mePriority
);
324 if (!rSchedCtx
.mpLastSchedulerData
[nTaskPriority
])
326 rSchedCtx
.mpFirstSchedulerData
[nTaskPriority
] = pSchedulerData
;
327 rSchedCtx
.mpLastSchedulerData
[nTaskPriority
] = pSchedulerData
;
331 rSchedCtx
.mpLastSchedulerData
[nTaskPriority
]->mpNext
= pSchedulerData
;
332 rSchedCtx
.mpLastSchedulerData
[nTaskPriority
] = pSchedulerData
;
336 static ImplSchedulerData
* DropSchedulerData(
337 ImplSchedulerContext
&rSchedCtx
, ImplSchedulerData
* const pPrevSchedulerData
,
338 const ImplSchedulerData
* const pSchedulerData
, const int nTaskPriority
)
340 assert( pSchedulerData
);
341 if ( pPrevSchedulerData
)
342 assert( pPrevSchedulerData
->mpNext
== pSchedulerData
);
344 assert(rSchedCtx
.mpFirstSchedulerData
[nTaskPriority
] == pSchedulerData
);
346 ImplSchedulerData
* const pSchedulerDataNext
= pSchedulerData
->mpNext
;
347 if ( pPrevSchedulerData
)
348 pPrevSchedulerData
->mpNext
= pSchedulerDataNext
;
350 rSchedCtx
.mpFirstSchedulerData
[nTaskPriority
] = pSchedulerDataNext
;
351 if ( !pSchedulerDataNext
)
352 rSchedCtx
.mpLastSchedulerData
[nTaskPriority
] = pPrevSchedulerData
;
353 return pSchedulerDataNext
;
356 void Scheduler::CallbackTaskScheduling()
358 ImplSVData
*pSVData
= ImplGetSVData();
359 ImplSchedulerContext
&rSchedCtx
= pSVData
->maSchedCtx
;
361 DBG_TESTSOLARMUTEX();
363 SchedulerGuard aSchedulerGuard
;
364 if ( !rSchedCtx
.mbActive
|| InfiniteTimeoutMs
== rSchedCtx
.mnTimerPeriod
)
367 sal_uInt64 nTime
= tools::Time::GetSystemTicks();
368 // Allow for decimals, so subtract in the compare (needed at least on iOS)
369 if ( nTime
< rSchedCtx
.mnTimerStart
+ rSchedCtx
.mnTimerPeriod
-1)
371 int nSleep
= rSchedCtx
.mnTimerStart
+ rSchedCtx
.mnTimerPeriod
- nTime
;
372 UpdateSystemTimer(rSchedCtx
, nSleep
, true, nTime
);
376 ImplSchedulerData
* pSchedulerData
= nullptr;
377 ImplSchedulerData
* pPrevSchedulerData
= nullptr;
378 ImplSchedulerData
*pMostUrgent
= nullptr;
379 ImplSchedulerData
*pPrevMostUrgent
= nullptr;
380 int nMostUrgentPriority
= 0;
381 sal_uInt64 nMinPeriod
= InfiniteTimeoutMs
;
382 sal_uInt64 nReadyPeriod
= InfiniteTimeoutMs
;
384 int nTaskPriority
= 0;
386 for (; nTaskPriority
< PRIO_COUNT
; ++nTaskPriority
)
388 // Related: tdf#152703 Eliminate potential blocking during live resize
389 // Only higher priority tasks need to be fired to redraw the window
390 // so skip firing potentially long-running tasks, such as the Writer
391 // idle layout timer, when a window is in live resize
392 if ( nTaskPriority
== static_cast<int>(TaskPriority::LOWEST
) && ( ImplGetSVData()->mpWinData
->mbIsLiveResize
|| ImplGetSVData()->mpWinData
->mbIsWaitingForNativeEvent
) )
395 pSchedulerData
= rSchedCtx
.mpFirstSchedulerData
[nTaskPriority
];
396 pPrevSchedulerData
= nullptr;
397 while (pSchedulerData
)
400 const Timer
*timer
= dynamic_cast<Timer
*>( pSchedulerData
->mpTask
);
402 SAL_INFO( "vcl.schedule", tools::Time::GetSystemTicks() << " "
403 << pSchedulerData
<< " " << *pSchedulerData
<< " " << *timer
);
404 else if ( pSchedulerData
->mpTask
)
405 SAL_INFO( "vcl.schedule", tools::Time::GetSystemTicks() << " "
406 << pSchedulerData
<< " " << *pSchedulerData
407 << " " << *pSchedulerData
->mpTask
);
409 SAL_INFO( "vcl.schedule", tools::Time::GetSystemTicks() << " "
410 << pSchedulerData
<< " " << *pSchedulerData
<< " (to be deleted)" );
412 // Should the Task be released from scheduling?
413 assert(!pSchedulerData
->mbInScheduler
);
414 if (!pSchedulerData
->mpTask
|| !pSchedulerData
->mpTask
->IsActive())
416 ImplSchedulerData
* const pSchedulerDataNext
=
417 DropSchedulerData(rSchedCtx
, pPrevSchedulerData
, pSchedulerData
, nTaskPriority
);
418 if ( pSchedulerData
->mpTask
)
419 pSchedulerData
->mpTask
->mpSchedulerData
= nullptr;
420 delete pSchedulerData
;
421 pSchedulerData
= pSchedulerDataNext
;
425 assert(pSchedulerData
->mpTask
);
426 if (pSchedulerData
->mpTask
->IsActive())
428 nReadyPeriod
= pSchedulerData
->mpTask
->UpdateMinPeriod( nTime
);
429 if (ImmediateTimeoutMs
== nReadyPeriod
)
433 pPrevMostUrgent
= pPrevSchedulerData
;
434 pMostUrgent
= pSchedulerData
;
435 nMostUrgentPriority
= nTaskPriority
;
439 nMinPeriod
= ImmediateTimeoutMs
;
443 else if (nMinPeriod
> nReadyPeriod
)
444 nMinPeriod
= nReadyPeriod
;
447 pPrevSchedulerData
= pSchedulerData
;
448 pSchedulerData
= pSchedulerData
->mpNext
;
451 if (ImmediateTimeoutMs
== nMinPeriod
)
455 if (InfiniteTimeoutMs
!= nMinPeriod
)
456 SAL_INFO("vcl.schedule",
457 "Calculated minimum timeout as " << nMinPeriod
<< " of " << nTasks
<< " tasks");
458 UpdateSystemTimer(rSchedCtx
, nMinPeriod
, true, nTime
);
463 SAL_INFO( "vcl.schedule", tools::Time::GetSystemTicks() << " "
464 << pMostUrgent
<< " invoke-in " << *pMostUrgent
->mpTask
);
466 Task
*pTask
= pMostUrgent
->mpTask
;
468 comphelper::ProfileZone
aZone( pTask
->GetDebugName() );
470 assert(!pMostUrgent
->mbInScheduler
);
471 pMostUrgent
->mbInScheduler
= true;
473 // always push the stack, as we don't traverse the whole list to push later
474 DropSchedulerData(rSchedCtx
, pPrevMostUrgent
, pMostUrgent
, nMostUrgentPriority
);
475 pMostUrgent
->mpNext
= rSchedCtx
.mpSchedulerStack
;
476 rSchedCtx
.mpSchedulerStack
= pMostUrgent
;
477 rSchedCtx
.mpSchedulerStackTop
= pMostUrgent
;
479 bool bIsHighPriorityIdle
= pMostUrgent
->mePriority
>= TaskPriority::HIGH_IDLE
;
484 // Delay invoking tasks with idle priorities as long as there are user input or repaint events
485 // in the OS event queue. This will often effectively compress such events and repaint only
486 // once at the end, improving performance in cases such as repeated zooming with a complex document.
488 = bIsHighPriorityIdle
489 && (rSchedCtx
.mnIdlesLockCount
> 0
490 || Application::AnyInput(VclInputFlags::MOUSE
| VclInputFlags::KEYBOARD
| VclInputFlags::PAINT
));
493 * Current policy is that scheduler tasks aren't allowed to throw an exception.
494 * Because otherwise the exception is caught somewhere totally unrelated.
495 * TODO Ideally we could capture a proper backtrace and feed this into breakpad,
496 * which is do-able, but requires writing some assembly.
497 * See also SalUserEventList::DispatchUserEvents
502 SAL_INFO( "vcl.schedule", tools::Time::GetSystemTicks()
503 << " idle priority task " << pTask
->GetDebugName()
504 << " delayed, system events pending" );
507 // prepare Scheduler object for deletion after handling
508 pTask
->SetDeletionFlags();
512 catch (css::uno::Exception
&)
514 TOOLS_WARN_EXCEPTION("vcl.schedule", "Uncaught");
517 catch (std::exception
& e
)
519 SAL_WARN("vcl.schedule", "Uncaught " << typeid(e
).name() << " " << e
.what());
524 SAL_WARN("vcl.schedule", "Uncaught exception during Task::Invoke()!");
529 assert(pMostUrgent
->mbInScheduler
);
530 pMostUrgent
->mbInScheduler
= false;
532 SAL_INFO( "vcl.schedule", tools::Time::GetSystemTicks() << " "
533 << pMostUrgent
<< " invoke-out" );
535 // pop the scheduler stack
536 pSchedulerData
= rSchedCtx
.mpSchedulerStack
;
537 assert(pSchedulerData
== pMostUrgent
);
538 rSchedCtx
.mpSchedulerStack
= pSchedulerData
->mpNext
;
540 // coverity[check_after_deref : FALSE] - pMostUrgent->mpTask is initially pMostUrgent->mpTask, but Task::Invoke can clear it
541 const bool bTaskAlive
= pMostUrgent
->mpTask
&& pMostUrgent
->mpTask
->IsActive();
544 if (pMostUrgent
->mpTask
)
545 pMostUrgent
->mpTask
->mpSchedulerData
= nullptr;
549 AppendSchedulerData(rSchedCtx
, pMostUrgent
);
551 // this just happens for nested calls, which renders all accounting
552 // invalid, so we just enforce a rescheduling!
553 if (rSchedCtx
.mpSchedulerStackTop
!= pSchedulerData
)
555 UpdateSystemTimer( rSchedCtx
, ImmediateTimeoutMs
, true,
556 tools::Time::GetSystemTicks() );
560 pMostUrgent
->mnUpdateTime
= nTime
;
561 nReadyPeriod
= pMostUrgent
->mpTask
->UpdateMinPeriod( nTime
);
562 if ( nMinPeriod
> nReadyPeriod
)
563 nMinPeriod
= nReadyPeriod
;
564 UpdateSystemTimer( rSchedCtx
, nMinPeriod
, false, nTime
);
568 void Scheduler::Wakeup()
570 Scheduler::ImplStartTimer( 0, false, tools::Time::GetSystemTicks() );
573 void Task::StartTimer( sal_uInt64 nMS
)
575 Scheduler::ImplStartTimer( nMS
, false, tools::Time::GetSystemTicks() );
578 void Task::SetDeletionFlags()
583 void Task::Start(const bool bStartTimer
)
585 ImplSVData
*const pSVData
= ImplGetSVData();
586 ImplSchedulerContext
&rSchedCtx
= pSVData
->maSchedCtx
;
588 SchedulerGuard aSchedulerGuard
;
589 if ( !rSchedCtx
.mbActive
)
592 // is the task scheduled in the correct priority queue?
593 // if not we have to get a new data object, as we don't want to traverse
594 // the whole list to move the data to the correct list, as the task list
595 // is just single linked.
596 // Task priority doesn't change that often AFAIK, or we might need to
597 // start caching ImplSchedulerData objects.
598 if (mpSchedulerData
&& mpSchedulerData
->mePriority
!= mePriority
)
600 mpSchedulerData
->mpTask
= nullptr;
601 mpSchedulerData
= nullptr;
605 if ( !mpSchedulerData
)
608 ImplSchedulerData
* pSchedulerData
= new ImplSchedulerData
;
609 pSchedulerData
->mpTask
= this;
610 pSchedulerData
->mbInScheduler
= false;
611 // mePriority is set in AppendSchedulerData
612 mpSchedulerData
= pSchedulerData
;
614 AppendSchedulerData( rSchedCtx
, pSchedulerData
);
615 SAL_INFO( "vcl.schedule", tools::Time::GetSystemTicks()
616 << " " << mpSchedulerData
<< " added " << *this );
619 SAL_INFO( "vcl.schedule", tools::Time::GetSystemTicks()
620 << " " << mpSchedulerData
<< " restarted " << *this );
622 mpSchedulerData
->mnUpdateTime
= tools::Time::GetSystemTicks();
630 SAL_INFO_IF( mbActive
, "vcl.schedule", tools::Time::GetSystemTicks()
631 << " " << mpSchedulerData
<< " stopped " << *this );
635 void Task::SetPriority(TaskPriority ePriority
)
637 // you don't actually need to call Stop() before but Start() after, but we
638 // can't check that and don't know when Start() should be called.
639 SAL_WARN_IF(mpSchedulerData
&& mbActive
, "vcl.schedule",
640 "Stop the task before changing the priority, as it will just "
641 "change after the task was scheduled with the old prio!");
642 mePriority
= ePriority
;
645 Task
& Task::operator=( const Task
& rTask
)
654 mePriority
= rTask
.mePriority
;
656 if ( rTask
.IsActive() )
662 Task::Task( const char *pDebugName
)
663 : mpSchedulerData( nullptr )
664 , mpDebugName( pDebugName
)
665 , mePriority( TaskPriority::DEFAULT
)
672 Task::Task( const Task
& rTask
)
673 : mpSchedulerData( nullptr )
674 , mpDebugName( rTask
.mpDebugName
)
675 , mePriority( rTask
.mePriority
)
680 if ( rTask
.IsActive() )
684 Task::~Task() COVERITY_NOEXCEPT_FALSE
688 SchedulerGuard aSchedulerGuard
;
689 if ( mpSchedulerData
)
690 mpSchedulerData
->mpTask
= nullptr;
693 assert(nullptr == mpSchedulerData
|| comphelper::IsFuzzing());
696 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */