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 10 #ifndef INCLUDED_VCL_TASK_STOPWATCH_HXX 11 #define INCLUDED_VCL_TASK_STOPWATCH_HXX 12 13 #include <tools/time.hxx> 14 #include <vcl/dllapi.h> 15 #include <vcl/inputtypes.hxx> 16 #include <vcl/svapp.hxx> 17 18 /** 19 * Helper class primary used to track time of long running iterating tasks. 20 * 21 * Normally it should be sufficient to instantiate the watch object before 22 * starting the iteration and query continueIter() at the end of each. 23 * 24 * Called Stopwatch, because there is already a Timer class in the Scheduler. 25 * 26 * TODO: merge into the general Scheduler, so this can also be used to track 27 * Task runtimes in a more general way. 28 * TODO: handle fast iterations, where continueIter is called multiple times 29 * per tick, by counting the iterations per tick and use that for approximation. 30 **/ 31 class VCL_DLLPUBLIC TaskStopwatch 32 { 33 static constexpr VclInputFlags eDefaultInputStop = VCL_INPUT_ANY & ~VclInputFlags::TIMER; 34 static constexpr unsigned int nDefaultTimeSlice = 50; 35 static unsigned int m_nTimeSlice; 36 37 sal_uInt64 m_nStartTicks; 38 sal_uInt64 m_nIterStartTicks; 39 bool m_bConsiderLastIterTime; 40 VclInputFlags m_eInputStop; 41 nextIter(bool bQueryOnly)42 bool nextIter(bool bQueryOnly) 43 { 44 sal_uInt64 nCurTicks = tools::Time::GetSystemTicks(); 45 // handle system ticks wrap as exceeded time slice 46 if (nCurTicks < m_nStartTicks) 47 return false; 48 49 if (!bQueryOnly && m_bConsiderLastIterTime) 50 { 51 // based on the last iter runtime, we don't expect to finish in time 52 // m_nTimeSlice < (nCurTicks - m_nStartTicks) + (nCurTicks - m_nIterStartTicks) 53 if (m_nTimeSlice < 2 * nCurTicks - m_nIterStartTicks - m_nStartTicks) 54 return false; 55 } 56 // time slice exceeded 57 else if (m_nTimeSlice < nCurTicks - m_nStartTicks) 58 return false; 59 60 if (!bQueryOnly) 61 m_nIterStartTicks = nCurTicks; 62 63 return !Application::AnyInput(m_eInputStop); 64 } 65 66 public: 67 /** 68 * Per default the watch considers the last iter time when asking for an 69 * other iteration, so considers Scheduler::acceptableTaskTime as a 70 * maximum value. 71 * 72 * If you already know your iter time vary in a large range, consider 73 * setting bConciderLastIterTime to false, so Scheduler::acceptableTaskTime 74 * will be used as a minimum time slot. 75 **/ TaskStopwatch(bool bConciderLastIterTime=true)76 TaskStopwatch(bool bConciderLastIterTime = true) 77 : m_nStartTicks(tools::Time::GetSystemTicks()) 78 , m_nIterStartTicks(m_nStartTicks) 79 , m_bConsiderLastIterTime(bConciderLastIterTime) 80 , m_eInputStop(eDefaultInputStop) 81 { 82 } 83 84 /** 85 * Returns true, if another iteration will probably pass in the time slot 86 **/ continueIter()87 bool continueIter() { return nextIter(false); } 88 89 /** 90 * Reset the stopwatch 91 **/ reset()92 void reset() 93 { 94 m_nStartTicks = tools::Time::GetSystemTicks(); 95 m_nIterStartTicks = m_nStartTicks; 96 } 97 98 /** 99 * Sets the input events, which should also "exceed" the stopwatch. 100 * 101 * Per default this ignores the VclInputFlags::TIMER. 102 */ setInputStop(VclInputFlags eInputStop=eDefaultInputStop)103 void setInputStop(VclInputFlags eInputStop = eDefaultInputStop) { m_eInputStop = eInputStop; } inputStop() const104 VclInputFlags inputStop() const { return m_eInputStop; } 105 106 /** 107 * Sets the time considered the acceptable maximum for a task to run 108 * 109 * This is an orientation for long time background jobs to yield to 110 * the scheduler, so Idle task don't starve each other too much. 111 **/ timeSlice()112 static unsigned int timeSlice() { return m_nTimeSlice; } setTimeSlice(unsigned int nTimeSlice)113 static void setTimeSlice(unsigned int nTimeSlice) { m_nTimeSlice = nTimeSlice; } 114 }; 115 116 #endif // INCLUDED_VCL_TASK_STOPWATCH_HXX 117 118 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ 119