551 lines
12 KiB
C++
551 lines
12 KiB
C++
|
#include "timer_test.h"
|
||
|
|
||
|
#include <iostream>
|
||
|
#include <sstream>
|
||
|
#include <algorithm>
|
||
|
|
||
|
#include "pbd/timer.h"
|
||
|
|
||
|
#ifdef PLATFORM_WINDOWS
|
||
|
#include <windows.h>
|
||
|
#endif
|
||
|
|
||
|
CPPUNIT_TEST_SUITE_REGISTRATION (TimerTest);
|
||
|
|
||
|
using namespace std;
|
||
|
|
||
|
#ifdef PLATFORM_WINDOWS
|
||
|
UINT&
|
||
|
min_timer_resolution ()
|
||
|
{
|
||
|
static UINT min_res_ms = 0;
|
||
|
return min_res_ms;
|
||
|
}
|
||
|
|
||
|
bool
|
||
|
set_min_timer_resolution ()
|
||
|
{
|
||
|
TIMECAPS caps;
|
||
|
|
||
|
if (timeGetDevCaps(&caps, sizeof(TIMECAPS)) != TIMERR_NOERROR) {
|
||
|
cerr << "Could not get timer device capabilities..." << endl;
|
||
|
} else {
|
||
|
if (timeBeginPeriod(caps.wPeriodMin) != TIMERR_NOERROR) {
|
||
|
cerr << "Could not set minimum timer resolution to: " << caps.wPeriodMin << "ms" << endl;
|
||
|
return false;
|
||
|
}
|
||
|
else {
|
||
|
cerr << "Multimedia timer resolution set to: " << caps.wPeriodMin << "ms" << endl;
|
||
|
min_timer_resolution() = caps.wPeriodMin;
|
||
|
return true;
|
||
|
}
|
||
|
}
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
bool
|
||
|
reset_timer_resolution ()
|
||
|
{
|
||
|
if (min_timer_resolution()) {
|
||
|
if (timeEndPeriod(min_timer_resolution()) != TIMERR_NOERROR) {
|
||
|
cerr << "Could not reset timer resolution" << endl;
|
||
|
return false;
|
||
|
} else {
|
||
|
cerr << "Multimedia timer resolution reset" << endl;
|
||
|
return true;
|
||
|
}
|
||
|
}
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
#endif
|
||
|
|
||
|
void
|
||
|
TimerTest::simulate_load (const string& name, guint64 load_usecs)
|
||
|
{
|
||
|
PBD::Timing timing;
|
||
|
std::ostringstream oss;
|
||
|
oss << name << " Load.";
|
||
|
|
||
|
guint64 i = 0;
|
||
|
do {
|
||
|
timing.update ();
|
||
|
|
||
|
// totally arbitrary
|
||
|
if (i % 10000 == 0) {
|
||
|
oss << ".";
|
||
|
}
|
||
|
|
||
|
++i;
|
||
|
} while (timing.elapsed () < load_usecs);
|
||
|
|
||
|
oss << "Expected = " << load_usecs;
|
||
|
oss << ", Elapsed = " << timing.elapsed ();
|
||
|
oss << endl;
|
||
|
//cerr << oss.str();
|
||
|
}
|
||
|
|
||
|
void
|
||
|
TimerTest::on_second_timeout ()
|
||
|
{
|
||
|
cerr << endl;
|
||
|
cerr << "Timing Summary: " << m_current_test_name << endl;
|
||
|
|
||
|
if (m_idle_timing_data.size()) {
|
||
|
cerr << "Idle Timing: " << m_idle_timing_data.summary();
|
||
|
}
|
||
|
if (m_fast_timing_data.size()) {
|
||
|
cerr << "Fast Timing: " << m_fast_timing_data.summary();
|
||
|
}
|
||
|
if (m_rapid1_timing_data.size()) {
|
||
|
cerr << "Rapid1 Timing: " << m_rapid1_timing_data.summary();
|
||
|
}
|
||
|
if (m_rapid2_timing_data.size()) {
|
||
|
cerr << "Rapid2 Timing: " << m_rapid2_timing_data.summary();
|
||
|
}
|
||
|
reset_timing ();
|
||
|
}
|
||
|
|
||
|
bool
|
||
|
TimerTest::on_second_timeout_glibmm ()
|
||
|
{
|
||
|
TimerTest::on_second_timeout ();
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
void
|
||
|
TimerTest::on_fast_timeout ()
|
||
|
{
|
||
|
m_fast_timing_data.add_interval ();
|
||
|
if (m_block_idle) {
|
||
|
// do nothing, handled in rapid timers
|
||
|
} else {
|
||
|
simulate_load ("Rapid1", 4000);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
bool
|
||
|
TimerTest::on_fast_timeout_glibmm ()
|
||
|
{
|
||
|
on_fast_timeout ();
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
void
|
||
|
TimerTest::on_rapid1_timeout ()
|
||
|
{
|
||
|
m_rapid1_timing_data.add_interval ();
|
||
|
if (m_block_idle) {
|
||
|
simulate_load ("Rapid1", rapid1_timer_usecs () * 0.5);
|
||
|
} else {
|
||
|
simulate_load ("Rapid1", 2000);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
bool
|
||
|
TimerTest::on_rapid1_timeout_glibmm ()
|
||
|
{
|
||
|
on_rapid1_timeout ();
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
void
|
||
|
TimerTest::on_rapid2_timeout ()
|
||
|
{
|
||
|
m_rapid2_timing_data.add_interval ();
|
||
|
if (m_block_idle) {
|
||
|
simulate_load ("Rapid2", rapid2_timer_usecs () * 0.5);
|
||
|
} else {
|
||
|
simulate_load ("Rapid2", 2000);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
bool
|
||
|
TimerTest::on_rapid2_timeout_glibmm ()
|
||
|
{
|
||
|
on_rapid2_timeout ();
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
bool
|
||
|
TimerTest::on_idle_handler ()
|
||
|
{
|
||
|
m_idle_timing_data.add_interval ();
|
||
|
if (m_block_idle) {
|
||
|
simulate_load ("Idle", rapid2_timer_usecs ());
|
||
|
}
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
bool
|
||
|
TimerTest::on_quit_handler ()
|
||
|
{
|
||
|
cerr << "Quit Handler" << endl;
|
||
|
m_main->quit ();
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
void
|
||
|
TimerTest::reset_timing ()
|
||
|
{
|
||
|
m_idle_timing_data.reset ();
|
||
|
m_fast_timing_data.reset ();
|
||
|
m_rapid1_timing_data.reset ();
|
||
|
m_rapid2_timing_data.reset ();
|
||
|
}
|
||
|
|
||
|
void
|
||
|
TimerTest::start_timing ()
|
||
|
{
|
||
|
m_idle_timing_data.start_timing ();
|
||
|
m_fast_timing_data.start_timing ();
|
||
|
m_rapid1_timing_data.start_timing ();
|
||
|
m_rapid2_timing_data.start_timing ();
|
||
|
}
|
||
|
|
||
|
gboolean
|
||
|
TimerTest::_second_timeout_handler (void *data)
|
||
|
{
|
||
|
TimerTest *const tt = static_cast<TimerTest*>(data);
|
||
|
tt->on_second_timeout ();
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
gboolean
|
||
|
TimerTest::_fast_timeout_handler (void *data)
|
||
|
{
|
||
|
TimerTest *const tt = static_cast<TimerTest*>(data);
|
||
|
tt->on_fast_timeout ();
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
gboolean
|
||
|
TimerTest::_rapid1_timeout_handler (void *data)
|
||
|
{
|
||
|
TimerTest *const tt = static_cast<TimerTest*>(data);
|
||
|
tt->on_rapid1_timeout ();
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
gboolean
|
||
|
TimerTest::_rapid2_timeout_handler (void *data)
|
||
|
{
|
||
|
TimerTest *const tt = static_cast<TimerTest*>(data);
|
||
|
tt->on_rapid2_timeout ();
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
void
|
||
|
TimerTest::reset_timing_run_main ()
|
||
|
{
|
||
|
reset_timing ();
|
||
|
start_timing ();
|
||
|
|
||
|
connect_quit_timeout ();
|
||
|
|
||
|
m_main = Glib::MainLoop::create (m_context);
|
||
|
m_main->run ();
|
||
|
}
|
||
|
|
||
|
void
|
||
|
TimerTest::testGlibTimeoutSources ()
|
||
|
{
|
||
|
m_current_test_name = "testGlibTimeoutSources";
|
||
|
_testGlibTimeoutSources ();
|
||
|
}
|
||
|
|
||
|
void
|
||
|
TimerTest::_testGlibTimeoutSources ()
|
||
|
{
|
||
|
m_context = Glib::MainContext::create ();
|
||
|
|
||
|
GSource * second_timeout_source = g_timeout_source_new (second_timer_ms ());
|
||
|
|
||
|
g_source_set_callback (second_timeout_source , &TimerTest::_second_timeout_handler, this, NULL);
|
||
|
|
||
|
g_source_attach (second_timeout_source, m_context->gobj());
|
||
|
|
||
|
if (m_connect_idle) {
|
||
|
connect_idle_handler ();
|
||
|
reset_timing_run_main ();
|
||
|
}
|
||
|
|
||
|
GSource * fast_timeout_source = g_timeout_source_new (fast_timer_ms ());
|
||
|
|
||
|
g_source_set_callback (fast_timeout_source , &TimerTest::_fast_timeout_handler, this, NULL);
|
||
|
|
||
|
g_source_attach (fast_timeout_source, m_context->gobj());
|
||
|
|
||
|
// now run with fast timeout
|
||
|
reset_timing_run_main ();
|
||
|
|
||
|
GSource * rapid1_timeout_source = g_timeout_source_new (rapid1_timer_ms ());
|
||
|
|
||
|
g_source_set_callback (rapid1_timeout_source , &TimerTest::_rapid1_timeout_handler, this, NULL);
|
||
|
|
||
|
g_source_attach (rapid1_timeout_source, m_context->gobj());
|
||
|
|
||
|
// now run with fast and rapid1 timeouts
|
||
|
reset_timing_run_main ();
|
||
|
|
||
|
GSource * rapid2_timeout_source = g_timeout_source_new (rapid2_timer_ms ());
|
||
|
|
||
|
g_source_set_callback (rapid2_timeout_source , &TimerTest::_rapid2_timeout_handler, this, NULL);
|
||
|
|
||
|
g_source_attach (rapid2_timeout_source, m_context->gobj());
|
||
|
|
||
|
// now run with fast, rapid1 and rapid2 timeouts
|
||
|
reset_timing_run_main ();
|
||
|
|
||
|
// cleanup
|
||
|
g_source_destroy (second_timeout_source);
|
||
|
g_source_unref (second_timeout_source);
|
||
|
|
||
|
g_source_destroy (fast_timeout_source);
|
||
|
g_source_unref (fast_timeout_source);
|
||
|
|
||
|
g_source_destroy (rapid1_timeout_source);
|
||
|
g_source_unref (rapid1_timeout_source);
|
||
|
|
||
|
g_source_destroy (rapid2_timeout_source);
|
||
|
g_source_unref (rapid2_timeout_source);
|
||
|
}
|
||
|
|
||
|
void
|
||
|
TimerTest::testGlibmmSignalTimeouts ()
|
||
|
{
|
||
|
m_current_test_name = "testGlibmmSignalTimeouts";
|
||
|
_testGlibmmSignalTimeouts ();
|
||
|
}
|
||
|
|
||
|
void
|
||
|
TimerTest::_testGlibmmSignalTimeouts ()
|
||
|
{
|
||
|
m_context = Glib::MainContext::get_default ();
|
||
|
|
||
|
Glib::signal_timeout().connect(sigc::mem_fun(*this, &TimerTest::on_second_timeout_glibmm), second_timer_ms());
|
||
|
|
||
|
if (m_connect_idle) {
|
||
|
connect_idle_handler ();
|
||
|
reset_timing_run_main ();
|
||
|
}
|
||
|
|
||
|
Glib::signal_timeout().connect(sigc::mem_fun(*this, &TimerTest::on_fast_timeout_glibmm), fast_timer_ms());
|
||
|
|
||
|
reset_timing_run_main ();
|
||
|
|
||
|
Glib::signal_timeout().connect(sigc::mem_fun(*this, &TimerTest::on_rapid1_timeout_glibmm), rapid1_timer_ms());
|
||
|
|
||
|
reset_timing_run_main ();
|
||
|
|
||
|
Glib::signal_timeout().connect(sigc::mem_fun(*this, &TimerTest::on_rapid2_timeout_glibmm), rapid2_timer_ms());
|
||
|
|
||
|
reset_timing_run_main ();
|
||
|
}
|
||
|
|
||
|
void
|
||
|
TimerTest::testGlibmmTimeoutSources ()
|
||
|
{
|
||
|
m_current_test_name = "testGlibmmTimeoutSources";
|
||
|
_testGlibmmTimeoutSources ();
|
||
|
}
|
||
|
|
||
|
void
|
||
|
TimerTest::_testGlibmmTimeoutSources ()
|
||
|
{
|
||
|
m_context = Glib::MainContext::create ();
|
||
|
|
||
|
const Glib::RefPtr<Glib::TimeoutSource> second_source = Glib::TimeoutSource::create(second_timer_ms());
|
||
|
second_source->connect(sigc::mem_fun(*this, &TimerTest::on_second_timeout_glibmm));
|
||
|
|
||
|
second_source->attach(m_context);
|
||
|
|
||
|
if (m_connect_idle) {
|
||
|
connect_idle_handler ();
|
||
|
reset_timing_run_main ();
|
||
|
}
|
||
|
|
||
|
const Glib::RefPtr<Glib::TimeoutSource> fast_source = Glib::TimeoutSource::create(fast_timer_ms());
|
||
|
fast_source->connect(sigc::mem_fun(*this, &TimerTest::on_fast_timeout_glibmm));
|
||
|
|
||
|
fast_source->attach(m_context);
|
||
|
|
||
|
reset_timing_run_main ();
|
||
|
|
||
|
const Glib::RefPtr<Glib::TimeoutSource> rapid1_source = Glib::TimeoutSource::create(rapid1_timer_ms());
|
||
|
sigc::connection rapid1_connection = rapid1_source->connect(sigc::mem_fun(*this, &TimerTest::on_rapid1_timeout_glibmm));
|
||
|
|
||
|
rapid1_source->attach(m_context);
|
||
|
|
||
|
reset_timing_run_main ();
|
||
|
|
||
|
const Glib::RefPtr<Glib::TimeoutSource> rapid2_source = Glib::TimeoutSource::create(rapid2_timer_ms());
|
||
|
sigc::connection rapid2_connection = rapid2_source->connect(sigc::mem_fun(*this, &TimerTest::on_rapid2_timeout_glibmm));
|
||
|
|
||
|
rapid2_source->attach(m_context);
|
||
|
|
||
|
reset_timing_run_main ();
|
||
|
}
|
||
|
|
||
|
void
|
||
|
TimerTest::connect_idle_handler ()
|
||
|
{
|
||
|
const Glib::RefPtr<Glib::IdleSource> idle_source = Glib::IdleSource::create();
|
||
|
idle_source->connect(sigc::mem_fun(*this, &TimerTest::on_idle_handler));
|
||
|
|
||
|
idle_source->attach(m_context);
|
||
|
}
|
||
|
|
||
|
void
|
||
|
TimerTest::connect_quit_timeout ()
|
||
|
{
|
||
|
const Glib::RefPtr<Glib::TimeoutSource> quit_source = Glib::TimeoutSource::create(test_length_ms());
|
||
|
quit_source->connect(sigc::mem_fun(*this, &TimerTest::on_quit_handler));
|
||
|
|
||
|
quit_source->attach(m_context);
|
||
|
}
|
||
|
|
||
|
void
|
||
|
TimerTest::testTimers ()
|
||
|
{
|
||
|
m_current_test_name = "testTimers";
|
||
|
_testTimers ();
|
||
|
}
|
||
|
|
||
|
void
|
||
|
TimerTest::_testTimers ()
|
||
|
{
|
||
|
m_context = Glib::MainContext::create ();
|
||
|
|
||
|
PBD::StandardTimer second_timer (second_timer_ms (), m_context);
|
||
|
sigc::connection second_connection = second_timer.connect (sigc::mem_fun (this, &TimerTest::on_second_timeout));
|
||
|
|
||
|
if (m_connect_idle) {
|
||
|
connect_idle_handler ();
|
||
|
// let the idle handler run as fast as it can
|
||
|
reset_timing_run_main();
|
||
|
}
|
||
|
|
||
|
PBD::StandardTimer fast_timer (fast_timer_ms (), m_context);
|
||
|
sigc::connection fast_connection = fast_timer.connect (sigc::mem_fun (this, &TimerTest::on_fast_timeout));
|
||
|
|
||
|
reset_timing_run_main();
|
||
|
|
||
|
PBD::StandardTimer rapid1_timer (rapid1_timer_ms (), m_context);
|
||
|
sigc::connection rapid1_connection = rapid1_timer.connect (sigc::mem_fun (this, &TimerTest::on_rapid1_timeout));
|
||
|
|
||
|
reset_timing_run_main();
|
||
|
|
||
|
PBD::StandardTimer rapid2_timer (rapid2_timer_ms (), m_context);
|
||
|
sigc::connection rapid2_connection = rapid2_timer.connect (sigc::mem_fun (this, &TimerTest::on_rapid2_timeout));
|
||
|
|
||
|
reset_timing_run_main();
|
||
|
}
|
||
|
|
||
|
void
|
||
|
TimerTest::testTimersIdleFrequency ()
|
||
|
{
|
||
|
m_current_test_name = "testTimersIdleFrequency";
|
||
|
_testTimersIdleFrequency ();
|
||
|
}
|
||
|
|
||
|
void
|
||
|
TimerTest::_testTimersIdleFrequency ()
|
||
|
{
|
||
|
m_block_idle = false;
|
||
|
m_connect_idle = true;
|
||
|
|
||
|
_testTimers ();
|
||
|
|
||
|
m_block_idle = false;
|
||
|
m_connect_idle = false;
|
||
|
}
|
||
|
|
||
|
void
|
||
|
TimerTest::testTimersBlockIdle ()
|
||
|
{
|
||
|
m_current_test_name = "testTimersBlockIdle";
|
||
|
_testTimersBlockIdle ();
|
||
|
}
|
||
|
|
||
|
void
|
||
|
TimerTest::_testTimersBlockIdle ()
|
||
|
{
|
||
|
m_block_idle = true;
|
||
|
m_connect_idle = true;
|
||
|
|
||
|
_testTimers ();
|
||
|
|
||
|
m_block_idle = false;
|
||
|
m_connect_idle = false;
|
||
|
}
|
||
|
|
||
|
#ifdef PLATFORM_WINDOWS
|
||
|
void
|
||
|
TimerTest::testGlibTimeoutSourcesHR ()
|
||
|
{
|
||
|
CPPUNIT_ASSERT(set_min_timer_resolution());
|
||
|
|
||
|
m_current_test_name = "testGlibTimeoutSourcesHR";
|
||
|
_testGlibTimeoutSources ();
|
||
|
|
||
|
CPPUNIT_ASSERT(reset_timer_resolution());
|
||
|
}
|
||
|
|
||
|
void
|
||
|
TimerTest::testGlibmmSignalTimeoutsHR ()
|
||
|
{
|
||
|
CPPUNIT_ASSERT(set_min_timer_resolution());
|
||
|
|
||
|
m_current_test_name = "testGlibmmSignalTimeoutsHR";
|
||
|
_testGlibmmSignalTimeouts ();
|
||
|
|
||
|
CPPUNIT_ASSERT(reset_timer_resolution());
|
||
|
}
|
||
|
|
||
|
void
|
||
|
TimerTest::testGlibmmTimeoutSourcesHR ()
|
||
|
{
|
||
|
CPPUNIT_ASSERT(set_min_timer_resolution());
|
||
|
|
||
|
m_current_test_name = "testGlibmmTimeoutSourcesHR";
|
||
|
_testGlibmmTimeoutSources ();
|
||
|
|
||
|
CPPUNIT_ASSERT(reset_timer_resolution());
|
||
|
}
|
||
|
|
||
|
void
|
||
|
TimerTest::testTimersHR ()
|
||
|
{
|
||
|
CPPUNIT_ASSERT(set_min_timer_resolution());
|
||
|
|
||
|
m_current_test_name = "testTimersHR";
|
||
|
_testTimers ();
|
||
|
|
||
|
CPPUNIT_ASSERT(reset_timer_resolution());
|
||
|
}
|
||
|
|
||
|
void
|
||
|
TimerTest::testTimersIdleFrequencyHR ()
|
||
|
{
|
||
|
CPPUNIT_ASSERT(set_min_timer_resolution());
|
||
|
|
||
|
m_current_test_name = "testTimersIdleFrequencyHR";
|
||
|
_testTimersIdleFrequency ();
|
||
|
|
||
|
CPPUNIT_ASSERT(reset_timer_resolution());
|
||
|
}
|
||
|
|
||
|
void
|
||
|
TimerTest::testTimersBlockIdleHR ()
|
||
|
{
|
||
|
CPPUNIT_ASSERT(set_min_timer_resolution());
|
||
|
|
||
|
m_current_test_name = "testTimersIdleFrequencyHR";
|
||
|
_testTimersBlockIdle ();
|
||
|
|
||
|
CPPUNIT_ASSERT(reset_timer_resolution());
|
||
|
}
|
||
|
|
||
|
#endif
|