Add tests that show the timing differences between the Glib/mm based timeouts
[ardour.git] / libs / pbd / test / timer_test.h
1 #include <cppunit/TestFixture.h>
2 #include <cppunit/extensions/HelperMacros.h>
3
4 #include "glibmm/main.h"
5
6 #include "pbd/timing.h"
7
8 /**
9  * The main point of this test is to the compare the different
10  * ways of setting a timeout with glib and glibmm and the
11  * PBD::Timers class and then to test them all again with
12  * the maximum multimedia timer resolution(1ms) set with
13  * timeBeginPeriod on Windows.
14  *
15  * The test demonstrates that when using Glibmm TimeoutSources
16  * the frequency of the timers is different that using Glib based
17  * timeouts. In Ardour that resulted in a noticable increase in
18  * CPU Usage, but behaviour may vary.
19  *
20  * The other thing being tested is what effect adding two short
21  * timeouts(<40ms) to a glib context has on the idle timeout on
22  * Windows.
23  *
24  * Glib Timeout sources run at a higher priority than the idle
25  * handler, so the more work performed in the timeout handlers
26  * the less frequent the idle handler will run until doesn't get
27  * scheduled at all. The consequence of this is blocking the UI.
28  *
29  * Similarily because timeout sources and UI updates/rendering
30  * occur in the same context in Gtk the length of expose/draw
31  * operations will affect the accuracy of the timeouts.
32  */
33 class TimerTest : public CppUnit::TestFixture
34 {
35         CPPUNIT_TEST_SUITE (TimerTest);
36         CPPUNIT_TEST (testGlibTimeoutSources);
37         CPPUNIT_TEST (testGlibmmSignalTimeouts);
38         CPPUNIT_TEST (testGlibmmTimeoutSources);
39         CPPUNIT_TEST (testTimers);
40         CPPUNIT_TEST (testTimersIdleFrequency);
41         CPPUNIT_TEST (testTimersBlockIdle);
42 #ifdef PLATFORM_WINDOWS
43         CPPUNIT_TEST (testGlibTimeoutSourcesHR);
44         CPPUNIT_TEST (testGlibmmSignalTimeoutsHR);
45         CPPUNIT_TEST (testGlibmmTimeoutSourcesHR);
46         CPPUNIT_TEST (testTimersHR);
47         CPPUNIT_TEST (testTimersIdleFrequencyHR);
48         CPPUNIT_TEST (testTimersBlockIdleHR);
49 #endif
50         CPPUNIT_TEST_SUITE_END ();
51
52 public:
53
54         TimerTest ()
55                 : m_connect_idle(false)
56                 , m_block_idle(false)
57         { }
58
59         void _testGlibTimeoutSources ();
60         void _testGlibmmSignalTimeouts ();
61         void _testGlibmmTimeoutSources ();
62         void _testTimers ();
63         void _testTimersIdleFrequency ();
64         void _testTimersBlockIdle ();
65
66         void testGlibTimeoutSources ();
67         void testGlibmmSignalTimeouts ();
68         void testGlibmmTimeoutSources ();
69         void testTimers ();
70         void testTimersIdleFrequency ();
71         void testTimersBlockIdle ();
72
73 #ifdef PLATFORM_WINDOWS
74         void testGlibTimeoutSourcesHR ();
75         void testGlibmmSignalTimeoutsHR ();
76         void testGlibmmTimeoutSourcesHR ();
77         void testTimersHR ();
78         void testTimersIdleFrequencyHR ();
79         void testTimersBlockIdleHR ();
80 #endif
81
82 private:
83
84         static guint64 second_timer_usecs ()
85         { return 1000000; }
86
87         static guint64 fast_timer_usecs ()
88         { return 100000; }
89
90         static guint64 rapid1_timer_usecs ()
91         { return 40000; }
92
93         static guint64 rapid2_timer_usecs ()
94         { return 15000; }
95
96         static guint64 second_timer_ms ()
97         { return second_timer_usecs () / 1000; }
98
99         static guint64 fast_timer_ms ()
100         { return fast_timer_usecs () / 1000; }
101
102         static guint64 rapid1_timer_ms ()
103         { return rapid1_timer_usecs () / 1000; }
104
105         static guint64 rapid2_timer_ms ()
106         { return rapid2_timer_usecs () / 1000; }
107
108         static guint64 test_length_ms ()
109         { return 10 * 1000; }
110
111         std::string m_current_test_name;
112
113         bool m_connect_idle;
114         bool m_block_idle;
115
116         bool on_idle_handler ();
117         bool on_quit_handler ();
118
119         void on_second_timeout ();
120         void on_fast_timeout ();
121         void on_rapid1_timeout ();
122         void on_rapid2_timeout ();
123
124         bool on_second_timeout_glibmm ();
125         bool on_fast_timeout_glibmm ();
126         bool on_rapid1_timeout_glibmm ();
127         bool on_rapid2_timeout_glibmm ();
128
129         static gboolean _second_timeout_handler (void*);
130         static gboolean _fast_timeout_handler (void*);
131         static gboolean _rapid1_timeout_handler (void*);
132         static gboolean _rapid2_timeout_handler (void*);
133
134         void start_timing ();
135         void reset_timing ();
136
137         void reset_timing_run_main ();
138
139         static void
140         simulate_load (const std::string& name, guint64 time_usecs);
141         Glib::RefPtr<Glib::MainLoop> m_main;
142         Glib::RefPtr<Glib::MainContext> m_context;
143
144         void connect_idle_handler ();
145         void connect_quit_timeout ();
146
147         PBD::TimingData m_idle_timing_data;
148         PBD::TimingData m_second_timing_data;
149         PBD::TimingData m_fast_timing_data;
150         PBD::TimingData m_rapid1_timing_data;
151         PBD::TimingData m_rapid2_timing_data;
152 };