-
Notifications
You must be signed in to change notification settings - Fork 25
Expand file tree
/
Copy pathmac_rate.cpp
More file actions
118 lines (100 loc) · 2.21 KB
/
Copy pathmac_rate.cpp
File metadata and controls
118 lines (100 loc) · 2.21 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
#include "util/rate.hpp"
#if defined(_WIN32)
#include "win32/timeval.h"
#else
#include <sys/time.h>
#include <time.h>
#endif
#include <math.h>
#include <unistd.h>
#include <stdexcept>
namespace cvisual {
namespace {
struct timeval : ::timeval
{
// Convert to straight usec.
operator long long() const
{
return tv_sec * 1000000 + tv_usec;
}
};
struct timespec : ::timespec
{
timespec()
{
tv_sec = 0;
tv_nsec = 0;
}
// Convert from usec.
timespec( long long t)
{
tv_sec = t / 1000000;
tv_nsec = t % 1000000 * 1000;
}
};
// Parts of the rate_timer common to both the OSX and Linux implementations.
class rate_timer
{
private:
timeval origin;
public:
rate_timer()
{
timerclear( &origin);
gettimeofday( &origin, 0);
}
// Force the loop to run in 'sec' seconds by inserting the appropriate delay.
void delay( double sec);
};
void
rate_timer::delay( double _delay)
{
timeval now;
timerclear(&now);
gettimeofday( &now, 0);
// Convert the requested delay into integer units of usec.
const long long delay = (long long)(_delay * 1e6);
long long origin = this->origin;
// The amount of time to wait.
long long wait = delay - ((long long)now - origin);
if (wait < 0) {
gettimeofday( &this->origin, 0);
return;
}
// The amout of time remaining when nanosleep returns
timespec remaining;
#ifdef __APPLE__ // OSX.
// OSX's nanosleep() is very accurate :)
timespec sleep_wait( wait);
nanosleep( &sleep_wait, &remaining);
#else
// Computation of the requested delay is the same, but the execution differs
// from OSX. This is to provide somewhat more accurate timing on Linux,
// whose timing is abominable.
if (wait > 2000) {
timespec sleep_wait(wait);
nanosleep( &sleep_wait, &remaining);
}
else {
// Busy wait out the remainder of the time.
while (wait > 0) {
sched_yield();
gettimeofday( &now, 0);
wait = delay - ((long long)now - origin);
}
}
#endif // !defined __APPLE__
gettimeofday( &this->origin, 0);
}
} // !namespace (unnamed)
void
rate( const double& freq)
{
static rate_timer* rt = 0;
if (!rt)
rt = new rate_timer();
if (freq <= 0.0)
throw std::invalid_argument( "Rate must be positive and nonzero.");
rt->delay( 1.0/freq );
}
} // !namespace cvisual