summaryrefslogtreecommitdiff
path: root/libs/pbd/test/timer_test.h
blob: 1da069fdba622811e8460b32b9a49f5325d7677d (plain)
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
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
#include <cppunit/TestFixture.h>
#include <cppunit/extensions/HelperMacros.h>

#include "glibmm/main.h"

#include "pbd/timing.h"

/**
 * The main point of this test is to the compare the different
 * ways of setting a timeout with glib and glibmm and the
 * PBD::Timers class and then to test them all again with
 * the maximum multimedia timer resolution(1ms) set with
 * timeBeginPeriod on Windows.
 *
 * The test demonstrates that when using Glibmm TimeoutSources
 * the frequency of the timers is different that using Glib based
 * timeouts. In Ardour that resulted in a noticable increase in
 * CPU Usage, but behaviour may vary.
 *
 * The other thing being tested is what effect adding two short
 * timeouts(<40ms) to a glib context has on the idle timeout on
 * Windows.
 *
 * Glib Timeout sources run at a higher priority than the idle
 * handler, so the more work performed in the timeout handlers
 * the less frequent the idle handler will run until doesn't get
 * scheduled at all. The consequence of this is blocking the UI.
 *
 * Similarily because timeout sources and UI updates/rendering
 * occur in the same context in Gtk the length of expose/draw
 * operations will affect the accuracy of the timeouts.
 */
class TimerTest : public CppUnit::TestFixture
{
	CPPUNIT_TEST_SUITE (TimerTest);
	CPPUNIT_TEST (testGlibTimeoutSources);
	CPPUNIT_TEST (testGlibmmSignalTimeouts);
	CPPUNIT_TEST (testGlibmmTimeoutSources);
	CPPUNIT_TEST (testTimers);
	CPPUNIT_TEST (testTimersIdleFrequency);
	CPPUNIT_TEST (testTimersBlockIdle);
#ifdef PLATFORM_WINDOWS
	CPPUNIT_TEST (testGlibTimeoutSourcesHR);
	CPPUNIT_TEST (testGlibmmSignalTimeoutsHR);
	CPPUNIT_TEST (testGlibmmTimeoutSourcesHR);
	CPPUNIT_TEST (testTimersHR);
	CPPUNIT_TEST (testTimersIdleFrequencyHR);
	CPPUNIT_TEST (testTimersBlockIdleHR);
#endif
	CPPUNIT_TEST_SUITE_END ();

public:

	TimerTest ()
		: m_connect_idle(false)
		, m_block_idle(false)
	{ }

	void _testGlibTimeoutSources ();
	void _testGlibmmSignalTimeouts ();
	void _testGlibmmTimeoutSources ();
	void _testTimers ();
	void _testTimersIdleFrequency ();
	void _testTimersBlockIdle ();

	void testGlibTimeoutSources ();
	void testGlibmmSignalTimeouts ();
	void testGlibmmTimeoutSources ();
	void testTimers ();
	void testTimersIdleFrequency ();
	void testTimersBlockIdle ();

#ifdef PLATFORM_WINDOWS
	void testGlibTimeoutSourcesHR ();
	void testGlibmmSignalTimeoutsHR ();
	void testGlibmmTimeoutSourcesHR ();
	void testTimersHR ();
	void testTimersIdleFrequencyHR ();
	void testTimersBlockIdleHR ();
#endif

private:

	static guint64 second_timer_usecs ()
	{ return 1000000; }

	static guint64 fast_timer_usecs ()
	{ return 100000; }

	static guint64 rapid1_timer_usecs ()
	{ return 40000; }

	static guint64 rapid2_timer_usecs ()
	{ return 15000; }

	static guint64 second_timer_ms ()
	{ return second_timer_usecs () / 1000; }

	static guint64 fast_timer_ms ()
	{ return fast_timer_usecs () / 1000; }

	static guint64 rapid1_timer_ms ()
	{ return rapid1_timer_usecs () / 1000; }

	static guint64 rapid2_timer_ms ()
	{ return rapid2_timer_usecs () / 1000; }

	static guint64 test_length_ms ()
	{ return 2 * 1000; }

	std::string m_current_test_name;

	bool m_connect_idle;
	bool m_block_idle;

	bool on_idle_handler ();
	bool on_quit_handler ();

	void on_second_timeout ();
	void on_fast_timeout ();
	void on_rapid1_timeout ();
	void on_rapid2_timeout ();

	bool on_second_timeout_glibmm ();
	bool on_fast_timeout_glibmm ();
	bool on_rapid1_timeout_glibmm ();
	bool on_rapid2_timeout_glibmm ();

	static gboolean _second_timeout_handler (void*);
	static gboolean _fast_timeout_handler (void*);
	static gboolean _rapid1_timeout_handler (void*);
	static gboolean _rapid2_timeout_handler (void*);

	void start_timing ();
	void reset_timing ();

	void reset_timing_run_main ();

	static void
	simulate_load (const std::string& name, guint64 time_usecs);
	Glib::RefPtr<Glib::MainLoop> m_main;
	Glib::RefPtr<Glib::MainContext> m_context;

	void connect_idle_handler ();
	void connect_quit_timeout ();

	PBD::TimingData m_idle_timing_data;
	PBD::TimingData m_second_timing_data;
	PBD::TimingData m_fast_timing_data;
	PBD::TimingData m_rapid1_timing_data;
	PBD::TimingData m_rapid2_timing_data;
};