aboutsummaryrefslogtreecommitdiff
path: root/Spear/Sys/Timer
diff options
context:
space:
mode:
Diffstat (limited to 'Spear/Sys/Timer')
-rw-r--r--Spear/Sys/Timer/Timer.h130
-rw-r--r--Spear/Sys/Timer/ctimer.c157
-rw-r--r--Spear/Sys/Timer/timer.c101
-rw-r--r--Spear/Sys/Timer/timer.h64
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
5typedef __int64 timeReading;
6#else
7typedef __UINT64_TYPE__ timeReading;
8#endif
9#else
10typedef __UINT64_TYPE__ timeReading;
11#endif
12
13#ifdef __cplusplus
14extern "C" {
15#endif
16
17/*
18 Header: Timer
19 A high resolution timer module.
20*/
21
22/*
23 Struct: Timer
24*/
25typedef 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*/
49void 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*/
61void 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*/
73void 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*/
85void 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*/
98void 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*/
107double 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*/
114float 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*/
120char 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*/
126void 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
16static double secondsPerCount;
17
18static 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
31static 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
46void timer_init (Timer* timer)
47{
48 timer_initialise_subsystem();
49 timer_reset (timer);
50}
51
52void 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
78void 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
90void 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
103void 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
122double 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
137float timer_get_delta (const Timer* timer)
138{
139 return timer->deltaTime;
140}
141
142char timer_is_running (const Timer* timer)
143{
144 return !timer->stopped;
145}
146
147void 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
10static const int64_t microseconds = 1000000;
11#endif
12static const int64_t nanoseconds = 1000000000;
13
14#ifdef _WIN32
15static double seconds_per_count;
16#endif
17
18static 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
26void timer_make(Timer* timer) {
27 timer_initialise();
28 *timer = (Timer){0};
29 timer_start(timer);
30}
31
32void 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
39void 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
47void 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
55time_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
66double 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
74time_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
82uint64_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
90void 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
7typedef 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>
16typedef struct timespec time_point;
17#endif
18
19/// Time elapsed between two time points.
20typedef uint64_t time_delta;
21
22/// A high resolution timer.
23typedef 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.
31void 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.
36void timer_start(Timer*);
37
38/// Update the timer's running and delta times.
39void timer_tick(Timer*);
40
41/// Get the current time.
42void time_now(time_point*);
43
44/// Return the time elapsed between two timestamps.
45time_delta time_diff(time_point* start, time_point* end);
46
47/// Return the time elapsed in seconds.
48double time_delta_to_sec(time_delta dt);
49
50/// Convert the time elapsed in seconds to a time delta.
51time_delta sec_to_time_delta(double seconds);
52
53/// Convert the time point to nanoseconds.
54uint64_t time_point_to_ns(time_point*);
55
56/// Put the caller thread to sleep for the given amount of time.
57void time_sleep(time_delta dt);
58
59/// The time point 0.
60#ifdef _WIN32
61static const time_point time_zero = 0;
62#else
63static const time_point time_zero = {0, 0};
64#endif