@@ -24,6 +24,7 @@ use std::cast;
24
24
use std:: libc:: { c_void, c_int} ;
25
25
use std:: rt:: task:: BlockedTask ;
26
26
use std:: unstable:: sync:: LittleLock ;
27
+ use std:: sync:: arc:: UnsafeArc ;
27
28
use mpsc = std:: sync:: mpsc_queue;
28
29
29
30
use async:: AsyncWatcher ;
@@ -39,46 +40,46 @@ enum Message {
39
40
struct State {
40
41
handle : * uvll:: uv_async_t ,
41
42
lock : LittleLock , // see comments in async_cb for why this is needed
43
+ queue : mpsc:: Queue < Message > ,
42
44
}
43
45
44
46
/// This structure is intended to be stored next to the event loop, and it is
45
47
/// used to create new `Queue` structures.
46
48
pub struct QueuePool {
47
- priv producer : mpsc:: Producer < Message , State > ,
48
- priv consumer : mpsc:: Consumer < Message , State > ,
49
+ priv queue : UnsafeArc < State > ,
49
50
priv refcnt : uint ,
50
51
}
51
52
52
53
/// This type is used to send messages back to the original event loop.
53
54
pub struct Queue {
54
- priv queue : mpsc :: Producer < Message , State > ,
55
+ priv queue : UnsafeArc < State > ,
55
56
}
56
57
57
58
extern fn async_cb ( handle : * uvll:: uv_async_t , status : c_int ) {
58
59
assert_eq ! ( status, 0 ) ;
59
- let state : & mut QueuePool = unsafe {
60
+ let pool : & mut QueuePool = unsafe {
60
61
cast:: transmute ( uvll:: get_data_for_uv_handle ( handle) )
61
62
} ;
62
- let packet = unsafe { state . consumer . packet ( ) } ;
63
+ let state : & mut State = unsafe { cast :: transmute ( pool . queue . get ( ) ) } ;
63
64
64
65
// Remember that there is no guarantee about how many times an async
65
66
// callback is called with relation to the number of sends, so process the
66
67
// entire queue in a loop.
67
68
loop {
68
- match state. consumer . pop ( ) {
69
+ match state. queue . pop ( ) {
69
70
mpsc:: Data ( Task ( task) ) => {
70
71
let _ = task. wake ( ) . map ( |t| t. reawaken ( ) ) ;
71
72
}
72
73
mpsc:: Data ( Increment ) => unsafe {
73
- if state . refcnt == 0 {
74
- uvll:: uv_ref ( ( * packet ) . handle ) ;
74
+ if pool . refcnt == 0 {
75
+ uvll:: uv_ref ( state . handle ) ;
75
76
}
76
- state . refcnt += 1 ;
77
+ pool . refcnt += 1 ;
77
78
} ,
78
79
mpsc:: Data ( Decrement ) => unsafe {
79
- state . refcnt -= 1 ;
80
- if state . refcnt == 0 {
81
- uvll:: uv_unref ( ( * packet ) . handle ) ;
80
+ pool . refcnt -= 1 ;
81
+ if pool . refcnt == 0 {
82
+ uvll:: uv_unref ( state . handle ) ;
82
83
}
83
84
} ,
84
85
mpsc:: Empty | mpsc:: Inconsistent => break
@@ -99,24 +100,24 @@ extern fn async_cb(handle: *uvll::uv_async_t, status: c_int) {
99
100
// If we acquire the mutex here, then we are guaranteed that there are no
100
101
// longer any senders which are holding on to their handles, so we can
101
102
// safely allow the event loop to exit.
102
- if state . refcnt == 0 {
103
+ if pool . refcnt == 0 {
103
104
unsafe {
104
- let _l = ( * packet ) . lock . lock ( ) ;
105
+ let _l = state . lock . lock ( ) ;
105
106
}
106
107
}
107
108
}
108
109
109
110
impl QueuePool {
110
111
pub fn new ( loop_ : & mut Loop ) -> ~QueuePool {
111
112
let handle = UvHandle :: alloc ( None :: < AsyncWatcher > , uvll:: UV_ASYNC ) ;
112
- let ( c , p ) = mpsc :: queue ( State {
113
+ let state = UnsafeArc :: new ( State {
113
114
handle : handle,
114
115
lock : LittleLock :: new ( ) ,
116
+ queue : mpsc:: Queue :: new ( ) ,
115
117
} ) ;
116
118
let q = ~QueuePool {
117
- producer : p,
118
- consumer : c,
119
119
refcnt : 0 ,
120
+ queue : state,
120
121
} ;
121
122
122
123
unsafe {
@@ -132,23 +133,23 @@ impl QueuePool {
132
133
pub fn queue ( & mut self ) -> Queue {
133
134
unsafe {
134
135
if self . refcnt == 0 {
135
- uvll:: uv_ref ( ( * self . producer . packet ( ) ) . handle ) ;
136
+ uvll:: uv_ref ( ( * self . queue . get ( ) ) . handle ) ;
136
137
}
137
138
self . refcnt += 1 ;
138
139
}
139
- Queue { queue : self . producer . clone ( ) }
140
+ Queue { queue : self . queue . clone ( ) }
140
141
}
141
142
142
143
pub fn handle ( & self ) -> * uvll:: uv_async_t {
143
- unsafe { ( * self . producer . packet ( ) ) . handle }
144
+ unsafe { ( * self . queue . get ( ) ) . handle }
144
145
}
145
146
}
146
147
147
148
impl Queue {
148
149
pub fn push ( & mut self , task : BlockedTask ) {
149
- self . queue . push ( Task ( task) ) ;
150
150
unsafe {
151
- uvll:: uv_async_send ( ( * self . queue . packet ( ) ) . handle ) ;
151
+ ( * self . queue . get ( ) ) . queue . push ( Task ( task) ) ;
152
+ uvll:: uv_async_send ( ( * self . queue . get ( ) ) . handle ) ;
152
153
}
153
154
}
154
155
}
@@ -161,7 +162,7 @@ impl Clone for Queue {
161
162
// and if the queue is dropped later on it'll see the increment for the
162
163
// decrement anyway.
163
164
unsafe {
164
- cast :: transmute_mut ( self ) . queue . push ( Increment ) ;
165
+ ( * self . queue . get ( ) ) . queue . push ( Increment ) ;
165
166
}
166
167
Queue { queue : self . queue . clone ( ) }
167
168
}
@@ -172,9 +173,9 @@ impl Drop for Queue {
172
173
// See the comments in the async_cb function for why there is a lock
173
174
// that is acquired only on a drop.
174
175
unsafe {
175
- let state = self . queue . packet ( ) ;
176
+ let state = self . queue . get ( ) ;
176
177
let _l = ( * state) . lock . lock ( ) ;
177
- self . queue . push ( Decrement ) ;
178
+ ( * state ) . queue . push ( Decrement ) ;
178
179
uvll:: uv_async_send ( ( * state) . handle ) ;
179
180
}
180
181
}
0 commit comments