Skip to content

Commit 5842b60

Browse files
committed
Migrate uv getaddrinfo away from ~fn()
1 parent be89628 commit 5842b60

File tree

2 files changed

+70
-142
lines changed

2 files changed

+70
-142
lines changed

src/librustuv/addrinfo.rs

Lines changed: 67 additions & 110 deletions
Original file line numberDiff line numberDiff line change
@@ -8,41 +8,44 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
use std::cast::transmute;
12-
use std::cell::Cell;
13-
use std::libc::{c_int, c_void};
14-
use std::ptr::null;
1511
use ai = std::rt::io::net::addrinfo;
12+
use std::cast;
13+
use std::libc::c_int;
14+
use std::ptr::null;
15+
use std::rt::BlockedTask;
16+
use std::rt::local::Local;
17+
use std::rt::sched::Scheduler;
1618

17-
use uvll;
18-
use uvll::UV_GETADDRINFO;
19-
use super::{Loop, UvError, NativeHandle, status_to_maybe_uv_error};
2019
use net;
20+
use super::{Loop, UvError, NativeHandle};
21+
use uvll::UV_GETADDRINFO;
22+
use uvll;
2123

22-
type GetAddrInfoCallback = ~fn(GetAddrInfoRequest, &net::UvAddrInfo, Option<UvError>);
24+
struct GetAddrInfoRequest {
25+
handle: *uvll::uv_getaddrinfo_t,
26+
}
2327

24-
pub struct GetAddrInfoRequest(*uvll::uv_getaddrinfo_t);
28+
struct Addrinfo {
29+
handle: *uvll::addrinfo,
30+
}
2531

26-
pub struct RequestData {
27-
priv getaddrinfo_cb: Option<GetAddrInfoCallback>,
32+
struct Ctx {
33+
slot: Option<BlockedTask>,
34+
status: c_int,
35+
addrinfo: Option<Addrinfo>,
2836
}
2937

3038
impl GetAddrInfoRequest {
3139
pub fn new() -> GetAddrInfoRequest {
32-
let req = unsafe { uvll::malloc_req(UV_GETADDRINFO) };
33-
assert!(req.is_not_null());
34-
let mut req: GetAddrInfoRequest = NativeHandle::from_native_handle(req);
35-
req.install_req_data();
36-
return req;
40+
GetAddrInfoRequest {
41+
handle: unsafe { uvll::malloc_req(uvll::UV_GETADDRINFO) },
42+
}
3743
}
3844

39-
pub fn getaddrinfo(&mut self, loop_: &Loop, node: Option<&str>,
40-
service: Option<&str>, hints: Option<ai::Hint>,
41-
cb: GetAddrInfoCallback) {
42-
45+
pub fn run(loop_: &Loop, node: Option<&str>, service: Option<&str>,
46+
hints: Option<ai::Hint>) -> Result<~[ai::Info], UvError> {
4347
assert!(node.is_some() || service.is_some());
44-
45-
let (c_node, c_node_ptr) = match node {
48+
let (_c_node, c_node_ptr) = match node {
4649
Some(n) => {
4750
let c_node = n.to_c_str();
4851
let c_node_ptr = c_node.with_ref(|r| r);
@@ -51,7 +54,7 @@ impl GetAddrInfoRequest {
5154
None => (None, null())
5255
};
5356

54-
let (c_service, c_service_ptr) = match service {
57+
let (_c_service, c_service_ptr) = match service {
5558
Some(s) => {
5659
let c_service = s.to_c_str();
5760
let c_service_ptr = c_service.with_ref(|r| r);
@@ -60,37 +63,13 @@ impl GetAddrInfoRequest {
6063
None => (None, null())
6164
};
6265

63-
let cb = Cell::new(cb);
64-
let wrapper_cb: GetAddrInfoCallback = |req, addrinfo, err| {
65-
// Capture some heap values that need to stay alive for the
66-
// getaddrinfo call
67-
let _ = &c_node;
68-
let _ = &c_service;
69-
70-
let cb = cb.take();
71-
cb(req, addrinfo, err)
72-
};
73-
7466
let hint = hints.map(|hint| {
7567
let mut flags = 0;
7668
do each_ai_flag |cval, aival| {
7769
if hint.flags & (aival as uint) != 0 {
7870
flags |= cval as i32;
7971
}
8072
}
81-
/* XXX: do we really want to support these?
82-
let socktype = match hint.socktype {
83-
Some(ai::Stream) => uvll::rust_SOCK_STREAM(),
84-
Some(ai::Datagram) => uvll::rust_SOCK_DGRAM(),
85-
Some(ai::Raw) => uvll::rust_SOCK_RAW(),
86-
None => 0,
87-
};
88-
let protocol = match hint.protocol {
89-
Some(ai::UDP) => uvll::rust_IPPROTO_UDP(),
90-
Some(ai::TCP) => uvll::rust_IPPROTO_TCP(),
91-
_ => 0,
92-
};
93-
*/
9473
let socktype = 0;
9574
let protocol = 0;
9675

@@ -106,66 +85,54 @@ impl GetAddrInfoRequest {
10685
}
10786
});
10887
let hint_ptr = hint.as_ref().map_default(null(), |x| x as *uvll::addrinfo);
88+
let req = GetAddrInfoRequest::new();
89+
90+
return match unsafe {
91+
uvll::uv_getaddrinfo(loop_.native_handle(), req.handle,
92+
getaddrinfo_cb, c_node_ptr, c_service_ptr,
93+
hint_ptr)
94+
} {
95+
0 => {
96+
let mut cx = Ctx { slot: None, status: 0, addrinfo: None };
97+
unsafe { uvll::set_data_for_req(req.handle, &cx) }
98+
let scheduler: ~Scheduler = Local::take();
99+
do scheduler.deschedule_running_task_and_then |_, task| {
100+
cx.slot = Some(task);
101+
}
109102

110-
self.get_req_data().getaddrinfo_cb = Some(wrapper_cb);
111-
112-
unsafe {
113-
assert!(0 == uvll::uv_getaddrinfo(loop_.native_handle(),
114-
self.native_handle(),
115-
getaddrinfo_cb,
116-
c_node_ptr,
117-
c_service_ptr,
118-
hint_ptr));
119-
}
120-
121-
extern "C" fn getaddrinfo_cb(req: *uvll::uv_getaddrinfo_t,
122-
status: c_int,
123-
res: *uvll::addrinfo) {
124-
let mut req: GetAddrInfoRequest = NativeHandle::from_native_handle(req);
125-
let err = status_to_maybe_uv_error(status);
126-
let addrinfo = net::UvAddrInfo(res);
127-
let data = req.get_req_data();
128-
(*data.getaddrinfo_cb.get_ref())(req, &addrinfo, err);
129-
unsafe {
130-
uvll::uv_freeaddrinfo(res);
103+
match cx.status {
104+
0 => Ok(accum_addrinfo(cx.addrinfo.get_ref())),
105+
n => Err(UvError(n))
106+
}
131107
}
132-
}
133-
}
108+
n => Err(UvError(n))
109+
};
134110

135-
fn get_loop(&self) -> Loop {
136-
unsafe {
137-
Loop {
138-
handle: uvll::get_loop_from_fs_req(self.native_handle())
139-
}
140-
}
141-
}
142111

143-
fn install_req_data(&mut self) {
144-
let req = self.native_handle() as *uvll::uv_getaddrinfo_t;
145-
let data = ~RequestData {
146-
getaddrinfo_cb: None
147-
};
148-
unsafe {
149-
let data = transmute::<~RequestData, *c_void>(data);
150-
uvll::set_data_for_req(req, data);
112+
extern fn getaddrinfo_cb(req: *uvll::uv_getaddrinfo_t,
113+
status: c_int,
114+
res: *uvll::addrinfo) {
115+
let cx: &mut Ctx = unsafe {
116+
cast::transmute(uvll::get_data_for_req(req))
117+
};
118+
cx.status = status;
119+
cx.addrinfo = Some(Addrinfo { handle: res });
120+
121+
let sched: ~Scheduler = Local::take();
122+
sched.resume_blocked_task_immediately(cx.slot.take_unwrap());
151123
}
152124
}
125+
}
153126

154-
fn get_req_data<'r>(&'r mut self) -> &'r mut RequestData {
155-
unsafe {
156-
let data = uvll::get_data_for_req(self.native_handle());
157-
let data = transmute::<&*c_void, &mut ~RequestData>(&data);
158-
return &mut **data;
159-
}
127+
impl Drop for GetAddrInfoRequest {
128+
fn drop(&mut self) {
129+
unsafe { uvll::free_req(self.handle) }
160130
}
131+
}
161132

162-
fn delete(self) {
163-
unsafe {
164-
let data = uvll::get_data_for_req(self.native_handle());
165-
let _data = transmute::<*c_void, ~RequestData>(data);
166-
uvll::set_data_for_req(self.native_handle(), null::<()>());
167-
uvll::free_req(self.native_handle());
168-
}
133+
impl Drop for Addrinfo {
134+
fn drop(&mut self) {
135+
unsafe { uvll::uv_freeaddrinfo(self.handle) }
169136
}
170137
}
171138

@@ -184,10 +151,9 @@ fn each_ai_flag(_f: &fn(c_int, ai::Flag)) {
184151
}
185152

186153
// Traverse the addrinfo linked list, producing a vector of Rust socket addresses
187-
pub fn accum_addrinfo(addr: &net::UvAddrInfo) -> ~[ai::Info] {
154+
pub fn accum_addrinfo(addr: &Addrinfo) -> ~[ai::Info] {
188155
unsafe {
189-
let &net::UvAddrInfo(addr) = addr;
190-
let mut addr = addr;
156+
let mut addr = addr.handle;
191157

192158
let mut addrs = ~[];
193159
loop {
@@ -235,15 +201,6 @@ pub fn accum_addrinfo(addr: &net::UvAddrInfo) -> ~[ai::Info] {
235201
}
236202
}
237203

238-
impl NativeHandle<*uvll::uv_getaddrinfo_t> for GetAddrInfoRequest {
239-
fn from_native_handle(handle: *uvll::uv_getaddrinfo_t) -> GetAddrInfoRequest {
240-
GetAddrInfoRequest(handle)
241-
}
242-
fn native_handle(&self) -> *uvll::uv_getaddrinfo_t {
243-
match self { &GetAddrInfoRequest(ptr) => ptr }
244-
}
245-
}
246-
247204
#[cfg(test)]
248205
mod test {
249206
use Loop;

src/librustuv/uvio.rs

Lines changed: 3 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ use ai = std::rt::io::net::addrinfo;
4646
use super::*;
4747
use idle::IdleWatcher;
4848
use net::{UvIpv4SocketAddr, UvIpv6SocketAddr};
49-
use addrinfo::{GetAddrInfoRequest, accum_addrinfo};
49+
use addrinfo::GetAddrInfoRequest;
5050
use pipe::PipeListener;
5151

5252
// XXX we should not be calling uvll functions in here.
@@ -351,37 +351,8 @@ impl IoFactory for UvIoFactory {
351351

352352
fn get_host_addresses(&mut self, host: Option<&str>, servname: Option<&str>,
353353
hint: Option<ai::Hint>) -> Result<~[ai::Info], IoError> {
354-
let result_cell = Cell::new_empty();
355-
let result_cell_ptr: *Cell<Result<~[ai::Info], IoError>> = &result_cell;
356-
let host_ptr: *Option<&str> = &host;
357-
let servname_ptr: *Option<&str> = &servname;
358-
let hint_ptr: *Option<ai::Hint> = &hint;
359-
let addrinfo_req = GetAddrInfoRequest::new();
360-
let addrinfo_req_cell = Cell::new(addrinfo_req);
361-
362-
do task::unkillable { // FIXME(#8674)
363-
let scheduler: ~Scheduler = Local::take();
364-
do scheduler.deschedule_running_task_and_then |_, task| {
365-
let task_cell = Cell::new(task);
366-
let mut addrinfo_req = addrinfo_req_cell.take();
367-
unsafe {
368-
do addrinfo_req.getaddrinfo(self.uv_loop(),
369-
*host_ptr, *servname_ptr,
370-
*hint_ptr) |_, addrinfo, err| {
371-
let res = match err {
372-
None => Ok(accum_addrinfo(addrinfo)),
373-
Some(err) => Err(uv_error_to_io_error(err))
374-
};
375-
(*result_cell_ptr).put_back(res);
376-
let scheduler: ~Scheduler = Local::take();
377-
scheduler.resume_blocked_task_immediately(task_cell.take());
378-
}
379-
}
380-
}
381-
}
382-
addrinfo_req.delete();
383-
assert!(!result_cell.is_empty());
384-
return result_cell.take();
354+
let r = GetAddrInfoRequest::run(self.uv_loop(), host, servname, hint);
355+
r.map_err(uv_error_to_io_error)
385356
}
386357

387358
fn fs_from_raw_fd(&mut self, fd: c_int,

0 commit comments

Comments
 (0)