File: RenderTimer.h

package info (click to toggle)
sonic-visualiser 5.2.1-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 24,744 kB
  • sloc: cpp: 158,888; ansic: 11,920; sh: 1,785; makefile: 517; xml: 64; perl: 31
file content (118 lines) | stat: -rw-r--r-- 3,666 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */

/*
    Sonic Visualiser
    An audio file viewer and annotation editor.
    Centre for Digital Music, Queen Mary, University of London.
    
    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License as
    published by the Free Software Foundation; either version 2 of the
    License, or (at your option) any later version.  See the file
    COPYING included with this distribution for more information.
*/

#ifndef RENDER_TIMER_H
#define RENDER_TIMER_H

#include <chrono>

namespace sv {

class RenderTimer
{
public:
    enum Type {
        /// A normal rendering operation with normal responsiveness demands
        FastRender,

        /// An operation that the user might accept being slower
        SlowRender,

        /// An operation that should always complete, i.e. as if there
        /// were no RenderTimer in use, but without having to change
        /// client code structurally
        NoTimeout
    };
    
    /**
     * Create a new RenderTimer and start timing. Make one of these
     * before rendering, and then call outOfTime() regularly during
     * rendering. If outOfTime() returns true, abandon rendering!  and
     * schedule the rest for after some user responsiveness has
     * happened.
     */
    RenderTimer(Type t) :
        m_start(std::chrono::steady_clock::now()),
        m_haveLimits(true),
        m_minFraction(0.15),
        m_almostFraction(0.65),
        m_softLimit(0.1),
        m_hardLimit(0.2),
        m_softLimitOverridden(false) {

        if (t == NoTimeout) {
            m_haveLimits = false;
        } else if (t == SlowRender) {
            m_softLimit = 0.2;
            m_hardLimit = 0.4;
        }
    }


    /**
     * Return true if we have run out of time and should suspend
     * rendering and handle user events instead. Call this regularly
     * during rendering work: fractionComplete should be an estimate
     * of how much of the work has been done as of this call, as a
     * number between 0.0 (none of it) and 1.0 (all of it).
     */
    bool outOfTime(double fractionComplete) {

        if (!m_haveLimits || fractionComplete < m_minFraction) {
            return false;
        }
        
        auto t = std::chrono::steady_clock::now();
        double elapsed = std::chrono::duration<double>(t - m_start).count();
        
        if (elapsed > m_hardLimit) {
            return true;
        } else if (!m_softLimitOverridden && elapsed > m_softLimit) {
            if (fractionComplete > m_almostFraction) {
                // If we're "almost done" by the time we reach the
                // soft limit, ignore it (though always respect the
                // hard limit, above). Otherwise respect the soft
                // limit and report out of time now.
                m_softLimitOverridden = true;
            } else {
                return true;
            }
        }

        return false;
    }

    double secondsPerItem(int itemsRendered) const {

        if (itemsRendered == 0) return 0.0;

        auto t = std::chrono::steady_clock::now();
        double elapsed = std::chrono::duration<double>(t - m_start).count();

        return elapsed / itemsRendered;
    }

private:
    std::chrono::time_point<std::chrono::steady_clock> m_start;
    bool m_haveLimits;
    double m_minFraction; // proportion, 0.0 -> 1.0
    double m_almostFraction; // proportion, 0.0 -> 1.0
    double m_softLimit; // seconds
    double m_hardLimit; // seconds
    bool m_softLimitOverridden;
};

} // end namespace sv

#endif