mirror of
https://github.com/Ardour/ardour.git
synced 2025-12-07 15:25:01 +01:00
Add PBD::QPC::initialize to initialize timer and call it from PBD::init
Check timer for invalid frequency Precalculate timer tick rate to save a few instructions Don't use static variables inside functions to avoid checking for initialization Use static functions inside anonymous namespace for internal linkage
This commit is contained in:
parent
9bd893a6a2
commit
119e56e7eb
3 changed files with 41 additions and 40 deletions
|
|
@ -109,6 +109,7 @@ PBD::init ()
|
|||
return false;
|
||||
}
|
||||
|
||||
QPC::initialize();
|
||||
test_timers_from_env ();
|
||||
|
||||
if (!PBD::MMCSS::initialize()) {
|
||||
|
|
|
|||
|
|
@ -59,20 +59,29 @@ bool reset_resolution();
|
|||
|
||||
namespace QPC {
|
||||
|
||||
/**
|
||||
* Initialize the QPC timer, must be called before QPC::get_microseconds will
|
||||
* return a valid value.
|
||||
* @return true if QPC timer is usable, use check_timer_valid to try to check
|
||||
* if it is monotonic.
|
||||
*/
|
||||
bool initialize ();
|
||||
|
||||
/**
|
||||
* @return true if QueryPerformanceCounter is usable as a timer source
|
||||
* This should always return true for systems > XP as those versions of windows
|
||||
* have there own tests to check timer validity and will select an appropriate
|
||||
* timer source.
|
||||
* timer source. This check is not conclusive and there are probably conditions
|
||||
* under which this check will return true but the timer is not monotonic.
|
||||
*/
|
||||
bool check_timer_valid ();
|
||||
|
||||
/**
|
||||
* @return the value of the performance counter converted to microseconds
|
||||
*
|
||||
* If get_counter_valid returns true then get_microseconds will always
|
||||
* return a positive value. If QPC is not supported(OS < XP) then -1 is
|
||||
* returned but the MS docs say that this won't occur for systems >= XP.
|
||||
* If initialize returns true then get_microseconds will always return a
|
||||
* positive value. If QPC is not supported(OS < XP) then -1 is returned but the
|
||||
* MS docs say that this won't occur for systems >= XP.
|
||||
*/
|
||||
int64_t get_microseconds ();
|
||||
|
||||
|
|
|
|||
|
|
@ -23,11 +23,15 @@
|
|||
|
||||
#include "pbd/compose.h"
|
||||
#include "pbd/debug.h"
|
||||
#include "pbd/error.h"
|
||||
|
||||
#include "i18n.h"
|
||||
|
||||
#define DEBUG_TIMING(msg) DEBUG_TRACE (PBD::DEBUG::Timing, msg);
|
||||
|
||||
namespace {
|
||||
|
||||
static
|
||||
UINT&
|
||||
timer_resolution ()
|
||||
{
|
||||
|
|
@ -35,7 +39,7 @@ timer_resolution ()
|
|||
return timer_res_ms;
|
||||
}
|
||||
|
||||
}
|
||||
} // namespace
|
||||
|
||||
namespace PBD {
|
||||
|
||||
|
|
@ -100,6 +104,7 @@ reset_resolution ()
|
|||
DEBUG_TIMING("Could not reset the Timer resolution.\n");
|
||||
return false;
|
||||
}
|
||||
DEBUG_TIMING("Reset the Timer resolution.\n");
|
||||
timer_resolution() = 0;
|
||||
return true;
|
||||
}
|
||||
|
|
@ -108,34 +113,9 @@ reset_resolution ()
|
|||
|
||||
namespace {
|
||||
|
||||
bool&
|
||||
qpc_frequency_success ()
|
||||
{
|
||||
static bool success = false;
|
||||
return success;
|
||||
}
|
||||
|
||||
LARGE_INTEGER
|
||||
qpc_frequency ()
|
||||
{
|
||||
LARGE_INTEGER freq;
|
||||
if (QueryPerformanceFrequency(&freq) == 0) {
|
||||
DEBUG_TIMING ("Failed to determine frequency of QPC\n");
|
||||
qpc_frequency_success() = false;
|
||||
} else {
|
||||
qpc_frequency_success() = true;
|
||||
}
|
||||
|
||||
return freq;
|
||||
}
|
||||
|
||||
LARGE_INTEGER
|
||||
qpc_frequency_cached ()
|
||||
{
|
||||
static LARGE_INTEGER frequency = qpc_frequency ();
|
||||
return frequency;
|
||||
}
|
||||
static double timer_rate_us = 0.0;
|
||||
|
||||
static
|
||||
bool
|
||||
test_qpc_validity ()
|
||||
{
|
||||
|
|
@ -159,25 +139,37 @@ namespace QPC {
|
|||
bool
|
||||
check_timer_valid ()
|
||||
{
|
||||
// setup caching the timer frequency
|
||||
qpc_frequency_cached ();
|
||||
if (!qpc_frequency_success ()) {
|
||||
if (!timer_rate_us) {
|
||||
return false;
|
||||
}
|
||||
return test_qpc_validity ();
|
||||
}
|
||||
|
||||
bool
|
||||
initialize ()
|
||||
{
|
||||
LARGE_INTEGER freq;
|
||||
if (!QueryPerformanceFrequency(&freq) || freq.QuadPart < 1) {
|
||||
info << X_("Failed to determine frequency of QPC\n") << endmsg;
|
||||
timer_rate_us = 0;
|
||||
} else {
|
||||
timer_rate_us = 1000000.0 / freq.QuadPart;
|
||||
}
|
||||
info << string_compose(X_("QPC timer microseconds per tick: %1\n"),
|
||||
timer_rate_us) << endmsg;
|
||||
return !timer_rate_us;
|
||||
}
|
||||
|
||||
int64_t
|
||||
get_microseconds ()
|
||||
{
|
||||
LARGE_INTEGER current_val;
|
||||
|
||||
if (qpc_frequency_success()) {
|
||||
if (timer_rate_us) {
|
||||
// MS docs say this will always succeed for systems >= XP but it may
|
||||
// not return a monotonic value with non-invariant TSC's etc
|
||||
if (QueryPerformanceCounter(¤t_val) != 0) {
|
||||
return (int64_t)(((double)current_val.QuadPart) /
|
||||
((double)qpc_frequency_cached().QuadPart) * 1000000.0);
|
||||
return (int64_t)(current_val.QuadPart * timer_rate_us);
|
||||
}
|
||||
}
|
||||
DEBUG_TIMING ("Could not get QPC timer\n");
|
||||
|
|
@ -189,8 +181,7 @@ get_microseconds ()
|
|||
int64_t
|
||||
get_microseconds ()
|
||||
{
|
||||
qpc_frequency_cached();
|
||||
if (qpc_frequency_success()) {
|
||||
if (timer_rate_us) {
|
||||
return QPC::get_microseconds ();
|
||||
}
|
||||
// For XP systems that don't support a high-res performance counter
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue