comparison layer/RenderTimer.h @ 1074:6f98aa5291d4 spectrogram-minor-refactor

Pull out render timer
author Chris Cannam
date Wed, 29 Jun 2016 14:04:57 +0100
parents
children eaab8bab3522
comparison
equal deleted inserted replaced
1073:cb4c9fb37ddc 1074:6f98aa5291d4
1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
2
3 /*
4 Sonic Visualiser
5 An audio file viewer and annotation editor.
6 Centre for Digital Music, Queen Mary, University of London.
7
8 This program is free software; you can redistribute it and/or
9 modify it under the terms of the GNU General Public License as
10 published by the Free Software Foundation; either version 2 of the
11 License, or (at your option) any later version. See the file
12 COPYING included with this distribution for more information.
13 */
14
15 #ifndef RENDER_TIMER_H
16 #define RENDER_TIMER_H
17
18 #include <chrono>
19
20 class RenderTimer
21 {
22 public:
23 enum Type {
24 /// A normal rendering operation with normal responsiveness demands
25 FastRender,
26
27 /// An operation that the user might accept being slower
28 SlowRender,
29
30 /// An operation that should always complete, i.e. as if there
31 /// were no RenderTimer in use, but without having to change
32 /// client code structurally
33 NoTimeout
34 };
35
36 /**
37 * Create a new RenderTimer and start timing. Make one of these
38 * before rendering, and then call outOfTime() regularly during
39 * rendering. If outOfTime() returns true, abandon rendering! and
40 * schedule the rest for after some user responsiveness has
41 * happened.
42 */
43 RenderTimer(Type t) :
44 m_start(std::chrono::steady_clock::now()),
45 m_haveLimits(true),
46 m_minFraction(0.1),
47 m_softLimit(0.1),
48 m_hardLimit(0.2),
49 m_softLimitOverridden(false) {
50
51 if (t == NoTimeout) {
52 m_haveLimits = false;
53 } else if (t == SlowRender) {
54 m_softLimit = 0.2;
55 m_hardLimit = 0.4;
56 }
57 }
58
59
60 /**
61 * Return true if we have run out of time and should suspend
62 * rendering and handle user events instead. Call this regularly
63 * during rendering work: fractionComplete should be an estimate
64 * of how much of the work has been done as of this call, as a
65 * number between 0.0 (none of it) and 1.0 (all of it).
66 */
67 bool outOfTime(double fractionComplete) {
68
69 if (!m_haveLimits || fractionComplete < m_minFraction) {
70 return false;
71 }
72
73 auto t = std::chrono::steady_clock::now();
74 double elapsed = std::chrono::duration<double>(t - m_start).count();
75
76 if (elapsed > m_hardLimit) {
77 return true;
78 } else if (!m_softLimitOverridden && elapsed > m_softLimit) {
79 if (fractionComplete > 0.6) {
80 // If we're significantly more than half way by the
81 // time we reach the soft limit, ignore it (though
82 // always respect the hard limit, above). Otherwise
83 // respect the soft limit and report out of time now.
84 m_softLimitOverridden = true;
85 } else {
86 return true;
87 }
88 }
89
90 return false;
91 }
92
93 private:
94 std::chrono::time_point<std::chrono::steady_clock> m_start;
95 bool m_haveLimits;
96 double m_minFraction;
97 double m_softLimit;
98 double m_hardLimit;
99 bool m_softLimitOverridden;
100 };
101
102 #endif