openMSX
Timer.cc
Go to the documentation of this file.
1 #include "Timer.hh"
2 #include "systemfuncs.hh"
3 #if HAVE_USLEEP
4 #include <unistdp.hh>
5 #endif
6 #include <chrono>
7 #include <SDL.h>
8 
9 namespace openmsx {
10 namespace Timer {
11 
12 // non-static to avoid unused function warning
13 inline uint64_t getSDLTicks()
14 {
15  return static_cast<uint64_t>(SDL_GetTicks()) * 1000;
16 }
17 
18 uint64_t getTime()
19 {
20  static uint64_t lastTime = 0;
21  uint64_t now;
22 
23 #ifndef _MSC_VER
24  using namespace std::chrono;
25  now = duration_cast<microseconds>(
26  steady_clock::now().time_since_epoch()).count();
27 #else
28  // Visual studio 2012 does offer std::chrono, but unfortunately it's
29  // buggy and low resolution. So for now we still use SDL. See also:
30  // http://stackoverflow.com/questions/11488075/vs11-is-steady-clock-steady
31  // https://connect.microsoft.com/VisualStudio/feedback/details/753115/
32  now = static_cast<uint64_t>(SDL_GetTicks()) * 1000;
33 #endif
34 
35  // Other parts of openMSX may crash if this function ever returns a
36  // value that is less than a previously returned value. Hence this
37  // extra check.
38  // SDL_GetTicks() is not guaranteed to return monotonic values.
39  // steady_clock OTOH should be monotonic. It's implemented in terms of
40  // clock_gettime(CLOCK_MONOTONIC). Unfortunately in older linux
41  // versions we've seen buggy implementation that once in a while did
42  // return time points slightly in the past.
43  if (now < lastTime) return lastTime;
44  lastTime = now;
45  return now;
46 }
47 
48 /*#if defined _WIN32
49 static void CALLBACK timerCallback(unsigned int,
50  unsigned int,
51  unsigned long eventHandle,
52  unsigned long,
53  unsigned long)
54 {
55  SetEvent((HANDLE)eventHandle);
56 }
57 #endif*/
58 
59 void sleep(uint64_t us)
60 {
61 /*#if defined _WIN32
62  us /= 1000;
63  if (us > 0) {
64  static HANDLE timerEvent = nullptr;
65  if (!timerEvent) {
66  timerEvent = CreateEvent(nullptr, FALSE, FALSE, nullptr);
67  }
68  UINT id = timeSetEvent(us, 1, timerCallback, (DWORD)timerEvent,
69  TIME_ONESHOT);
70  WaitForSingleObject(timerEvent, INFINITE);
71  timeKillEvent(id);
72  }
73 */
74 #if HAVE_USLEEP
75  usleep(us);
76 #else
77  SDL_Delay(unsigned(us / 1000));
78 #endif
79 }
80 
81 } // namespace Timer
82 } // namespace openmsx
uint64_t getSDLTicks()
Definition: Timer.cc:13
Thanks to enen for testing this on a real cartridge:
Definition: Autofire.cc:5
void sleep(uint64_t us)
Sleep for the specified amount of time (in us).
Definition: Timer.cc:59
uint64_t getTime()
Get current (real) time in us.
Definition: Timer.cc:18