1
1
#[ doc="
2
- Process -wide, lazily started/stopped libuv event loop interaction .
2
+ A process -wide libuv event loop for library use .
3
3
" ] ;
4
4
5
5
import ll = uv_ll;
6
6
import hl = uv_hl;
7
7
import get_gl = get;
8
8
9
- export get, get_single_task_gl;
9
+ export get, get_single_task_gl, get_monitor_task_gl ;
10
10
11
11
native mod rustrt {
12
12
fn rust_uv_get_kernel_global_chan_ptr ( ) -> * libc:: uintptr_t ;
13
+ fn rust_uv_get_kernel_monitor_global_chan_ptr ( ) -> * libc:: uintptr_t ;
13
14
fn rust_uv_get_kernel_global_async_handle ( ) -> * libc:: uintptr_t ;
14
15
fn rust_compare_and_swap_ptr ( address : * libc:: uintptr_t ,
15
16
oldval : libc:: uintptr_t ,
@@ -20,13 +21,34 @@ native mod rustrt {
20
21
Race-free helper to get access to a global task where a libuv
21
22
loop is running.
22
23
24
+ Use `uv::hl::interact`, `uv::hl::ref_handle` and `uv::hl::unref_handle` to
25
+ do operations against the global loop that this function returns.
26
+
23
27
# Return
24
28
25
29
* A `hl::high_level_loop` that encapsulates communication with the global
26
30
loop.
27
31
" ]
28
32
fn get ( ) -> hl:: high_level_loop {
29
- ret get_single_task_gl ( ) ;
33
+ ret get_monitor_task_gl ( ) ;
34
+ }
35
+
36
+ #[ doc( hidden) ]
37
+ fn get_monitor_task_gl ( ) -> hl:: high_level_loop {
38
+ let monitor_loop_chan =
39
+ rustrt:: rust_uv_get_kernel_monitor_global_chan_ptr ( ) ;
40
+ ret spawn_global_weak_task (
41
+ monitor_loop_chan,
42
+ { |weak_exit_po, msg_po, loop_ptr, first_msg|
43
+ log ( debug, "monitor gl: entering inner loop" ) ;
44
+ unsafe {
45
+ monitor_task_loop_body ( weak_exit_po, msg_po, loop_ptr,
46
+ copy ( first_msg) )
47
+ }
48
+ } ,
49
+ { |msg_ch|
50
+ hl:: monitor_task_loop ( { op_chan: msg_ch} )
51
+ } ) ;
30
52
}
31
53
32
54
#[ doc( hidden) ]
@@ -35,7 +57,7 @@ fn get_single_task_gl() -> hl::high_level_loop {
35
57
ret spawn_global_weak_task (
36
58
global_loop_chan_ptr,
37
59
{ |weak_exit_po, msg_po, loop_ptr, first_msg|
38
- log ( debug, "about to enter inner loop" ) ;
60
+ log ( debug, "single-task gl: about to enter inner loop" ) ;
39
61
unsafe {
40
62
single_task_loop_body ( weak_exit_po, msg_po, loop_ptr,
41
63
copy ( first_msg) )
@@ -135,6 +157,83 @@ unsafe fn outer_global_loop_body(
135
157
136
158
ll:: loop_delete ( loop_ptr) ;
137
159
}
160
+
161
+ unsafe fn monitor_task_loop_body ( weak_exit_po_in : comm:: port < ( ) > ,
162
+ msg_po_in : comm:: port < hl:: high_level_msg > ,
163
+ loop_ptr : * libc:: c_void ,
164
+ -first_interaction : hl:: high_level_msg ) -> bool {
165
+ // resend the msg to be handled in the select2 loop below..
166
+ comm:: send ( comm:: chan ( msg_po_in) , first_interaction) ;
167
+
168
+ // our async_handle
169
+ let async_handle_po = comm:: port :: < * ll:: uv_async_t > ( ) ;
170
+ let async_handle_ch = comm:: chan ( async_handle_po) ;
171
+
172
+ // the msg_po that libuv will be receiving on..
173
+ let loop_msg_po = comm:: port :: < hl:: high_level_msg > ( ) ;
174
+ let loop_msg_po_ptr = ptr:: addr_of ( loop_msg_po) ;
175
+ let loop_msg_ch = comm:: chan ( loop_msg_po) ;
176
+
177
+ // the question of whether unsupervising this will even do any
178
+ // good is there.. but since this'll go into blocking in libuv with
179
+ // a quickness.. any errors that occur (including inside crust) will
180
+ // be segfaults.. so yeah.
181
+ task:: spawn_sched ( task:: manual_threads ( 1 u) ) { ||
182
+ let loop_msg_po_in = * loop_msg_po_ptr;
183
+ hl:: run_high_level_loop (
184
+ loop_ptr,
185
+ loop_msg_po_in, // here the loop gets handed a different message
186
+ // port, as we'll be receiving all of the messages
187
+ // initially and then passing them on..
188
+ // before_run
189
+ { |async_handle|
190
+ log ( debug, #fmt ( "monitor gl: before_run: async_handle %?" ,
191
+ async_handle) ) ;
192
+ // when this is ran, our async_handle is set up, so let's
193
+ // do an async_send with it.. letting the loop know, once it
194
+ // starts, that is has work
195
+ ll:: async_send ( async_handle) ;
196
+ comm:: send ( async_handle_ch, copy ( async_handle) ) ;
197
+ } ,
198
+ // before_msg_drain
199
+ { |async_handle|
200
+ log ( debug, #fmt ( "monitor gl: b4_msg_drain: async_handle %?" ,
201
+ async_handle) ) ;
202
+ true
203
+ } ,
204
+ // before_tear_down
205
+ { |async_handle|
206
+ log ( debug, #fmt ( "monitor gl: b4_tear_down: async_handle %?" ,
207
+ async_handle) ) ;
208
+ } ) ;
209
+ } ;
210
+
211
+ // our loop is set up, so let's emit the handle back out to our users..
212
+ let async_handle = comm:: recv ( async_handle_po) ;
213
+ // supposed to return a bool to indicate to the enclosing loop whether
214
+ // it should continue or not..
215
+ let mut continue_inner_loop = true ;
216
+ let mut didnt_get_hl_bailout = true ;
217
+ while continue_inner_loop {
218
+ log ( debug, "monitor task inner loop.. about to block on select2" ) ;
219
+ continue_inner_loop = either:: either (
220
+ { |left_val|
221
+ // bail out..
222
+ log ( debug, #fmt ( "monitor inner weak_exit_po recv'd msg: %?" ,
223
+ left_val) ) ;
224
+ // TODO: make loop bail out
225
+ didnt_get_hl_bailout = false ;
226
+ false
227
+ } , { |right_val|
228
+ // wake up our inner loop and pass it a msg..
229
+ comm:: send ( loop_msg_ch, copy ( right_val) ) ;
230
+ ll:: async_send ( async_handle) ;
231
+ true
232
+ } , comm:: select2 ( weak_exit_po_in, msg_po_in)
233
+ )
234
+ }
235
+ didnt_get_hl_bailout
236
+ }
138
237
139
238
unsafe fn single_task_loop_body ( weak_exit_po_in : comm:: port < ( ) > ,
140
239
msg_po_in : comm:: port < hl:: high_level_msg > ,
0 commit comments