@@ -3,7 +3,7 @@ Utilities that leverage libuv's `uv_timer_*` API
3
3
" ] ;
4
4
5
5
import uv = uv;
6
- export delayed_send, sleep;
6
+ export delayed_send, sleep, recv_timeout ;
7
7
8
8
#[ doc = "
9
9
Wait for timeout period then send provided value over a channel
@@ -16,9 +16,9 @@ for *at least* that period of time.
16
16
17
17
# Arguments
18
18
19
- msecs - a timeout period, in milliseconds, to wait
20
- ch - a channel of type T to send a `val` on
21
- val - a value of type T to send over the provided `ch`
19
+ * msecs - a timeout period, in milliseconds, to wait
20
+ * ch - a channel of type T to send a `val` on
21
+ * val - a value of type T to send over the provided `ch`
22
22
" ]
23
23
fn delayed_send < T : send > ( msecs : uint , ch : comm:: chan < T > , val : T ) {
24
24
task:: spawn ( ) { ||
@@ -80,6 +80,39 @@ fn sleep(msecs: uint) {
80
80
comm:: recv ( exit_po) ;
81
81
}
82
82
83
+ #[ doc = "
84
+ Receive on a port for (up to) a specified time, then return an `option<T>`
85
+
86
+ This call will block to receive on the provided port for up to the specified
87
+ timeout. Depending on whether the provided port receives in that time period,
88
+ `recv_timeout` will return an `option<T>` representing the result.
89
+
90
+ # Arguments
91
+
92
+ * msecs - an mount of time, in milliseconds, to wait to receive
93
+ * wait_port - a `comm::port<T>` to receive on
94
+
95
+ # Returns
96
+
97
+ An `option<T>` representing the outcome of the call. If the call `recv`'d on
98
+ the provided port in the allotted timeout period, then the result will be a
99
+ `some(T)`. If not, then `none` will be returned.
100
+ " ]
101
+ fn recv_timeout < T : send > ( msecs : uint , wait_po : comm:: port < T > ) -> option < T > {
102
+ let timeout_po = comm:: port :: < ( ) > ( ) ;
103
+ let timeout_ch = comm:: chan ( timeout_po) ;
104
+ delayed_send ( msecs, timeout_ch, ( ) ) ;
105
+ either:: either (
106
+ { |left_val|
107
+ log ( debug, #fmt ( "recv_time .. left_val %?" ,
108
+ left_val) ) ;
109
+ none
110
+ } , { |right_val|
111
+ some ( right_val)
112
+ } , comm:: select2 ( timeout_po, wait_po)
113
+ )
114
+ }
115
+
83
116
// INTERNAL API
84
117
crust fn delayed_send_cb ( handle : * uv:: ll:: uv_timer_t ,
85
118
status : libc:: c_int ) unsafe {
@@ -108,6 +141,43 @@ crust fn delayed_send_close_cb(handle: *uv::ll::uv_timer_t) unsafe {
108
141
mod test {
109
142
#[ test]
110
143
fn test_timer_simple_sleep_test ( ) {
111
- sleep ( 2000 u) ;
144
+ sleep ( 1 u) ;
145
+ }
146
+
147
+ #[ test]
148
+ fn test_timer_recv_timeout_before_time_passes ( ) {
149
+ let expected = rand:: rng ( ) . gen_str ( 16 u) ;
150
+ let test_po = comm:: port :: < str > ( ) ;
151
+ let test_ch = comm:: chan ( test_po) ;
152
+
153
+ task:: spawn ( ) { ||
154
+ delayed_send ( 1 u, test_ch, expected) ;
155
+ } ;
156
+
157
+ let actual = alt recv_timeout ( 1000 u, test_po) {
158
+ some ( val) { val }
159
+ _ { fail "test_timer_recv_timeout_before_time_passes:" +
160
+ " didn't receive result before timeout" ; }
161
+ } ;
162
+ assert actual == expected;
163
+ }
164
+
165
+ #[ test]
166
+ fn test_timer_recv_timeout_after_time_passes ( ) {
167
+ let expected = rand:: rng ( ) . gen_str ( 16 u) ;
168
+ let fail_msg = rand:: rng ( ) . gen_str ( 16 u) ;
169
+ let test_po = comm:: port :: < str > ( ) ;
170
+ let test_ch = comm:: chan ( test_po) ;
171
+
172
+ task:: spawn ( ) { ||
173
+ delayed_send ( 1000 u, test_ch, expected) ;
174
+ } ;
175
+
176
+ let actual = alt recv_timeout ( 1 u, test_po) {
177
+ none { fail_msg }
178
+ _ { fail "test_timer_recv_timeout_before_time_passes:" +
179
+ " didn't receive result before timeout" ; }
180
+ } ;
181
+ assert actual == fail_msg;
112
182
}
113
183
}
0 commit comments