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 | ||
