diff options
Diffstat (limited to 'Spear/Sys/Timer')
-rw-r--r-- | Spear/Sys/Timer/Timer.h | 130 | ||||
-rw-r--r-- | Spear/Sys/Timer/ctimer.c | 157 | ||||
-rw-r--r-- | Spear/Sys/Timer/timer.c | 101 | ||||
-rw-r--r-- | Spear/Sys/Timer/timer.h | 64 |
4 files changed, 165 insertions, 287 deletions
diff --git a/Spear/Sys/Timer/Timer.h b/Spear/Sys/Timer/Timer.h deleted file mode 100644 index 308509c..0000000 --- a/Spear/Sys/Timer/Timer.h +++ /dev/null | |||
@@ -1,130 +0,0 @@ | |||
1 | #pragma once | ||
2 | |||
3 | #ifdef WIN32 | ||
4 | #ifdef _MSC_VER | ||
5 | typedef __int64 timeReading; | ||
6 | #else | ||
7 | typedef __UINT64_TYPE__ timeReading; | ||
8 | #endif | ||
9 | #else | ||
10 | typedef __UINT64_TYPE__ timeReading; | ||
11 | #endif | ||
12 | |||
13 | #ifdef __cplusplus | ||
14 | extern "C" { | ||
15 | #endif | ||
16 | |||
17 | /* | ||
18 | Header: Timer | ||
19 | A high resolution timer module. | ||
20 | */ | ||
21 | |||
22 | /* | ||
23 | Struct: Timer | ||
24 | */ | ||
25 | typedef struct | ||
26 | { | ||
27 | timeReading baseTime; // The instant since we start timing. | ||
28 | timeReading stopTime; // The instant the timer is stopped. | ||
29 | timeReading prevTime; // The instant the timer was ticked prior to the last tick. | ||
30 | timeReading curTime; // The instant the timer was last ticked. | ||
31 | timeReading pausedTime; // Amount of time the timer has been stopped for. | ||
32 | float deltaTime; // Amount of time elapsed since the last call to tick. | ||
33 | char stopped; | ||
34 | } Timer; | ||
35 | |||
36 | /* | ||
37 | Function: timer_init | ||
38 | Construct a new timer. | ||
39 | |||
40 | The timer is initialised by making a call to reset(). Since time | ||
41 | calculations are measured from the instant the timer is reset (base time), | ||
42 | you probably want to make a manual call to reset() at the start of | ||
43 | your application, otherwise the application will be measuring times | ||
44 | from the instant the timer's constructor is called, which can be error prone. | ||
45 | |||
46 | A call to start() must be made prior to any time calculations, as the | ||
47 | timer is initialised as stopped. | ||
48 | */ | ||
49 | void timer_init (Timer*); | ||
50 | |||
51 | /* | ||
52 | Function: timer_tick | ||
53 | Update the timer's values. | ||
54 | |||
55 | This function updates the timer's running time and caches the time | ||
56 | elapsed since the last tick or since the start if this is the first | ||
57 | tick after the last call to start(). | ||
58 | |||
59 | This function has no effect on a stopped ticker. | ||
60 | */ | ||
61 | void timer_tick (Timer*); | ||
62 | |||
63 | /* | ||
64 | Function: timer_start | ||
65 | Start the timer. | ||
66 | |||
67 | This function starts the timer for the first time or resumes it | ||
68 | after a call to stop(). | ||
69 | |||
70 | Note that this function does not reset the timer's base time; | ||
71 | it's only a mechanism to resume a stopped timer. | ||
72 | */ | ||
73 | void timer_start (Timer*); | ||
74 | |||
75 | /* | ||
76 | Function: timer_stop | ||
77 | Stop the timer. | ||
78 | |||
79 | This function essentially freezes time; any values dependent on | ||
80 | the timer will behave as if time had not passed since the moment | ||
81 | the timer was stopped. | ||
82 | |||
83 | To resume the timer call start(). | ||
84 | */ | ||
85 | void timer_stop (Timer*); | ||
86 | |||
87 | /* | ||
88 | Function: timer_reset | ||
89 | Reset the timer. | ||
90 | |||
91 | This function resets all of the timer's values such as running and | ||
92 | stop times and sets the timer to stopped. The total running time is | ||
93 | then measured from the instant the timer is reset, making the timer | ||
94 | behave as a newly constructed one. | ||
95 | |||
96 | A call to start() must be made prior to any further time calculations. | ||
97 | */ | ||
98 | void timer_reset (Timer*); | ||
99 | |||
100 | /* | ||
101 | Function: timer_get_time | ||
102 | Get the total running time. | ||
103 | |||
104 | The amount of time the timer has been stopped for is not taken | ||
105 | into account. | ||
106 | */ | ||
107 | double timer_get_time (const Timer*); | ||
108 | |||
109 | /* | ||
110 | Function: timer_get_delta | ||
111 | Get the time elapsed since the last tick, or since the start if | ||
112 | this is the first tick. | ||
113 | */ | ||
114 | float timer_get_delta (const Timer*); | ||
115 | |||
116 | /* | ||
117 | Function: timer_is_running | ||
118 | Return true if the timer is running (not stopped), false otherwise. | ||
119 | */ | ||
120 | char timer_is_running (const Timer*); | ||
121 | |||
122 | /* | ||
123 | Function: timer_sleep | ||
124 | Put the caller thread to sleep for the given number of seconds. | ||
125 | */ | ||
126 | void timer_sleep (float seconds); | ||
127 | |||
128 | #ifdef __cplusplus | ||
129 | } | ||
130 | #endif | ||
diff --git a/Spear/Sys/Timer/ctimer.c b/Spear/Sys/Timer/ctimer.c deleted file mode 100644 index 8c059c0..0000000 --- a/Spear/Sys/Timer/ctimer.c +++ /dev/null | |||
@@ -1,157 +0,0 @@ | |||
1 | #include "Timer.h" | ||
2 | #include <stdlib.h> | ||
3 | |||
4 | #ifdef __APPLE__ | ||
5 | #include <mach/mach_time.h> | ||
6 | #elif WIN32 | ||
7 | #define WIN32_LEAN_AND_MEAN | ||
8 | #include <Windows.h> | ||
9 | #else // Linux | ||
10 | #include <time.h> | ||
11 | const double NSEC_TO_SEC = 1.0 / 1000000000.0; | ||
12 | const double SEC_TO_NSECd = 1000000000.0; | ||
13 | const timeReading SEC_TO_NSEC = 1000000000; | ||
14 | #endif | ||
15 | |||
16 | static double secondsPerCount; | ||
17 | |||
18 | static void timer_initialise_subsystem () | ||
19 | { | ||
20 | #ifdef WIN32 | ||
21 | __int64 countsPerSec; | ||
22 | QueryPerformanceFrequency((LARGE_INTEGER*)&countsPerSec); | ||
23 | secondsPerCount = 1.0 / (double)countsPerSec; | ||
24 | #else | ||
25 | struct timespec ts; | ||
26 | clock_getres(CLOCK_REALTIME, &ts); | ||
27 | secondsPerCount = (double)ts.tv_sec + ((double)ts.tv_nsec * NSEC_TO_SEC); | ||
28 | #endif | ||
29 | } | ||
30 | |||
31 | static timeReading now () | ||
32 | { | ||
33 | timeReading t; | ||
34 | #ifdef __APPLE__ | ||
35 | t = mach_absolute_time(); | ||
36 | #elif WIN32 | ||
37 | QueryPerformanceCounter((LARGE_INTEGER*)&t); | ||
38 | #else | ||
39 | struct timespec ts; | ||
40 | clock_gettime(CLOCK_REALTIME, &ts); | ||
41 | t = ts.tv_sec*SEC_TO_NSEC + ts.tv_nsec; | ||
42 | #endif | ||
43 | return t; | ||
44 | } | ||
45 | |||
46 | void timer_init (Timer* timer) | ||
47 | { | ||
48 | timer_initialise_subsystem(); | ||
49 | timer_reset (timer); | ||
50 | } | ||
51 | |||
52 | void timer_tick (Timer* timer) | ||
53 | { | ||
54 | if (timer->stopped) | ||
55 | { | ||
56 | timer->deltaTime = 0.0; | ||
57 | return; | ||
58 | } | ||
59 | |||
60 | //Get the time on this frame. | ||
61 | timer->curTime = now(); | ||
62 | |||
63 | //Time delta between the current frame and the previous. | ||
64 | timer->deltaTime = (float) ((timer->curTime - timer->prevTime) * secondsPerCount); | ||
65 | |||
66 | //Update for next frame. | ||
67 | timer->prevTime = timer->curTime; | ||
68 | |||
69 | // Force nonnegative. The DXSDK's CDXUTTimer mentions that if the | ||
70 | // processor goes into a power save mode or we get shuffled to | ||
71 | // another processor, then the delta time can be negative. | ||
72 | if(timer->deltaTime < 0.0f) | ||
73 | { | ||
74 | timer->deltaTime = 0.0f; | ||
75 | } | ||
76 | } | ||
77 | |||
78 | void timer_reset (Timer* timer) | ||
79 | { | ||
80 | timeReading n = now(); | ||
81 | timer->baseTime = n; | ||
82 | timer->stopTime = n; | ||
83 | timer->prevTime = n; | ||
84 | timer->curTime = n; | ||
85 | timer->pausedTime = 0; | ||
86 | timer->deltaTime = 0.0f; | ||
87 | timer->stopped = 1; | ||
88 | } | ||
89 | |||
90 | void timer_stop (Timer* timer) | ||
91 | { | ||
92 | // Don't do anything if we are already stopped. | ||
93 | if (!timer->stopped) | ||
94 | { | ||
95 | // Grab the stop time. | ||
96 | timer->stopTime = now(); | ||
97 | |||
98 | // Now we are stopped. | ||
99 | timer->stopped = 1; | ||
100 | } | ||
101 | } | ||
102 | |||
103 | void timer_start (Timer* timer) | ||
104 | { | ||
105 | // Only start if we are stopped. | ||
106 | if (timer->stopped) | ||
107 | { | ||
108 | timeReading startTime = now(); | ||
109 | |||
110 | // Accumulate the paused time. | ||
111 | timer->pausedTime = timer->pausedTime + startTime - timer->stopTime; | ||
112 | |||
113 | // Make the previous time valid. | ||
114 | timer->prevTime = startTime; | ||
115 | |||
116 | //Now we are running. | ||
117 | timer->stopTime = 0; | ||
118 | timer->stopped = 0; | ||
119 | } | ||
120 | } | ||
121 | |||
122 | double timer_get_time (const Timer* timer) | ||
123 | { | ||
124 | // If we are stopped, we do not count the time we have been stopped for. | ||
125 | if (timer->stopped) | ||
126 | { | ||
127 | return (double)((timer->stopTime - timer->baseTime) * secondsPerCount); | ||
128 | } | ||
129 | // Otherwise return the time elapsed since the start but without | ||
130 | // taking into account the time we have been stopped for. | ||
131 | else | ||
132 | { | ||
133 | return (double)((timer->curTime - timer->baseTime - timer->pausedTime) * secondsPerCount); | ||
134 | } | ||
135 | } | ||
136 | |||
137 | float timer_get_delta (const Timer* timer) | ||
138 | { | ||
139 | return timer->deltaTime; | ||
140 | } | ||
141 | |||
142 | char timer_is_running (const Timer* timer) | ||
143 | { | ||
144 | return !timer->stopped; | ||
145 | } | ||
146 | |||
147 | void timer_sleep (float seconds) | ||
148 | { | ||
149 | #ifdef WIN32 | ||
150 | Sleep((DWORD)(seconds * 1000)); | ||
151 | #else | ||
152 | struct timespec ts; | ||
153 | ts.tv_sec = (int) seconds; | ||
154 | ts.tv_nsec = (long) ((double)(seconds - (int)seconds) * SEC_TO_NSECd); | ||
155 | nanosleep(&ts, NULL); | ||
156 | #endif | ||
157 | } | ||
diff --git a/Spear/Sys/Timer/timer.c b/Spear/Sys/Timer/timer.c new file mode 100644 index 0000000..8487f48 --- /dev/null +++ b/Spear/Sys/Timer/timer.c | |||
@@ -0,0 +1,101 @@ | |||
1 | #include "timer.h" | ||
2 | |||
3 | #include <stdlib.h> | ||
4 | #ifdef _WIN32 | ||
5 | #define WIN32_LEAN_AND_MEAN | ||
6 | #include <Windows.h> | ||
7 | #endif | ||
8 | |||
9 | #ifdef _WIN32 | ||
10 | static const int64_t microseconds = 1000000; | ||
11 | #endif | ||
12 | static const int64_t nanoseconds = 1000000000; | ||
13 | |||
14 | #ifdef _WIN32 | ||
15 | static double seconds_per_count; | ||
16 | #endif | ||
17 | |||
18 | static void timer_initialise() { | ||
19 | #ifdef _WIN32 | ||
20 | __int64 counts_per_sec; | ||
21 | QueryPerformanceFrequency((LARGE_INTEGER*)&counts_per_sec); | ||
22 | seconds_per_count = 1.0 / (double)counts_per_sec; | ||
23 | #endif | ||
24 | } | ||
25 | |||
26 | void timer_make(Timer* timer) { | ||
27 | timer_initialise(); | ||
28 | *timer = (Timer){0}; | ||
29 | timer_start(timer); | ||
30 | } | ||
31 | |||
32 | void timer_start(Timer* timer) { | ||
33 | time_now(&timer->start_time); | ||
34 | timer->last_tick = timer->start_time; | ||
35 | timer->running_time = 0; | ||
36 | timer->delta_time = 0; | ||
37 | } | ||
38 | |||
39 | void timer_tick(Timer* timer) { | ||
40 | time_point this_tick; | ||
41 | time_now(&this_tick); | ||
42 | timer->running_time = time_diff(&timer->start_time, &this_tick); | ||
43 | timer->delta_time = time_diff(&timer->last_tick, &this_tick); | ||
44 | timer->last_tick = this_tick; | ||
45 | } | ||
46 | |||
47 | void time_now(time_point* t) { | ||
48 | #ifdef _WIN32 | ||
49 | QueryPerformanceCounter((LARGE_INTEGER*)t); | ||
50 | #else | ||
51 | clock_gettime(CLOCK_REALTIME, t); | ||
52 | #endif | ||
53 | } | ||
54 | |||
55 | time_delta time_diff(time_point* start, time_point* end) { | ||
56 | #ifdef _WIN32 | ||
57 | // Force nonnegative. The DXSDK's CDXUTTimer mentions that if the | ||
58 | // processor goes into a power save mode or we get shuffled to | ||
59 | // another processor, then the delta time can be negative. | ||
60 | return std::max(0, *end - *start); | ||
61 | #else | ||
62 | return (end->tv_sec - start->tv_sec) * 1e9 + (end->tv_nsec - start->tv_nsec); | ||
63 | #endif | ||
64 | } | ||
65 | |||
66 | double time_delta_to_sec(time_delta dt) { | ||
67 | #ifdef _WIN32 | ||
68 | return (double)dt * seconds_per_count; | ||
69 | #else | ||
70 | return (double)dt * 1.0e-9; | ||
71 | #endif | ||
72 | } | ||
73 | |||
74 | time_delta sec_to_time_delta(double seconds) { | ||
75 | #ifdef _WIN32 | ||
76 | return (time_delta)(seconds / seconds_per_count); | ||
77 | #else | ||
78 | return (time_delta)(seconds * 1.0e9); | ||
79 | #endif | ||
80 | } | ||
81 | |||
82 | uint64_t time_point_to_ns(time_point* t) { | ||
83 | #ifdef _WIN32 | ||
84 | return (uint64_t)((double)*t * seconds_per_count * 1.0e+9); | ||
85 | #else | ||
86 | return (uint64_t)t->tv_sec * 1e+9 + (uint64_t)t->tv_nsec; | ||
87 | #endif | ||
88 | } | ||
89 | |||
90 | void time_sleep(time_delta dt) { | ||
91 | #ifdef _WIN32 | ||
92 | const int64_t ms = dt / microseconds; | ||
93 | Sleep((DWORD)(ms)); | ||
94 | #else | ||
95 | const int64_t sec = dt / nanoseconds; | ||
96 | struct timespec ts; | ||
97 | ts.tv_sec = (long)sec; | ||
98 | ts.tv_nsec = (long)(dt % nanoseconds); | ||
99 | nanosleep(&ts, NULL); | ||
100 | #endif | ||
101 | } | ||
diff --git a/Spear/Sys/Timer/timer.h b/Spear/Sys/Timer/timer.h new file mode 100644 index 0000000..e426135 --- /dev/null +++ b/Spear/Sys/Timer/timer.h | |||
@@ -0,0 +1,64 @@ | |||
1 | #pragma once | ||
2 | |||
3 | #include <stdint.h> | ||
4 | |||
5 | /// A particular point in time. | ||
6 | #ifdef _WIN32 | ||
7 | typedef uint64_t time_point; | ||
8 | #else | ||
9 | // Need to macro to make CLOCK_REALTIME available when compiling with ISO C11. | ||
10 | // The constant is only needed in the source file, but the header file needs to | ||
11 | // include time.h too. | ||
12 | #ifndef __USE_POSIX199309 | ||
13 | #define __USE_POSIX199309 | ||
14 | #endif // | ||
15 | #include <time.h> | ||
16 | typedef struct timespec time_point; | ||
17 | #endif | ||
18 | |||
19 | /// Time elapsed between two time points. | ||
20 | typedef uint64_t time_delta; | ||
21 | |||
22 | /// A high resolution timer. | ||
23 | typedef struct Timer { | ||
24 | time_point start_time; // The instant the timer was last started. | ||
25 | time_point last_tick; // The instant the timer was last ticked. | ||
26 | time_delta running_time; // Time elapsed since the timer was last started. | ||
27 | time_delta delta_time; // Time elapsed since the last tick. | ||
28 | } Timer; | ||
29 | |||
30 | /// Construct a new timer. | ||
31 | void timer_make(Timer*); | ||
32 | |||
33 | /// Start the timer. | ||
34 | /// This sets the time point from which time deltas are measured. | ||
35 | /// Calling this multilple times resets the timer. | ||
36 | void timer_start(Timer*); | ||
37 | |||
38 | /// Update the timer's running and delta times. | ||
39 | void timer_tick(Timer*); | ||
40 | |||
41 | /// Get the current time. | ||
42 | void time_now(time_point*); | ||
43 | |||
44 | /// Return the time elapsed between two timestamps. | ||
45 | time_delta time_diff(time_point* start, time_point* end); | ||
46 | |||
47 | /// Return the time elapsed in seconds. | ||
48 | double time_delta_to_sec(time_delta dt); | ||
49 | |||
50 | /// Convert the time elapsed in seconds to a time delta. | ||
51 | time_delta sec_to_time_delta(double seconds); | ||
52 | |||
53 | /// Convert the time point to nanoseconds. | ||
54 | uint64_t time_point_to_ns(time_point*); | ||
55 | |||
56 | /// Put the caller thread to sleep for the given amount of time. | ||
57 | void time_sleep(time_delta dt); | ||
58 | |||
59 | /// The time point 0. | ||
60 | #ifdef _WIN32 | ||
61 | static const time_point time_zero = 0; | ||
62 | #else | ||
63 | static const time_point time_zero = {0, 0}; | ||
64 | #endif | ||