PEBL 2.2
Psychology Experiment Building Language - Cross-platform psychological experiment development system
sdl/PlatformTimer.cpp
Go to the documentation of this file.
1//* -*- mode:C++; tab-width:4; c-basic-offset:4; indent-tabs-mode:nil -*- */
3// Name: src/platforms/sdl/PlatformTimer.cpp
4// Purpose: SDL-specific timer event device
5// Author: Shane T. Mueller, Ph.D.
6// Copyright: (c) 2003-2026 Shane T. Mueller <smueller@obereed.net>
7// License: GPL 2
8//
9//
10//
11// This file is part of the PEBL project.
12//
13// PEBL is free software; you can redistribute it and/or modify
14// it under the terms of the GNU General Public License as published by
15// the Free Software Foundation; either version 2 of the License, or
16// (at your option) any later version.
17//
18// PEBL is distributed in the hope that it will be useful,
19// but WITHOUT ANY WARRANTY; without even the implied warranty of
20// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21// GNU General Public License for more details.
22//
23// You should have received a copy of the GNU General Public License
24// along with PEBL; if not, write to the Free Software
25// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27#if defined(PEBL_WIN32) || defined(PEBL_WINDOWS)
28#include <winsock2.h> // Must be first to avoid conflicts
29#endif
30
31#include "PlatformTimer.h"
32#include "SDL.h"
33#include <iostream>
34#include "../../devices/DeviceState.h"
35
36#ifdef PEBL_EMSCRIPTEN
37#include <emscripten.h>
38#endif
39
40#include <sys/time.h>
41#if defined(PEBL_UNIX) || defined(PEBL_EMSCRIPTEN)
42
43//Nothing special here
44
45#elif defined(PEBL_WIN32) || defined(PEBL_WINDOWS)
46 #include <windows.h>
47 #include <iostream>
48 #include <iomanip>
49 #include <stdio.h>
50#endif
51
52#undef PEBL_CHECKTIMER
53
54using namespace std;
55
61
64{
65 // Standard Destructor
66}
67
68
69
70
71// The following function is not used anymore.
72//
73void PlatformTimer::Wait(unsigned long int msecs)
74 //This does a busy wait; could be augmented with interrupts or RTC calls if necessary.
75 //Both version should be nearly identical--all the ifdefs makes it really difficult
76 //to understand inline, so I just replicated the function.
77#ifdef PEBL_CHECKTIMER
78{
80
81 //This should check for wrapping at ~49 days.
82
83 unsigned long int timeX = SDL_GetTicks() + msecs;
84 unsigned long int missedticks = 0;
85 unsigned long int missedms = 0;
86 unsigned long int lasttime = 0;
87
88 unsigned long int time=SDL_GetTicks();
89
90 while(true)
91 {
92 lasttime = time;
93
94 time = SDL_GetTicks();
95 if((time-lasttime) > 1)
96 {
97 missedticks++;
98 missedms += (time-lasttime);
99 }
100
101
102 if(time > timeX)
103 {
104
105 cerr << "Timer missed [" << missedticks << "] ticks, for a total of [" << missedms << "] ms, on a wait of [" << msecs <<"] ms.\n";
106 break;
107 }
108 }
109}
110#else
111{
112 //This does a busy wait; could be augmented with interrupts or RTC calls if necessary.
113 //This should check for wrapping at ~49 days.
114
115 unsigned long int timeX = SDL_GetTicks() + msecs;
116 unsigned long int time;
117
118 while(true)
119 {
120 time = SDL_GetTicks();
121 if(time > timeX)
122 break;
123
124 }
125}
126
127#endif
128
129
132void PlatformTimer::Sleep(unsigned long int msecs)
133{
134#ifdef PEBL_EMSCRIPTEN
135 // Emscripten: yield to browser to allow browser events to be processed
136 emscripten_sleep(msecs);
137#elif defined(PEBL_UNIX)
138 // Unix/Linux: nanosleep (high precision, yields CPU)
139 struct timespec a, b;
140 a.tv_sec = msecs / 1000;
141 a.tv_nsec = (msecs % 1000) * 1000000; // Convert remaining ms to nanoseconds
142 nanosleep(&a, &b);
143#elif defined(PEBL_WIN32) || defined(PEBL_WINDOWS)
144 // Windows: SDL_Delay (yields CPU, ~1ms precision)
145 SDL_Delay(msecs);
146#else
147 // Fallback: use SDL_Delay on unknown platforms
148 SDL_Delay(msecs);
149#endif
150}
151
152
153unsigned long int PlatformTimer::GetTime() const
154{
155 return SDL_GetTicks();
156}
157
158int PlatformTimer::GetState(int iface) const
159{
160 //There is no interface for the timer.
161 return SDL_GetTicks();
162}
163
164// int PlatformTimer::TestDevice(const DeviceState & state) const
165// {
166// int time = GetTime();
167// int result = state.TestDevice(time);
168// return result;
169// }
170
171void PlatformTimer::GetTimeOfDay(unsigned long & secs, unsigned long & msecs)
172{
173#if defined( PEBL_UNIX) || defined(PEBL_EMSCRIPTEN)
174 struct timeval * tp=NULL;
175 gettimeofday(tp,NULL);
176
177 time_t secs1 = tp->tv_sec;
178 suseconds_t usecs = tp->tv_usec;
179
180 secs = secs1;
181 msecs = usecs/100;
182#else
183
184 SYSTEMTIME st;
185 ::GetSystemTime(&st);
186
187
188 std::cerr << std::setw(2) << st.wHour << ':'
189 << std::setw(2) << st.wMinute << ':'
190 << std::setw(2) << st.wSecond << '.'
191 << std::setw(3) << st.wMilliseconds << '\n';
192
193// return timeGetTime();
194#endif
195}
196
197
198ostream & PlatformTimer::SendToStream(ostream & out) const
199{
200 out << "<SDL Platform Timer>" << std::flush;
201 return out;
202}
#define NULL
Definition BinReloc.cpp:317
virtual void Sleep(unsigned long int msecs)
virtual void GetTimeOfDay(unsigned long &secs, unsigned long &msecs)
PlatformTimer()
The Standard constructor.
virtual void Wait(unsigned long int msecs)
virtual unsigned long int GetTime() const
virtual int GetState(int iface) const
virtual ~PlatformTimer()
The Standard destructor.