Tizen 2.1 base
[platform/upstream/gcd.git] / dispatch-1.0 / testing / dispatch_drift.c
1 /*
2  * Copyright (c) 2008-2009 Apple Inc. All rights reserved.
3  *
4  * @APPLE_APACHE_LICENSE_HEADER_START@
5  * 
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  * 
10  *     http://www.apache.org/licenses/LICENSE-2.0
11  * 
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  * 
18  * @APPLE_APACHE_LICENSE_HEADER_END@
19  */
20
21 #include "config/config.h"
22
23 #include <dispatch/dispatch.h>
24 #include <sys/time.h>
25 #include <math.h>
26 #include <unistd.h>
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include "dispatch_test.h"
30
31 //
32 // Verify that dispatch timers do not drift, that is to say, increasingly
33 // stray from their intended interval.
34 //
35 // The jitter of the event handler is defined to be the amount of time
36 // difference between the actual and expected timing of the event handler
37 // invocation. The drift is defined to be the amount that the jitter changes
38 // over time. 
39 //
40 // Important: be sure to use the same clock when comparing actual and expected
41 // values. Skew between different clocks is to be expected.
42 //
43
44 int
45 main(int argc __attribute__((unused)), char* argv[] __attribute__((unused)))
46 {
47         __block uint32_t count = 0;
48         __block double last_jitter = 0;
49         
50         // interval is 1/10th of a second
51         uint64_t interval = NSEC_PER_SEC / 10;
52         double interval_d = (double)interval / (double)NSEC_PER_SEC;
53         
54         // for 25 seconds
55         unsigned int target = 25 / interval_d;
56
57         __block double first = 0;
58         __block double jittersum = 0;
59         __block double driftsum = 0;
60         
61         test_start("Timer drift test");
62
63         dispatch_source_t timer;
64         timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, dispatch_get_main_queue());
65         test_ptr_notnull("DISPATCH_SOURCE_TYPE_TIMER", timer);
66         
67         dispatch_source_set_event_handler(timer, ^{
68                 struct timeval now_tv;
69                 gettimeofday(&now_tv, NULL);
70                 double now = now_tv.tv_sec + ((double)now_tv.tv_usec / (double)USEC_PER_SEC);
71
72                 if (first == 0) {
73                         first = now;
74                 }
75
76                 double goal = first + interval_d * count;
77                 double jitter = goal - now;
78                 double drift = jitter - last_jitter;
79
80                 count += dispatch_source_get_data(timer);
81                 jittersum += jitter;
82                 driftsum += drift;
83                 
84                 printf("%4d: jitter %f, drift %f\n", count, jitter, drift);
85                 
86                 if (count >= target) {
87                         test_double_less_than("average jitter", fabs(jittersum) / (double)count, 0.0001);
88                         test_double_less_than("average drift", fabs(driftsum) / (double)count, 0.0001);
89                         test_stop();
90                 }
91                 last_jitter = jitter;
92         });
93         
94         struct timeval now_tv;
95         struct timespec now_ts;
96         
97         gettimeofday(&now_tv, NULL);
98         now_ts.tv_sec = now_tv.tv_sec;
99         now_ts.tv_nsec = now_tv.tv_usec * NSEC_PER_USEC;
100
101         dispatch_source_set_timer(timer, dispatch_walltime(&now_ts, interval), interval, 0);
102
103         dispatch_resume(timer);
104
105         dispatch_main();
106         return 0;
107 }
108