@@ -18,9 +18,11 @@ and create receivers which will receive notifications after a period of time.
18
18
*/
19
19
20
20
use comm:: { Receiver , Sender , channel} ;
21
+ use time:: Duration ;
21
22
use io:: { IoResult , IoError } ;
22
23
use kinds:: Send ;
23
24
use boxed:: Box ;
25
+ use num:: { CheckedMul , CheckedAdd } ;
24
26
use rt:: rtio:: { IoFactory , LocalIo , RtioTimer , Callback } ;
25
27
26
28
/// A synchronous timer object
@@ -69,6 +71,33 @@ pub struct Timer {
69
71
70
72
struct TimerCallback { tx : Sender < ( ) > }
71
73
74
+ #[ allow( missing_doc) ]
75
+ trait DurationExtension {
76
+ fn in_ms ( & self ) -> u64 ;
77
+ }
78
+
79
+ impl DurationExtension for Duration {
80
+ fn in_ms ( & self ) -> u64 {
81
+ if self . ndays ( ) < 0 { fail ! ( "negative duration" ) }
82
+ let nanos = self . nnanoseconds ( ) as u64 ;
83
+ let secs = self . nseconds ( ) as u64 ;
84
+ let days = self . ndays ( ) as u64 ;
85
+ let nanos_in_ms = nanos / 1000 ;
86
+ let secs_in_ms = secs. checked_mul ( & 1000 ) . expect ( "overflow" ) ;
87
+ let ms_per_day = 24 * 60 * 60 * 1000 ; // hours/day * min/hour * sec/min * ms/sec
88
+ let days_in_ms = days. checked_mul ( & ms_per_day) . expect ( "overflow" ) ;
89
+ let result = nanos_in_ms;
90
+ let result = result. checked_add ( & secs_in_ms) . expect ( "overflow" ) ;
91
+ let result = result. checked_add ( & ( days_in_ms as u64 ) ) . expect ( "overflow" ) ;
92
+ return result;
93
+ }
94
+ }
95
+
96
+ /// Sleep the current task for the specified duration.
97
+ pub fn sleep ( duration : Duration ) {
98
+ sleep_ms ( duration. in_ms ( ) )
99
+ }
100
+
72
101
/// Sleep the current task for `msecs` milliseconds.
73
102
pub fn sleep_ms ( msecs : u64 ) {
74
103
let timer = Timer :: new ( ) ;
@@ -87,6 +116,14 @@ impl Timer {
87
116
} ) . map_err ( IoError :: from_rtio_error)
88
117
}
89
118
119
+ /// Blocks the current task for the specified duration.
120
+ ///
121
+ /// Note that this function will cause any other receivers for this timer to
122
+ /// be invalidated (the other end will be closed).
123
+ pub fn sleep ( & mut self , duration : Duration ) {
124
+ self . obj . sleep ( duration. in_ms ( ) ) ;
125
+ }
126
+
90
127
/// Blocks the current task for `msecs` milliseconds.
91
128
///
92
129
/// Note that this function will cause any other receivers for this timer to
@@ -95,6 +132,23 @@ impl Timer {
95
132
self . obj . sleep ( msecs) ;
96
133
}
97
134
135
+ /// Creates a oneshot receiver which will have a notification sent when
136
+ /// the specified duration has elapsed.
137
+ ///
138
+ /// This does *not* block the current task, but instead returns immediately.
139
+ ///
140
+ /// Note that this invalidates any previous receiver which has been created
141
+ /// by this timer, and that the returned receiver will be invalidated once
142
+ /// the timer is destroyed (when it falls out of scope). In particular, if
143
+ /// this is called in method-chaining style, the receiver will be
144
+ /// invalidated at the end of that statement, and all `recv` calls will
145
+ /// fail.
146
+ pub fn oneshot ( & mut self , duration : Duration ) -> Receiver < ( ) > {
147
+ let ( tx, rx) = channel ( ) ;
148
+ self . obj . oneshot ( duration. in_ms ( ) , box TimerCallback { tx : tx } ) ;
149
+ return rx
150
+ }
151
+
98
152
/// Creates a oneshot receiver which will have a notification sent when
99
153
/// `msecs` milliseconds has elapsed.
100
154
///
@@ -135,6 +189,25 @@ impl Timer {
135
189
return rx
136
190
}
137
191
192
+ /// Creates a receiver which will have a continuous stream of notifications
193
+ /// being sent each time the specified duration has elapsed.
194
+ ///
195
+ /// This does *not* block the current task, but instead returns
196
+ /// immediately. The first notification will not be received immediately,
197
+ /// but rather after the first duration.
198
+ ///
199
+ /// Note that this invalidates any previous receiver which has been created
200
+ /// by this timer, and that the returned receiver will be invalidated once
201
+ /// the timer is destroyed (when it falls out of scope). In particular, if
202
+ /// this is called in method-chaining style, the receiver will be
203
+ /// invalidated at the end of that statement, and all `recv` calls will
204
+ /// fail.
205
+ pub fn periodic ( & mut self , duration : Duration ) -> Receiver < ( ) > {
206
+ let ( tx, rx) = channel ( ) ;
207
+ self . obj . period ( duration. in_ms ( ) , box TimerCallback { tx : tx } ) ;
208
+ return rx
209
+ }
210
+
138
211
/// Creates a receiver which will have a continuous stream of notifications
139
212
/// being sent every `msecs` milliseconds.
140
213
///
@@ -365,4 +438,28 @@ mod test {
365
438
// callback do something terrible.
366
439
timer2. sleep_ms( 2 ) ;
367
440
} )
441
+
442
+
443
+ iotest ! ( fn test_io_timer_sleep_duration_simple( ) {
444
+ use time:: Duration ;
445
+ let mut timer = Timer :: new( ) . unwrap( ) ;
446
+ timer. sleep( Duration :: seconds( 1 ) ) ;
447
+ } )
448
+
449
+ iotest ! ( fn test_io_timer_sleep_oneshot_duration( ) {
450
+ use time:: Duration ;
451
+ let mut timer = Timer :: new( ) . unwrap( ) ;
452
+ timer. oneshot( Duration :: seconds( 1 ) ) . recv( ) ;
453
+ } )
454
+
455
+ iotest ! ( fn test_io_timer_sleep_periodic_duration( ) {
456
+ use time:: Duration ;
457
+ let mut timer = Timer :: new( ) . unwrap( ) ;
458
+ let rx = timer. periodic( Duration :: seconds( 1 ) ) ;
459
+ rx. recv( ) ;
460
+ rx. recv( ) ;
461
+ rx. recv( ) ;
462
+ } )
463
+
464
+
368
465
}
0 commit comments