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
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
use clock::Clock;
#[cfg(any(target_os = "linux", target_os = "macos", target_os = "android"))]
mod ffi {
use Clock;
type LazyPointer = usize;
pub struct Timer {
timeout: f32,
clock: Clock,
ticks: f32,
}
#[repr(C)]
#[derive(Copy, Clone)]
pub struct TimeVal {
sec: isize,
usec: isize,
}
extern {
fn nanosleep(req: *const TimeVal, rem: LazyPointer) -> i32;
}
impl Timer {
pub fn create(secs: f32) -> Timer {
Timer{ timeout:secs, ticks:secs, clock:Clock::create() }
}
pub fn wait(&mut self) -> () {
let passed = self.clock.since();
let delay = self.ticks - passed;
if delay > 0.0 {
let fsec = delay as isize;
let usec = ((delay % 1.0) * 1_000_000_000.0)
as isize;
let timeout = TimeVal { sec: fsec, usec: usec };
unsafe {
nanosleep(&timeout, 0);
}
}
self.ticks += self.timeout;
}
}
}
#[cfg(target_os = "windows")]
mod ffi {
type Handle = usize;
type LazyPointer = usize;
type Bool = i32;
type Long = i32;
type DWord = u32;
pub struct Timer {
timer: Handle,
}
#[repr(C)]
pub struct LargeInt {
a: i64,
b: i64,
}
#[link(name = "winmm")]
#[link(name = "gdi32")]
extern "system" {
fn CreateWaitableTimerW(timer_attrib: LazyPointer,
manual_reset: Bool, name: LazyPointer) -> Handle;
fn SetWaitableTimer(timer: Handle, due_time: *const LargeInt,
period: Long, routine: LazyPointer, crarg: LazyPointer,
resume: Bool) -> Bool;
fn WaitForSingleObject(timer: Handle, ms: DWord) -> DWord;
fn CloseHandle(timer: Handle) -> Bool;
}
#[cfg(feature = "checks")]
fn checks(timer: Handle) -> () {
if timer == 0 {
panic!("Failed to create Timer.");
} else {
println!("Successfully created Timer.");
}
}
#[cfg(not(feature = "checks"))]
fn checks(_: Handle) {}
impl Timer {
pub fn create(secs: f32) -> Timer {
let timer = unsafe { CreateWaitableTimerW(0, 0, 0) };
checks(timer);
let time = (secs * -10000000.0) as i64;
let millis = (secs * 1000.0) as Long;
let time = LargeInt { a: time, b: time };
let r = unsafe { SetWaitableTimer(timer, &time, millis, 0, 0, 0) };
if r != 1 {
panic!("Timer: Failed to create.");
}
Timer { timer: timer }
}
pub fn wait(&self) -> () {
unsafe { WaitForSingleObject(self.timer, 0xffffffff); }
}
}
impl Drop for Timer {
fn drop(&mut self) {
unsafe { CloseHandle(self.timer); }
}
}
}
pub struct Timer {
timer: ffi::Timer,
clock: Clock,
}
impl Timer {
pub fn create(secs: f32) -> Timer {
Timer{ timer: ffi::Timer::create(secs), clock: Clock::create() }
}
pub fn wait(&mut self) -> f32 {
self.timer.wait();
self.clock.since()
}
pub fn sleep(secs: f32) -> f32 {
Timer::create(secs).wait()
}
}