@@ -190,120 +190,125 @@ impl<Clock: crate::Clock, Dur: Duration> Timer<Periodic, Running, Clock, Dur> {
190
190
}
191
191
192
192
#[ cfg( test) ]
193
+ #[ allow( unused_imports) ]
194
+ #[ allow( unsafe_code) ]
193
195
mod test {
194
- #![ allow( unsafe_code) ]
195
-
196
196
use crate :: { units:: * , Clock as _, Duration , Instant , Period , TimeInt } ;
197
197
use std:: convert:: TryFrom ;
198
+ use std:: sync:: atomic:: { AtomicI64 , Ordering } ;
199
+ use std:: thread;
198
200
199
201
#[ derive( Debug , Ord , PartialOrd , Eq , PartialEq ) ]
200
202
struct Clock ;
201
203
202
- static mut START : Option < std :: time :: Instant > = None ;
204
+ static TICKS : AtomicI64 = AtomicI64 :: new ( 0 ) ;
203
205
204
206
impl crate :: Clock for Clock {
205
207
type Rep = i64 ;
206
- const PERIOD : Period = Period :: new ( 1 , 64_000_000 ) ;
208
+ const PERIOD : Period = Period :: new ( 1 , 1_000 ) ;
207
209
208
210
fn now ( ) -> Instant < Self > {
209
- let since_start = unsafe { START . unwrap ( ) } . elapsed ( ) ;
210
- let ticks = Nanoseconds :: < i64 > :: try_from ( since_start)
211
- . unwrap ( )
212
- . into_ticks ( Self :: PERIOD )
213
- . unwrap ( ) ;
214
- Instant :: new ( ticks)
215
- }
216
- }
217
-
218
- fn init_start_time ( ) {
219
- unsafe {
220
- START = Some ( std:: time:: Instant :: now ( ) ) ;
211
+ Instant :: new ( TICKS . load ( Ordering :: Acquire ) )
221
212
}
222
213
}
223
214
224
215
#[ test]
225
216
fn oneshot_wait ( ) {
226
- init_start_time ( ) ;
217
+ init_ticks ( ) ;
227
218
228
- // WHEN blocking on a timer
229
- let timer = Clock :: new_timer ( ) . set_duration ( 1 . seconds ( ) ) . start ( ) . wait ( ) ;
219
+ let timer = Clock :: new_timer ( ) . set_duration ( 1 . seconds ( ) ) . start ( ) ;
220
+ let timer_handle = thread :: spawn ( move || timer . wait ( ) ) ;
230
221
231
- // THEN the block occurs for _at least_ the given duration
232
- unsafe {
233
- assert ! ( Seconds :: <i32 >:: try_from( START . unwrap( ) . elapsed( ) ) . unwrap( ) >= 1 . seconds( ) ) ;
234
- }
222
+ add_to_ticks ( 1 . seconds ( ) ) ;
235
223
236
- // WHEN blocking on a timer
237
- timer. start ( ) . wait ( ) ;
224
+ let result = timer_handle. join ( ) ;
238
225
239
- // THEN the block occurs for _at least_ the given duration
240
- unsafe {
241
- assert ! ( Seconds :: <i32 >:: try_from( START . unwrap( ) . elapsed( ) ) . unwrap( ) >= 2 . seconds( ) ) ;
242
- }
226
+ assert ! ( result. is_ok( ) ) ;
227
+
228
+ let timer = result. unwrap ( ) . start ( ) ;
229
+ let timer_handle = thread:: spawn ( move || timer. wait ( ) ) ;
230
+
231
+ add_to_ticks ( 1 . seconds ( ) ) ;
232
+
233
+ assert ! ( timer_handle. join( ) . is_ok( ) ) ;
243
234
}
244
235
245
236
#[ test]
246
237
fn periodic_wait ( ) {
247
- init_start_time ( ) ;
238
+ init_ticks ( ) ;
248
239
249
240
let timer = Clock :: new_timer ( )
250
241
. into_periodic ( )
251
242
. set_duration ( 1 . seconds ( ) )
252
- . start ( )
253
- . wait ( ) ;
243
+ . start ( ) ;
244
+ let timer_handle = thread :: spawn ( move || timer . wait ( ) ) ;
254
245
255
- unsafe {
256
- assert ! ( Seconds :: <i32 >:: try_from( START . unwrap( ) . elapsed( ) ) . unwrap( ) == 1 . seconds( ) ) ;
257
- }
246
+ add_to_ticks ( 1 . seconds ( ) ) ;
258
247
259
- let timer = timer. wait ( ) ;
260
- unsafe {
261
- assert ! ( Seconds :: <i32 >:: try_from( START . unwrap( ) . elapsed( ) ) . unwrap( ) == 2 . seconds( ) ) ;
262
- }
248
+ let result = timer_handle. join ( ) ;
263
249
264
- timer. wait ( ) ;
265
- unsafe {
266
- assert ! ( Seconds :: <i32 >:: try_from( START . unwrap( ) . elapsed( ) ) . unwrap( ) == 3 . seconds( ) ) ;
267
- }
250
+ assert ! ( result. is_ok( ) ) ;
251
+
252
+ let timer = result. unwrap ( ) ;
253
+
254
+ // WHEN blocking on a timer
255
+ let timer_handle = thread:: spawn ( move || timer. wait ( ) ) ;
256
+
257
+ add_to_ticks ( 1 . seconds ( ) ) ;
258
+
259
+ assert ! ( timer_handle. join( ) . is_ok( ) ) ;
268
260
}
269
261
270
262
#[ test]
271
263
fn periodic_expiration ( ) {
272
- init_start_time ( ) ;
264
+ init_ticks ( ) ;
273
265
274
266
let mut timer = Clock :: new_timer ( )
275
267
. into_periodic ( )
276
268
. set_duration ( 1 . seconds ( ) )
277
269
. start ( ) ;
278
270
279
- std :: thread :: sleep ( std :: time :: Duration :: from_secs ( 2 ) ) ;
271
+ add_to_ticks ( 2 . seconds ( ) ) ;
280
272
281
273
assert ! ( timer. period_complete( ) ) ;
282
274
assert ! ( timer. period_complete( ) ) ;
283
275
}
284
276
285
277
#[ test]
286
278
fn read_timer ( ) {
287
- init_start_time ( ) ;
279
+ init_ticks ( ) ;
288
280
289
281
let timer = Clock :: new_timer ( ) . set_duration ( 2 . seconds ( ) ) . start ( ) ;
290
282
283
+ add_to_ticks ( 1 . milliseconds ( ) ) ;
284
+
291
285
assert_eq ! ( timer. elapsed( ) , 0 . seconds( ) ) ;
292
286
assert_eq ! ( timer. remaining( ) , 1 . seconds( ) ) ;
293
287
294
- std :: thread :: sleep ( std :: time :: Duration :: from_secs ( 1 ) ) ;
288
+ add_to_ticks ( 1 . seconds ( ) ) ;
295
289
296
290
assert_eq ! ( timer. elapsed( ) , 1 . seconds( ) ) ;
297
291
assert_eq ! ( timer. remaining( ) , 0 . seconds( ) ) ;
298
292
299
- std :: thread :: sleep ( std :: time :: Duration :: from_secs ( 1 ) ) ;
293
+ add_to_ticks ( 1 . seconds ( ) ) ;
300
294
301
295
assert_eq ! ( timer. elapsed( ) , 2 . seconds( ) ) ;
302
296
assert_eq ! ( timer. remaining( ) , ( 0 ) . seconds( ) ) ;
303
297
304
- std :: thread :: sleep ( std :: time :: Duration :: from_secs ( 1 ) ) ;
298
+ add_to_ticks ( 1 . seconds ( ) ) ;
305
299
306
300
assert_eq ! ( timer. elapsed( ) , 3 . seconds( ) ) ;
307
301
assert_eq ! ( timer. remaining( ) , ( -1 ) . seconds( ) ) ;
308
302
}
303
+
304
+ fn init_ticks ( ) { }
305
+
306
+ fn add_to_ticks < Dur : Duration > ( duration : Dur ) {
307
+ let ticks = TICKS . load ( Ordering :: Acquire ) ;
308
+ let ticks = ticks
309
+ + duration
310
+ . into_ticks :: < <Clock as crate :: Clock >:: Rep > ( Clock :: PERIOD )
311
+ . unwrap ( ) ;
312
+ TICKS . store ( ticks, Ordering :: Release ) ;
313
+ }
309
314
}
0 commit comments