1
Fork 0

libsyntax: Remove fn() unsafe { ... }. r=graydon

This commit is contained in:
Patrick Walton 2013-01-23 11:43:58 -08:00
parent 1d1b81143b
commit 54b2cad8b3
59 changed files with 2807 additions and 2425 deletions

View file

@ -33,34 +33,36 @@ fn load_errors(testfile: &Path) -> ~[expected_error] {
return error_patterns; return error_patterns;
} }
fn parse_expected(line_num: uint, line: ~str) -> ~[expected_error] unsafe { fn parse_expected(line_num: uint, line: ~str) -> ~[expected_error] {
let error_tag = ~"//~"; unsafe {
let mut idx; let error_tag = ~"//~";
match str::find_str(line, error_tag) { let mut idx;
None => return ~[], match str::find_str(line, error_tag) {
Some(nn) => { idx = (nn as uint) + str::len(error_tag); } None => return ~[],
Some(nn) => { idx = (nn as uint) + str::len(error_tag); }
}
// "//~^^^ kind msg" denotes a message expected
// three lines above current line:
let mut adjust_line = 0u;
let len = str::len(line);
while idx < len && line[idx] == ('^' as u8) {
adjust_line += 1u;
idx += 1u;
}
// Extract kind:
while idx < len && line[idx] == (' ' as u8) { idx += 1u; }
let start_kind = idx;
while idx < len && line[idx] != (' ' as u8) { idx += 1u; }
let kind = str::to_lower(str::slice(line, start_kind, idx));
// Extract msg:
while idx < len && line[idx] == (' ' as u8) { idx += 1u; }
let msg = str::slice(line, idx, len);
debug!("line=%u kind=%s msg=%s", line_num - adjust_line, kind, msg);
return ~[{line: line_num - adjust_line, kind: kind, msg: msg}];
} }
// "//~^^^ kind msg" denotes a message expected
// three lines above current line:
let mut adjust_line = 0u;
let len = str::len(line);
while idx < len && line[idx] == ('^' as u8) {
adjust_line += 1u;
idx += 1u;
}
// Extract kind:
while idx < len && line[idx] == (' ' as u8) { idx += 1u; }
let start_kind = idx;
while idx < len && line[idx] != (' ' as u8) { idx += 1u; }
let kind = str::to_lower(str::slice(line, start_kind, idx));
// Extract msg:
while idx < len && line[idx] == (' ' as u8) { idx += 1u; }
let msg = str::slice(line, idx, len);
debug!("line=%u kind=%s msg=%s", line_num - adjust_line, kind, msg);
return ~[{line: line_num - adjust_line, kind: kind, msg: msg}];
} }

View file

@ -146,15 +146,17 @@ fn parse_name_directive(line: ~str, directive: ~str) -> bool {
} }
fn parse_name_value_directive(line: ~str, fn parse_name_value_directive(line: ~str,
directive: ~str) -> Option<~str> unsafe { directive: ~str) -> Option<~str> {
let keycolon = directive + ~":"; unsafe {
match str::find_str(line, keycolon) { let keycolon = directive + ~":";
Some(colon) => { match str::find_str(line, keycolon) {
let value = str::slice(line, colon + str::len(keycolon), Some(colon) => {
str::len(line)); let value = str::slice(line, colon + str::len(keycolon),
debug!("%s: %s", directive, value); str::len(line));
Some(value) debug!("%s: %s", directive, value);
Some(value)
}
None => None
} }
None => None
} }
} }

View file

@ -1135,28 +1135,30 @@ fn get_temp_workdir(c: &Cargo) -> Path {
} }
} }
fn cmd_install(c: &Cargo) unsafe { fn cmd_install(c: &Cargo) {
let wd = get_temp_workdir(c); unsafe {
let wd = get_temp_workdir(c);
if vec::len(c.opts.free) == 2u { if vec::len(c.opts.free) == 2u {
let cwd = os::getcwd(); let cwd = os::getcwd();
let status = run::run_program(~"cp", ~[~"-R", cwd.to_str(), let status = run::run_program(~"cp", ~[~"-R", cwd.to_str(),
wd.to_str()]); wd.to_str()]);
if status != 0 { if status != 0 {
fail fmt!("could not copy directory: %s", cwd.to_str()); fail fmt!("could not copy directory: %s", cwd.to_str());
}
install_source(c, &wd);
return;
} }
install_source(c, &wd); sync(c);
return;
let query = c.opts.free[2];
c.current_install = query.to_str();
install_query(c, &wd, query);
} }
sync(c);
let query = c.opts.free[2];
c.current_install = query.to_str();
install_query(c, &wd, query);
} }
fn sync(c: &Cargo) { fn sync(c: &Cargo) {

View file

@ -121,8 +121,9 @@ pub fn listen<T: Owned, U>(f: fn(Chan<T>) -> U) -> U {
} }
struct PortPtr<T:Owned> { struct PortPtr<T:Owned> {
po: *rust_port, po: *rust_port,
drop unsafe { drop {
unsafe {
do task::unkillable { do task::unkillable {
// Once the port is detached it's guaranteed not to receive further // Once the port is detached it's guaranteed not to receive further
// messages // messages
@ -140,6 +141,7 @@ struct PortPtr<T:Owned> {
recv_::<T>(self.po); recv_::<T>(self.po);
} }
rustrt::del_port(self.po); rustrt::del_port(self.po);
}
} }
} }
} }
@ -209,7 +211,7 @@ pub fn send<T: Owned>(ch: Chan<T>, data: T) {
let Chan_(p) = ch; let Chan_(p) = ch;
let data_ptr = ptr::addr_of(&data) as *(); let data_ptr = ptr::addr_of(&data) as *();
let res = rustrt::rust_port_id_send(p, data_ptr); let res = rustrt::rust_port_id_send(p, data_ptr);
if res != 0 unsafe { if res != 0 {
// Data sent successfully // Data sent successfully
cast::forget(move data); cast::forget(move data);
} }

View file

@ -86,8 +86,10 @@ pub fn fill_charp_buf(f: fn(*mut c_char, size_t) -> bool)
-> Option<~str> { -> Option<~str> {
let buf = vec::cast_to_mut(vec::from_elem(tmpbuf_sz, 0u8 as c_char)); let buf = vec::cast_to_mut(vec::from_elem(tmpbuf_sz, 0u8 as c_char));
do vec::as_mut_buf(buf) |b, sz| { do vec::as_mut_buf(buf) |b, sz| {
if f(b, sz as size_t) unsafe { if f(b, sz as size_t) {
Some(str::raw::from_buf(b as *u8)) unsafe {
Some(str::raw::from_buf(b as *u8))
}
} else { } else {
None None
} }

View file

@ -193,8 +193,10 @@ impl PacketHeader {
reinterpret_cast(&self.buffer) reinterpret_cast(&self.buffer)
} }
fn set_buffer<T: Owned>(b: ~Buffer<T>) unsafe { fn set_buffer<T: Owned>(b: ~Buffer<T>) {
self.buffer = reinterpret_cast(&b); unsafe {
self.buffer = reinterpret_cast(&b);
}
} }
} }
@ -356,19 +358,21 @@ pub unsafe fn get_buffer<T: Owned>(p: *PacketHeader) -> ~Buffer<T> {
struct BufferResource<T: Owned> { struct BufferResource<T: Owned> {
buffer: ~Buffer<T>, buffer: ~Buffer<T>,
drop unsafe { drop {
let b = move_it!(self.buffer); unsafe {
//let p = ptr::addr_of(*b); let b = move_it!(self.buffer);
//error!("drop %?", p); //let p = ptr::addr_of(*b);
let old_count = atomic_sub_rel(&mut b.header.ref_count, 1); //error!("drop %?", p);
//let old_count = atomic_xchng_rel(b.header.ref_count, 0); let old_count = atomic_sub_rel(&mut b.header.ref_count, 1);
if old_count == 1 { //let old_count = atomic_xchng_rel(b.header.ref_count, 0);
// The new count is 0. if old_count == 1 {
// The new count is 0.
// go go gadget drop glue // go go gadget drop glue
} }
else { else {
forget(move b) forget(move b)
}
} }
} }
} }
@ -641,18 +645,20 @@ fn wait_many<T: Selectable>(pkts: &[T]) -> uint {
let mut data_avail = false; let mut data_avail = false;
let mut ready_packet = pkts.len(); let mut ready_packet = pkts.len();
for pkts.eachi |i, p| unsafe { for pkts.eachi |i, p| {
let p = unsafe { &*p.header() }; unsafe {
let old = p.mark_blocked(this); let p = &*p.header();
match old { let old = p.mark_blocked(this);
Full | Terminated => { match old {
data_avail = true; Full | Terminated => {
ready_packet = i; data_avail = true;
(*p).state = old; ready_packet = i;
break; (*p).state = old;
} break;
Blocked => fail ~"blocking on blocked packet", }
Empty => () Blocked => fail ~"blocking on blocked packet",
Empty => ()
}
} }
} }
@ -1072,23 +1078,27 @@ impl<T: Owned> Port<T>: GenericPort<T> {
} }
impl<T: Owned> Port<T>: Peekable<T> { impl<T: Owned> Port<T>: Peekable<T> {
pure fn peek() -> bool unsafe { pure fn peek() -> bool {
let mut endp = None; unsafe {
endp <-> self.endp; let mut endp = None;
let peek = match &endp { endp <-> self.endp;
&Some(ref endp) => pipes::peek(endp), let peek = match &endp {
&None => fail ~"peeking empty stream" &Some(ref endp) => pipes::peek(endp),
}; &None => fail ~"peeking empty stream"
self.endp <-> endp; };
peek self.endp <-> endp;
peek
}
} }
} }
impl<T: Owned> Port<T>: Selectable { impl<T: Owned> Port<T>: Selectable {
pure fn header() -> *PacketHeader unsafe { pure fn header() -> *PacketHeader {
match self.endp { unsafe {
Some(ref endp) => endp.header(), match self.endp {
None => fail ~"peeking empty stream" Some(ref endp) => endp.header(),
None => fail ~"peeking empty stream"
}
} }
} }
} }

View file

@ -64,22 +64,26 @@ pub unsafe fn run_in_bare_thread(f: ~fn()) {
let (port, chan) = pipes::stream(); let (port, chan) = pipes::stream();
// FIXME #4525: Unfortunate that this creates an extra scheduler but it's // FIXME #4525: Unfortunate that this creates an extra scheduler but it's
// necessary since rust_raw_thread_join_delete is blocking // necessary since rust_raw_thread_join_delete is blocking
do task::spawn_sched(task::SingleThreaded) unsafe { do task::spawn_sched(task::SingleThreaded) {
let closure: &fn() = || { unsafe {
f() let closure: &fn() = || {
}; f()
let thread = rustrt::rust_raw_thread_start(closure); };
rustrt::rust_raw_thread_join_delete(thread); let thread = rustrt::rust_raw_thread_start(closure);
chan.send(()); rustrt::rust_raw_thread_join_delete(thread);
chan.send(());
}
} }
port.recv(); port.recv();
} }
#[test] #[test]
fn test_run_in_bare_thread() unsafe { fn test_run_in_bare_thread() {
let i = 100; unsafe {
do run_in_bare_thread { let i = 100;
assert i == 100; do run_in_bare_thread {
assert i == 100;
}
} }
} }
@ -273,8 +277,10 @@ pub unsafe fn weaken_task(f: fn(oldcomm::Port<()>)) {
struct Unweaken { struct Unweaken {
ch: oldcomm::Chan<()>, ch: oldcomm::Chan<()>,
drop unsafe { drop {
rustrt::rust_task_unweaken(cast::reinterpret_cast(&self.ch)); unsafe {
rustrt::rust_task_unweaken(cast::reinterpret_cast(&self.ch));
}
} }
} }
@ -359,37 +365,40 @@ struct ArcData<T> {
struct ArcDestruct<T> { struct ArcDestruct<T> {
mut data: *libc::c_void, mut data: *libc::c_void,
drop unsafe { drop {
if self.data.is_null() { unsafe {
return; // Happens when destructing an unwrapper's handle. if self.data.is_null() {
} return; // Happens when destructing an unwrapper's handle.
do task::unkillable { }
let data: ~ArcData<T> = cast::reinterpret_cast(&self.data); do task::unkillable {
let new_count = rusti::atomic_xsub(&mut data.count, 1) - 1; let data: ~ArcData<T> = cast::reinterpret_cast(&self.data);
assert new_count >= 0; let new_count = rusti::atomic_xsub(&mut data.count, 1) - 1;
if new_count == 0 { assert new_count >= 0;
// Were we really last, or should we hand off to an unwrapper? if new_count == 0 {
// It's safe to not xchg because the unwrapper will set the // Were we really last, or should we hand off to an
// unwrap lock *before* dropping his/her reference. In effect, // unwrapper? It's safe to not xchg because the unwrapper
// being here means we're the only *awake* task with the data. // will set the unwrap lock *before* dropping his/her
if data.unwrapper != 0 { // reference. In effect, being here means we're the only
let p: UnwrapProto = // *awake* task with the data.
cast::reinterpret_cast(&data.unwrapper); if data.unwrapper != 0 {
let (message, response) = option::swap_unwrap(p); let p: UnwrapProto =
// Send 'ready' and wait for a response. cast::reinterpret_cast(&data.unwrapper);
pipes::send_one(move message, ()); let (message, response) = option::swap_unwrap(p);
// Unkillable wait. Message guaranteed to come. // Send 'ready' and wait for a response.
if pipes::recv_one(move response) { pipes::send_one(move message, ());
// Other task got the data. // Unkillable wait. Message guaranteed to come.
cast::forget(move data); if pipes::recv_one(move response) {
// Other task got the data.
cast::forget(move data);
} else {
// Other task was killed. drop glue takes over.
}
} else { } else {
// Other task was killed. drop glue takes over. // drop glue takes over.
} }
} else { } else {
// drop glue takes over. cast::forget(move data);
} }
} else {
cast::forget(move data);
} }
} }
} }
@ -406,18 +415,21 @@ pub unsafe fn unwrap_shared_mutable_state<T: Owned>(rc: SharedMutableState<T>)
struct DeathThroes<T> { struct DeathThroes<T> {
mut ptr: Option<~ArcData<T>>, mut ptr: Option<~ArcData<T>>,
mut response: Option<pipes::ChanOne<bool>>, mut response: Option<pipes::ChanOne<bool>>,
drop unsafe { drop {
let response = option::swap_unwrap(&mut self.response); unsafe {
// In case we get killed early, we need to tell the person who let response = option::swap_unwrap(&mut self.response);
// tried to wake us whether they should hand-off the data to us. // In case we get killed early, we need to tell the person who
if task::failing() { // tried to wake us whether they should hand-off the data to
pipes::send_one(move response, false); // us.
// Either this swap_unwrap or the one below (at "Got here") if task::failing() {
// ought to run. pipes::send_one(move response, false);
cast::forget(option::swap_unwrap(&mut self.ptr)); // Either this swap_unwrap or the one below (at "Got
} else { // here") ought to run.
assert self.ptr.is_none(); cast::forget(option::swap_unwrap(&mut self.ptr));
pipes::send_one(move response, true); } else {
assert self.ptr.is_none();
pipes::send_one(move response, true);
}
} }
} }
} }

View file

@ -165,8 +165,10 @@ pub pure fn to_mut_unsafe_ptr<T>(thing: &mut T) -> *mut T {
(I couldn't think of a cutesy name for this one.) (I couldn't think of a cutesy name for this one.)
*/ */
#[inline(always)] #[inline(always)]
pub pure fn to_uint<T>(thing: &T) -> uint unsafe { pub pure fn to_uint<T>(thing: &T) -> uint {
cast::reinterpret_cast(&thing) unsafe {
cast::reinterpret_cast(&thing)
}
} }
/// Determine if two borrowed pointers point to the same thing. /// Determine if two borrowed pointers point to the same thing.
@ -215,10 +217,12 @@ impl<T> *mut T: Ptr<T> {
#[cfg(notest)] #[cfg(notest)]
impl<T> *const T : Eq { impl<T> *const T : Eq {
#[inline(always)] #[inline(always)]
pure fn eq(&self, other: &*const T) -> bool unsafe { pure fn eq(&self, other: &*const T) -> bool {
let a: uint = cast::reinterpret_cast(&(*self)); unsafe {
let b: uint = cast::reinterpret_cast(&(*other)); let a: uint = cast::reinterpret_cast(&(*self));
return a == b; let b: uint = cast::reinterpret_cast(&(*other));
return a == b;
}
} }
#[inline(always)] #[inline(always)]
pure fn ne(&self, other: &*const T) -> bool { !(*self).eq(other) } pure fn ne(&self, other: &*const T) -> bool { !(*self).eq(other) }
@ -228,28 +232,36 @@ impl<T> *const T : Eq {
#[cfg(notest)] #[cfg(notest)]
impl<T> *const T : Ord { impl<T> *const T : Ord {
#[inline(always)] #[inline(always)]
pure fn lt(&self, other: &*const T) -> bool unsafe { pure fn lt(&self, other: &*const T) -> bool {
let a: uint = cast::reinterpret_cast(&(*self)); unsafe {
let b: uint = cast::reinterpret_cast(&(*other)); let a: uint = cast::reinterpret_cast(&(*self));
return a < b; let b: uint = cast::reinterpret_cast(&(*other));
return a < b;
}
} }
#[inline(always)] #[inline(always)]
pure fn le(&self, other: &*const T) -> bool unsafe { pure fn le(&self, other: &*const T) -> bool {
let a: uint = cast::reinterpret_cast(&(*self)); unsafe {
let b: uint = cast::reinterpret_cast(&(*other)); let a: uint = cast::reinterpret_cast(&(*self));
return a <= b; let b: uint = cast::reinterpret_cast(&(*other));
return a <= b;
}
} }
#[inline(always)] #[inline(always)]
pure fn ge(&self, other: &*const T) -> bool unsafe { pure fn ge(&self, other: &*const T) -> bool {
let a: uint = cast::reinterpret_cast(&(*self)); unsafe {
let b: uint = cast::reinterpret_cast(&(*other)); let a: uint = cast::reinterpret_cast(&(*self));
return a >= b; let b: uint = cast::reinterpret_cast(&(*other));
return a >= b;
}
} }
#[inline(always)] #[inline(always)]
pure fn gt(&self, other: &*const T) -> bool unsafe { pure fn gt(&self, other: &*const T) -> bool {
let a: uint = cast::reinterpret_cast(&(*self)); unsafe {
let b: uint = cast::reinterpret_cast(&(*other)); let a: uint = cast::reinterpret_cast(&(*self));
return a > b; let b: uint = cast::reinterpret_cast(&(*other));
return a > b;
}
} }
} }

View file

@ -366,10 +366,12 @@ Section: Transforming strings
* *
* The result vector is not null-terminated. * The result vector is not null-terminated.
*/ */
pub pure fn to_bytes(s: &str) -> ~[u8] unsafe { pub pure fn to_bytes(s: &str) -> ~[u8] {
let mut v: ~[u8] = ::cast::transmute(from_slice(s)); unsafe {
vec::raw::set_len(&mut v, len(s)); let mut v: ~[u8] = ::cast::transmute(from_slice(s));
v vec::raw::set_len(&mut v, len(s));
v
}
} }
/// Work with the string as a byte slice, not including trailing null. /// Work with the string as a byte slice, not including trailing null.
@ -454,8 +456,10 @@ pure fn split_char_inner(s: &str, sep: char, count: uint, allow_empty: bool)
let mut i = 0u, start = 0u; let mut i = 0u, start = 0u;
while i < l && done < count { while i < l && done < count {
if s[i] == b { if s[i] == b {
if allow_empty || start < i unsafe { if allow_empty || start < i {
result.push(unsafe { raw::slice_bytes(s, start, i) }); unsafe {
result.push(raw::slice_bytes(s, start, i));
}
} }
start = i + 1u; start = i + 1u;
done += 1u; done += 1u;
@ -497,16 +501,20 @@ pure fn split_inner(s: &str, sepfn: fn(cc: char) -> bool, count: uint,
while i < l && done < count { while i < l && done < count {
let CharRange {ch, next} = char_range_at(s, i); let CharRange {ch, next} = char_range_at(s, i);
if sepfn(ch) { if sepfn(ch) {
if allow_empty || start < i unsafe { if allow_empty || start < i {
result.push(unsafe { raw::slice_bytes(s, start, i)}); unsafe {
result.push(raw::slice_bytes(s, start, i));
}
} }
start = next; start = next;
done += 1u; done += 1u;
} }
i = next; i = next;
} }
if allow_empty || start < l unsafe { if allow_empty || start < l {
result.push(unsafe { raw::slice_bytes(s, start, l) }); unsafe {
result.push(raw::slice_bytes(s, start, l));
}
} }
result result
} }
@ -1490,17 +1498,20 @@ pub pure fn to_utf16(s: &str) -> ~[u16] {
// Arithmetic with u32 literals is easier on the eyes than chars. // Arithmetic with u32 literals is easier on the eyes than chars.
let mut ch = cch as u32; let mut ch = cch as u32;
if (ch & 0xFFFF_u32) == ch unsafe { unsafe {
// The BMP falls through (assuming non-surrogate, as it should) if (ch & 0xFFFF_u32) == ch {
assert ch <= 0xD7FF_u32 || ch >= 0xE000_u32; // The BMP falls through (assuming non-surrogate, as it
u.push(ch as u16) // should)
} else unsafe { assert ch <= 0xD7FF_u32 || ch >= 0xE000_u32;
// Supplementary planes break into surrogates. u.push(ch as u16)
assert ch >= 0x1_0000_u32 && ch <= 0x10_FFFF_u32; } else {
ch -= 0x1_0000_u32; // Supplementary planes break into surrogates.
let w1 = 0xD800_u16 | ((ch >> 10) as u16); assert ch >= 0x1_0000_u32 && ch <= 0x10_FFFF_u32;
let w2 = 0xDC00_u16 | ((ch as u16) & 0x3FF_u16); ch -= 0x1_0000_u32;
u.push_all(~[w1, w2]) let w1 = 0xD800_u16 | ((ch >> 10) as u16);
let w2 = 0xDC00_u16 | ((ch as u16) & 0x3FF_u16);
u.push_all(~[w1, w2])
}
} }
} }
u u

View file

@ -213,24 +213,26 @@ pub mod tests {
} }
#[test] #[test]
pub fn synthesize_closure() unsafe { pub fn synthesize_closure() {
let x = 10; unsafe {
let f: fn(int) -> int = |y| x + y; let x = 10;
let f: fn(int) -> int = |y| x + y;
assert f(20) == 30; assert f(20) == 30;
let original_closure: Closure = cast::transmute(move f); let original_closure: Closure = cast::transmute(move f);
let actual_function_pointer = original_closure.code; let actual_function_pointer = original_closure.code;
let environment = original_closure.env; let environment = original_closure.env;
let new_closure = Closure { let new_closure = Closure {
code: actual_function_pointer, code: actual_function_pointer,
env: environment env: environment
}; };
let new_f: fn(int) -> int = cast::transmute(move new_closure); let new_f: fn(int) -> int = cast::transmute(move new_closure);
assert new_f(20) == 30; assert new_f(20) == 30;
}
} }
} }

View file

@ -86,79 +86,97 @@ pub unsafe fn local_data_modify<T: Durable>(
} }
#[test] #[test]
fn test_tls_multitask() unsafe { fn test_tls_multitask() {
fn my_key(_x: @~str) { } unsafe {
local_data_set(my_key, @~"parent data"); fn my_key(_x: @~str) { }
do task::spawn unsafe { local_data_set(my_key, @~"parent data");
assert local_data_get(my_key).is_none(); // TLS shouldn't carry over. do task::spawn {
local_data_set(my_key, @~"child data"); unsafe {
assert *(local_data_get(my_key).get()) == ~"child data"; // TLS shouldn't carry over.
// should be cleaned up for us assert local_data_get(my_key).is_none();
} local_data_set(my_key, @~"child data");
// Must work multiple times assert *(local_data_get(my_key).get()) == ~"child data";
assert *(local_data_get(my_key).get()) == ~"parent data"; // should be cleaned up for us
assert *(local_data_get(my_key).get()) == ~"parent data"; }
assert *(local_data_get(my_key).get()) == ~"parent data";
}
#[test]
fn test_tls_overwrite() unsafe {
fn my_key(_x: @~str) { }
local_data_set(my_key, @~"first data");
local_data_set(my_key, @~"next data"); // Shouldn't leak.
assert *(local_data_get(my_key).get()) == ~"next data";
}
#[test]
fn test_tls_pop() unsafe {
fn my_key(_x: @~str) { }
local_data_set(my_key, @~"weasel");
assert *(local_data_pop(my_key).get()) == ~"weasel";
// Pop must remove the data from the map.
assert local_data_pop(my_key).is_none();
}
#[test]
fn test_tls_modify() unsafe {
fn my_key(_x: @~str) { }
local_data_modify(my_key, |data| {
match data {
Some(@ref val) => fail ~"unwelcome value: " + *val,
None => Some(@~"first data")
} }
}); // Must work multiple times
local_data_modify(my_key, |data| { assert *(local_data_get(my_key).get()) == ~"parent data";
match data { assert *(local_data_get(my_key).get()) == ~"parent data";
Some(@~"first data") => Some(@~"next data"), assert *(local_data_get(my_key).get()) == ~"parent data";
Some(@ref val) => fail ~"wrong value: " + *val,
None => fail ~"missing value"
}
});
assert *(local_data_pop(my_key).get()) == ~"next data";
}
#[test]
fn test_tls_crust_automorestack_memorial_bug() unsafe {
// This might result in a stack-canary clobber if the runtime fails to set
// sp_limit to 0 when calling the cleanup extern - it might automatically
// jump over to the rust stack, which causes next_c_sp to get recorded as
// Something within a rust stack segment. Then a subsequent upcall (esp.
// for logging, think vsnprintf) would run on a stack smaller than 1 MB.
fn my_key(_x: @~str) { }
do task::spawn {
unsafe { local_data_set(my_key, @~"hax"); }
} }
} }
#[test] #[test]
fn test_tls_multiple_types() unsafe { fn test_tls_overwrite() {
fn str_key(_x: @~str) { } unsafe {
fn box_key(_x: @@()) { } fn my_key(_x: @~str) { }
fn int_key(_x: @int) { } local_data_set(my_key, @~"first data");
do task::spawn unsafe { local_data_set(my_key, @~"next data"); // Shouldn't leak.
local_data_set(str_key, @~"string data"); assert *(local_data_get(my_key).get()) == ~"next data";
local_data_set(box_key, @@()); }
local_data_set(int_key, @42); }
#[test]
fn test_tls_pop() {
unsafe {
fn my_key(_x: @~str) { }
local_data_set(my_key, @~"weasel");
assert *(local_data_pop(my_key).get()) == ~"weasel";
// Pop must remove the data from the map.
assert local_data_pop(my_key).is_none();
}
}
#[test]
fn test_tls_modify() {
unsafe {
fn my_key(_x: @~str) { }
local_data_modify(my_key, |data| {
match data {
Some(@ref val) => fail ~"unwelcome value: " + *val,
None => Some(@~"first data")
}
});
local_data_modify(my_key, |data| {
match data {
Some(@~"first data") => Some(@~"next data"),
Some(@ref val) => fail ~"wrong value: " + *val,
None => fail ~"missing value"
}
});
assert *(local_data_pop(my_key).get()) == ~"next data";
}
}
#[test]
fn test_tls_crust_automorestack_memorial_bug() {
unsafe {
// This might result in a stack-canary clobber if the runtime fails to
// set sp_limit to 0 when calling the cleanup extern - it might
// automatically jump over to the rust stack, which causes next_c_sp
// to get recorded as something within a rust stack segment. Then a
// subsequent upcall (esp. for logging, think vsnprintf) would run on
// a stack smaller than 1 MB.
fn my_key(_x: @~str) { }
do task::spawn {
unsafe { local_data_set(my_key, @~"hax"); }
}
}
}
#[test]
fn test_tls_multiple_types() {
unsafe {
fn str_key(_x: @~str) { }
fn box_key(_x: @@()) { }
fn int_key(_x: @int) { }
do task::spawn {
unsafe {
local_data_set(str_key, @~"string data");
local_data_set(box_key, @@());
local_data_set(int_key, @42);
}
}
} }
} }
@ -167,31 +185,38 @@ fn test_tls_overwrite_multiple_types() {
fn str_key(_x: @~str) { } fn str_key(_x: @~str) { }
fn box_key(_x: @@()) { } fn box_key(_x: @@()) { }
fn int_key(_x: @int) { } fn int_key(_x: @int) { }
do task::spawn unsafe { do task::spawn {
local_data_set(str_key, @~"string data"); unsafe {
local_data_set(int_key, @42); local_data_set(str_key, @~"string data");
// This could cause a segfault if overwriting-destruction is done with local_data_set(int_key, @42);
// the crazy polymorphic transmute rather than the provided finaliser. // This could cause a segfault if overwriting-destruction is done
local_data_set(int_key, @31337); // with the crazy polymorphic transmute rather than the provided
// finaliser.
local_data_set(int_key, @31337);
}
} }
} }
#[test] #[test]
#[should_fail] #[should_fail]
#[ignore(cfg(windows))] #[ignore(cfg(windows))]
fn test_tls_cleanup_on_failure() unsafe { fn test_tls_cleanup_on_failure() {
fn str_key(_x: @~str) { } unsafe {
fn box_key(_x: @@()) { } fn str_key(_x: @~str) { }
fn int_key(_x: @int) { } fn box_key(_x: @@()) { }
local_data_set(str_key, @~"parent data"); fn int_key(_x: @int) { }
local_data_set(box_key, @@()); local_data_set(str_key, @~"parent data");
do task::spawn unsafe { // spawn_linked
local_data_set(str_key, @~"string data");
local_data_set(box_key, @@()); local_data_set(box_key, @@());
local_data_set(int_key, @42); do task::spawn {
unsafe { // spawn_linked
local_data_set(str_key, @~"string data");
local_data_set(box_key, @@());
local_data_set(int_key, @42);
fail;
}
}
// Not quite nondeterministic.
local_data_set(int_key, @31337);
fail; fail;
} }
// Not quite nondeterministic.
local_data_set(int_key, @31337);
fail;
} }

View file

@ -29,10 +29,12 @@ pub trait LocalData { }
impl<T: Durable> @T: LocalData { } impl<T: Durable> @T: LocalData { }
impl LocalData: Eq { impl LocalData: Eq {
pure fn eq(&self, other: &@LocalData) -> bool unsafe { pure fn eq(&self, other: &@LocalData) -> bool {
let ptr_a: (uint, uint) = cast::reinterpret_cast(&(*self)); unsafe {
let ptr_b: (uint, uint) = cast::reinterpret_cast(other); let ptr_a: (uint, uint) = cast::reinterpret_cast(&(*self));
return ptr_a == ptr_b; let ptr_b: (uint, uint) = cast::reinterpret_cast(other);
return ptr_a == ptr_b;
}
} }
pure fn ne(&self, other: &@LocalData) -> bool { !(*self).eq(other) } pure fn ne(&self, other: &@LocalData) -> bool { !(*self).eq(other) }
} }
@ -43,11 +45,14 @@ type TaskLocalElement = (*libc::c_void, *libc::c_void, LocalData);
// Has to be a pointer at outermost layer; the foreign call returns void *. // Has to be a pointer at outermost layer; the foreign call returns void *.
type TaskLocalMap = @dvec::DVec<Option<TaskLocalElement>>; type TaskLocalMap = @dvec::DVec<Option<TaskLocalElement>>;
extern fn cleanup_task_local_map(map_ptr: *libc::c_void) unsafe { extern fn cleanup_task_local_map(map_ptr: *libc::c_void) {
assert !map_ptr.is_null(); unsafe {
// Get and keep the single reference that was created at the beginning. assert !map_ptr.is_null();
let _map: TaskLocalMap = cast::reinterpret_cast(&map_ptr); // Get and keep the single reference that was created at the
// All local_data will be destroyed along with the map. // beginning.
let _map: TaskLocalMap = cast::reinterpret_cast(&map_ptr);
// All local_data will be destroyed along with the map.
}
} }
// Gets the map from the runtime. Lazily initialises if not done so already. // Gets the map from the runtime. Lazily initialises if not done so already.

View file

@ -114,17 +114,21 @@ impl<A: ToStr Copy, B: ToStr Copy, C: ToStr Copy> (A, B, C): ToStr {
impl<A: ToStr> ~[A]: ToStr { impl<A: ToStr> ~[A]: ToStr {
#[inline(always)] #[inline(always)]
pure fn to_str() -> ~str unsafe { pure fn to_str() -> ~str {
// Bleh -- not really unsafe unsafe {
// push_str and push_char // Bleh -- not really unsafe
let mut acc = ~"[", first = true; // push_str and push_char
for vec::each(self) |elt| unsafe { let mut acc = ~"[", first = true;
if first { first = false; } for vec::each(self) |elt| {
else { str::push_str(&mut acc, ~", "); } unsafe {
str::push_str(&mut acc, elt.to_str()); if first { first = false; }
else { str::push_str(&mut acc, ~", "); }
str::push_str(&mut acc, elt.to_str());
}
}
str::push_char(&mut acc, ']');
move acc
} }
str::push_char(&mut acc, ']');
move acc
} }
} }

View file

@ -450,51 +450,52 @@ pub pure fn partitioned<T: Copy>(v: &[T], f: fn(&T) -> bool) -> (~[T], ~[T]) {
// Mutators // Mutators
/// Removes the first element from a vector and return it /// Removes the first element from a vector and return it
pub fn shift<T>(v: &mut ~[T]) -> T unsafe { pub fn shift<T>(v: &mut ~[T]) -> T {
unsafe {
assert v.is_not_empty();
assert v.is_not_empty(); if v.len() == 1 { return v.pop() }
if v.len() == 1 { return v.pop() } if v.len() == 2 {
let last = v.pop();
let first = v.pop();
v.push(last);
return first;
}
if v.len() == 2 { let ln = v.len();
let last = v.pop(); let next_ln = v.len() - 1;
let first = v.pop();
v.push(last); // Save the last element. We're going to overwrite its position
return first; let mut work_elt = v.pop();
// We still should have room to work where what last element was
assert capacity(v) >= ln;
// Pretend like we have the original length so we can use
// the vector copy_memory to overwrite the hole we just made
raw::set_len(&mut *v, ln);
// Memcopy the head element (the one we want) to the location we just
// popped. For the moment it unsafely exists at both the head and last
// positions
let first_slice = view(*v, 0, 1);
let last_slice = mut_view(*v, next_ln, ln);
raw::copy_memory(last_slice, first_slice, 1);
// Memcopy everything to the left one element
let init_slice = mut_view(*v, 0, next_ln);
let tail_slice = view(*v, 1, ln);
raw::copy_memory(init_slice, tail_slice, next_ln);
// Set the new length. Now the vector is back to normal
raw::set_len(&mut *v, next_ln);
// Swap out the element we want from the end
let vp = raw::to_mut_ptr(*v);
let vp = ptr::mut_offset(vp, next_ln - 1);
*vp <-> work_elt;
return work_elt;
} }
let ln = v.len();
let next_ln = v.len() - 1;
// Save the last element. We're going to overwrite its position
let mut work_elt = v.pop();
// We still should have room to work where what last element was
assert capacity(v) >= ln;
// Pretend like we have the original length so we can use
// the vector copy_memory to overwrite the hole we just made
raw::set_len(&mut *v, ln);
// Memcopy the head element (the one we want) to the location we just
// popped. For the moment it unsafely exists at both the head and last
// positions
let first_slice = view(*v, 0, 1);
let last_slice = mut_view(*v, next_ln, ln);
raw::copy_memory(last_slice, first_slice, 1);
// Memcopy everything to the left one element
let init_slice = mut_view(*v, 0, next_ln);
let tail_slice = view(*v, 1, ln);
raw::copy_memory(init_slice, tail_slice, next_ln);
// Set the new length. Now the vector is back to normal
raw::set_len(&mut *v, next_ln);
// Swap out the element we want from the end
let vp = raw::to_mut_ptr(*v);
let vp = ptr::mut_offset(vp, next_ln - 1);
*vp <-> work_elt;
return work_elt;
} }
/// Prepend an element to the vector /// Prepend an element to the vector
@ -532,23 +533,25 @@ pub fn remove<T>(v: &mut ~[T], i: uint) -> T {
v.pop() v.pop()
} }
pub fn consume<T>(v: ~[T], f: fn(uint, v: T)) unsafe { pub fn consume<T>(v: ~[T], f: fn(uint, v: T)) {
let mut v = v; // FIXME(#3488) unsafe {
let mut v = v; // FIXME(#3488)
do as_mut_buf(v) |p, ln| { do as_mut_buf(v) |p, ln| {
for uint::range(0, ln) |i| { for uint::range(0, ln) |i| {
// NB: This unsafe operation counts on init writing 0s to the // NB: This unsafe operation counts on init writing 0s to the
// holes we create in the vector. That ensures that, if the // holes we create in the vector. That ensures that, if the
// iterator fails then we won't try to clean up the consumed // iterator fails then we won't try to clean up the consumed
// elements during unwinding // elements during unwinding
let mut x = rusti::init(); let mut x = rusti::init();
let p = ptr::mut_offset(p, i); let p = ptr::mut_offset(p, i);
x <-> *p; x <-> *p;
f(i, x); f(i, x);
}
} }
}
raw::set_len(&mut v, 0); raw::set_len(&mut v, 0);
}
} }
pub fn consume_mut<T>(v: ~[mut T], f: fn(uint, v: T)) { pub fn consume_mut<T>(v: ~[mut T], f: fn(uint, v: T)) {
@ -666,36 +669,39 @@ pub fn truncate<T>(v: &mut ~[T], newlen: uint) {
* Remove consecutive repeated elements from a vector; if the vector is * Remove consecutive repeated elements from a vector; if the vector is
* sorted, this removes all duplicates. * sorted, this removes all duplicates.
*/ */
pub fn dedup<T: Eq>(v: &mut ~[T]) unsafe { pub fn dedup<T: Eq>(v: &mut ~[T]) {
if v.len() < 1 { return; } unsafe {
let mut last_written = 0, next_to_read = 1; if v.len() < 1 { return; }
do as_const_buf(*v) |p, ln| { let mut last_written = 0, next_to_read = 1;
// We have a mutable reference to v, so we can make arbitrary changes. do as_const_buf(*v) |p, ln| {
// (cf. push and pop) // We have a mutable reference to v, so we can make arbitrary
let p = p as *mut T; // changes. (cf. push and pop)
// last_written < next_to_read <= ln let p = p as *mut T;
while next_to_read < ln {
// last_written < next_to_read < ln
if *ptr::mut_offset(p, next_to_read) ==
*ptr::mut_offset(p, last_written) {
// FIXME #4204 Should be rusti::uninit() - don't need to zero
let mut dropped = rusti::init();
dropped <-> *ptr::mut_offset(p, next_to_read);
} else {
last_written += 1;
// last_written <= next_to_read < ln
if next_to_read != last_written {
*ptr::mut_offset(p, last_written) <->
*ptr::mut_offset(p, next_to_read);
}
}
// last_written <= next_to_read < ln
next_to_read += 1;
// last_written < next_to_read <= ln // last_written < next_to_read <= ln
while next_to_read < ln {
// last_written < next_to_read < ln
if *ptr::mut_offset(p, next_to_read) ==
*ptr::mut_offset(p, last_written) {
// FIXME #4204 Should be rusti::uninit() - don't need to
// zero
let mut dropped = rusti::init();
dropped <-> *ptr::mut_offset(p, next_to_read);
} else {
last_written += 1;
// last_written <= next_to_read < ln
if next_to_read != last_written {
*ptr::mut_offset(p, last_written) <->
*ptr::mut_offset(p, next_to_read);
}
}
// last_written <= next_to_read < ln
next_to_read += 1;
// last_written < next_to_read <= ln
}
} }
// last_written < next_to_read == ln
raw::set_len(v, last_written + 1);
} }
// last_written < next_to_read == ln
raw::set_len(v, last_written + 1);
} }
@ -1215,7 +1221,9 @@ pub pure fn zip_slice<T: Copy, U: Copy>(v: &[const T], u: &[const U])
let sz = len(v); let sz = len(v);
let mut i = 0u; let mut i = 0u;
assert sz == len(u); assert sz == len(u);
while i < sz unsafe { zipped.push((v[i], u[i])); i += 1u; } while i < sz {
unsafe { zipped.push((v[i], u[i])); i += 1u; }
}
zipped zipped
} }
@ -1454,8 +1462,10 @@ pub pure fn windowed<TT: Copy>(nn: uint, xx: &[TT]) -> ~[~[TT]] {
assert 1u <= nn; assert 1u <= nn;
for vec::eachi (xx) |ii, _x| { for vec::eachi (xx) |ii, _x| {
let len = vec::len(xx); let len = vec::len(xx);
if ii+nn <= len unsafe { if ii+nn <= len {
ww.push(vec::slice(xx, ii, ii+nn)); unsafe {
ww.push(vec::slice(xx, ii, ii+nn));
}
} }
} }
ww ww
@ -3909,10 +3919,12 @@ mod tests {
#[test] #[test]
#[should_fail] #[should_fail]
#[ignore(cfg(windows))] #[ignore(cfg(windows))]
fn test_copy_memory_oob() unsafe { fn test_copy_memory_oob() {
let a = [mut 1, 2, 3, 4]; unsafe {
let b = [1, 2, 3, 4, 5]; let a = [mut 1, 2, 3, 4];
raw::copy_memory(a, b, 5); let b = [1, 2, 3, 4, 5];
raw::copy_memory(a, b, 5);
}
} }
} }

View file

@ -59,12 +59,14 @@ impl output_type : cmp::Eq {
pure fn ne(&self, other: &output_type) -> bool { !(*self).eq(other) } pure fn ne(&self, other: &output_type) -> bool { !(*self).eq(other) }
} }
pub fn llvm_err(sess: Session, +msg: ~str) -> ! unsafe { pub fn llvm_err(sess: Session, +msg: ~str) -> ! {
let cstr = llvm::LLVMRustGetLastError(); unsafe {
if cstr == ptr::null() { let cstr = llvm::LLVMRustGetLastError();
sess.fatal(msg); if cstr == ptr::null() {
} else { sess.fatal(msg);
sess.fatal(msg + ~": " + str::raw::from_c_str(cstr)); } else {
sess.fatal(msg + ~": " + str::raw::from_c_str(cstr));
}
} }
} }
@ -121,50 +123,52 @@ pub mod jit {
pm: PassManagerRef, pm: PassManagerRef,
m: ModuleRef, m: ModuleRef,
opt: c_int, opt: c_int,
stacks: bool) unsafe { stacks: bool) {
let manager = llvm::LLVMRustPrepareJIT(rusti::morestack_addr()); unsafe {
let manager = llvm::LLVMRustPrepareJIT(rusti::morestack_addr());
// We need to tell JIT where to resolve all linked // We need to tell JIT where to resolve all linked
// symbols from. The equivalent of -lstd, -lcore, etc. // symbols from. The equivalent of -lstd, -lcore, etc.
// By default the JIT will resolve symbols from the std and // By default the JIT will resolve symbols from the std and
// core linked into rustc. We don't want that, // core linked into rustc. We don't want that,
// incase the user wants to use an older std library. // incase the user wants to use an older std library.
let cstore = sess.cstore; let cstore = sess.cstore;
for cstore::get_used_crate_files(cstore).each |cratepath| { for cstore::get_used_crate_files(cstore).each |cratepath| {
let path = cratepath.to_str(); let path = cratepath.to_str();
debug!("linking: %s", path); debug!("linking: %s", path);
let _: () = str::as_c_str( let _: () = str::as_c_str(
path, path,
|buf_t| { |buf_t| {
if !llvm::LLVMRustLoadCrate(manager, buf_t) { if !llvm::LLVMRustLoadCrate(manager, buf_t) {
llvm_err(sess, ~"Could not link"); llvm_err(sess, ~"Could not link");
} }
debug!("linked: %s", path); debug!("linked: %s", path);
}); });
} }
// The execute function will return a void pointer // The execute function will return a void pointer
// to the _rust_main function. We can do closure // to the _rust_main function. We can do closure
// magic here to turn it straight into a callable rust // magic here to turn it straight into a callable rust
// closure. It will also cleanup the memory manager // closure. It will also cleanup the memory manager
// for us. // for us.
let entry = llvm::LLVMRustExecuteJIT(manager, let entry = llvm::LLVMRustExecuteJIT(manager,
pm, m, opt, stacks); pm, m, opt, stacks);
if ptr::is_null(entry) { if ptr::is_null(entry) {
llvm_err(sess, ~"Could not JIT"); llvm_err(sess, ~"Could not JIT");
} else { } else {
let closure = Closure { let closure = Closure {
code: entry, code: entry,
env: ptr::null() env: ptr::null()
}; };
let func: fn(++argv: ~[~str]) = cast::transmute(move closure); let func: fn(++argv: ~[~str]) = cast::transmute(move closure);
func(~[/*bad*/copy sess.opts.binary]); func(~[/*bad*/copy sess.opts.binary]);
}
} }
} }
} }
@ -576,8 +580,10 @@ fn build_link_meta(sess: Session, c: &ast::crate, output: &Path,
return {name: name, vers: vers, extras_hash: extras_hash}; return {name: name, vers: vers, extras_hash: extras_hash};
} }
fn truncated_hash_result(symbol_hasher: &hash::State) -> ~str unsafe { fn truncated_hash_result(symbol_hasher: &hash::State) -> ~str {
symbol_hasher.result_str() unsafe {
symbol_hasher.result_str()
}
} }

View file

@ -1386,7 +1386,7 @@ fn float_width(llt: TypeRef) -> uint {
} }
} }
fn fn_ty_param_tys(fn_ty: TypeRef) -> ~[TypeRef] unsafe { fn fn_ty_param_tys(fn_ty: TypeRef) -> ~[TypeRef] {
unsafe { unsafe {
let args = vec::from_elem(llvm::LLVMCountParamTypes(fn_ty) as uint, let args = vec::from_elem(llvm::LLVMCountParamTypes(fn_ty) as uint,
0 as TypeRef); 0 as TypeRef);

View file

@ -201,51 +201,53 @@ fn metadata_matches(extern_metas: ~[@ast::meta_item],
} }
fn get_metadata_section(os: os, fn get_metadata_section(os: os,
filename: &Path) -> Option<@~[u8]> unsafe { filename: &Path) -> Option<@~[u8]> {
let mb = str::as_c_str(filename.to_str(), |buf| { unsafe {
llvm::LLVMRustCreateMemoryBufferWithContentsOfFile(buf) let mb = str::as_c_str(filename.to_str(), |buf| {
}); llvm::LLVMRustCreateMemoryBufferWithContentsOfFile(buf)
if mb as int == 0 { return option::None::<@~[u8]>; } });
let of = match mk_object_file(mb) { if mb as int == 0 { return option::None::<@~[u8]>; }
option::Some(of) => of, let of = match mk_object_file(mb) {
_ => return option::None::<@~[u8]> option::Some(of) => of,
}; _ => return option::None::<@~[u8]>
let si = mk_section_iter(of.llof); };
while llvm::LLVMIsSectionIteratorAtEnd(of.llof, si.llsi) == False { let si = mk_section_iter(of.llof);
let name_buf = llvm::LLVMGetSectionName(si.llsi); while llvm::LLVMIsSectionIteratorAtEnd(of.llof, si.llsi) == False {
let name = unsafe { str::raw::from_c_str(name_buf) }; let name_buf = llvm::LLVMGetSectionName(si.llsi);
if name == meta_section_name(os) { let name = unsafe { str::raw::from_c_str(name_buf) };
let cbuf = llvm::LLVMGetSectionContents(si.llsi); if name == meta_section_name(os) {
let csz = llvm::LLVMGetSectionSize(si.llsi) as uint; let cbuf = llvm::LLVMGetSectionContents(si.llsi);
let mut found = None; let csz = llvm::LLVMGetSectionSize(si.llsi) as uint;
unsafe { let mut found = None;
let cvbuf: *u8 = cast::reinterpret_cast(&cbuf); unsafe {
let vlen = vec::len(encoder::metadata_encoding_version); let cvbuf: *u8 = cast::reinterpret_cast(&cbuf);
debug!("checking %u bytes of metadata-version stamp", let vlen = vec::len(encoder::metadata_encoding_version);
vlen); debug!("checking %u bytes of metadata-version stamp",
let minsz = uint::min(vlen, csz); vlen);
let mut version_ok = false; let minsz = uint::min(vlen, csz);
do vec::raw::buf_as_slice(cvbuf, minsz) |buf0| { let mut version_ok = false;
version_ok = (buf0 == do vec::raw::buf_as_slice(cvbuf, minsz) |buf0| {
encoder::metadata_encoding_version); version_ok = (buf0 ==
} encoder::metadata_encoding_version);
if !version_ok { return None; } }
if !version_ok { return None; }
let cvbuf1 = ptr::offset(cvbuf, vlen); let cvbuf1 = ptr::offset(cvbuf, vlen);
debug!("inflating %u bytes of compressed metadata", debug!("inflating %u bytes of compressed metadata",
csz - vlen); csz - vlen);
do vec::raw::buf_as_slice(cvbuf1, csz-vlen) |bytes| { do vec::raw::buf_as_slice(cvbuf1, csz-vlen) |bytes| {
let inflated = flate::inflate_bytes(bytes); let inflated = flate::inflate_bytes(bytes);
found = move Some(@(move inflated)); found = move Some(@(move inflated));
} }
if found != None { if found != None {
return found; return found;
}
} }
} }
llvm::LLVMMoveToNextSection(si.llsi);
} }
llvm::LLVMMoveToNextSection(si.llsi); return option::None::<@~[u8]>;
} }
return option::None::<@~[u8]>;
} }
fn meta_section_name(os: os) -> ~str { fn meta_section_name(os: os) -> ~str {

View file

@ -2255,14 +2255,16 @@ fn create_main_wrapper(ccx: @crate_ctxt, sp: span, main_llfn: ValueRef) {
val_ty(crate_map)], ccx.int_type); val_ty(crate_map)], ccx.int_type);
let start = decl_cdecl_fn(ccx.llmod, ~"rust_start", start_ty); let start = decl_cdecl_fn(ccx.llmod, ~"rust_start", start_ty);
let args = if ccx.sess.building_library unsafe { let args = unsafe {
~[rust_main, if ccx.sess.building_library {
llvm::LLVMConstInt(T_i32(), 0u as c_ulonglong, False), ~[rust_main,
llvm::LLVMConstInt(T_i32(), 0u as c_ulonglong, False), llvm::LLVMConstInt(T_i32(), 0u as c_ulonglong, False),
crate_map] llvm::LLVMConstInt(T_i32(), 0u as c_ulonglong, False),
} else unsafe { crate_map]
~[rust_main, llvm::LLVMGetParam(llfn, 0 as c_uint), } else {
llvm::LLVMGetParam(llfn, 1 as c_uint), crate_map] ~[rust_main, llvm::LLVMGetParam(llfn, 0 as c_uint),
llvm::LLVMGetParam(llfn, 1 as c_uint), crate_map]
}
}; };
let result = unsafe { let result = unsafe {

View file

@ -176,9 +176,11 @@ fn IndirectBr(cx: block, Addr: ValueRef, NumDests: uint) {
// This is a really awful way to get a zero-length c-string, but better (and a // This is a really awful way to get a zero-length c-string, but better (and a
// lot more efficient) than doing str::as_c_str("", ...) every time. // lot more efficient) than doing str::as_c_str("", ...) every time.
fn noname() -> *libc::c_char unsafe { fn noname() -> *libc::c_char {
const cnull: uint = 0u; unsafe {
return cast::reinterpret_cast(&ptr::addr_of(&cnull)); const cnull: uint = 0u;
return cast::reinterpret_cast(&ptr::addr_of(&cnull));
}
} }
fn Invoke(cx: block, Fn: ValueRef, Args: ~[ValueRef], fn Invoke(cx: block, Fn: ValueRef, Args: ~[ValueRef],

View file

@ -660,7 +660,7 @@ fn val_str(tn: type_names, v: ValueRef) -> @str {
} }
// Returns the nth element of the given LLVM structure type. // Returns the nth element of the given LLVM structure type.
fn struct_elt(llstructty: TypeRef, n: uint) -> TypeRef unsafe { fn struct_elt(llstructty: TypeRef, n: uint) -> TypeRef {
unsafe { unsafe {
let elt_count = llvm::LLVMCountStructElementTypes(llstructty) as uint; let elt_count = llvm::LLVMCountStructElementTypes(llstructty) as uint;
assert (n < elt_count); assert (n < elt_count);
@ -832,10 +832,12 @@ fn T_size_t(targ_cfg: @session::config) -> TypeRef {
return T_int(targ_cfg); return T_int(targ_cfg);
} }
fn T_fn(inputs: ~[TypeRef], output: TypeRef) -> TypeRef unsafe { fn T_fn(inputs: ~[TypeRef], output: TypeRef) -> TypeRef {
return llvm::LLVMFunctionType(output, to_ptr(inputs), unsafe {
inputs.len() as c_uint, return llvm::LLVMFunctionType(output, to_ptr(inputs),
False); inputs.len() as c_uint,
False);
}
} }
fn T_fn_pair(cx: @crate_ctxt, tfn: TypeRef) -> TypeRef { fn T_fn_pair(cx: @crate_ctxt, tfn: TypeRef) -> TypeRef {
@ -854,7 +856,7 @@ fn T_root(t: TypeRef, addrspace: addrspace) -> TypeRef {
} }
} }
fn T_struct(elts: ~[TypeRef]) -> TypeRef unsafe { fn T_struct(elts: ~[TypeRef]) -> TypeRef {
unsafe { unsafe {
return llvm::LLVMStructType(to_ptr(elts), return llvm::LLVMStructType(to_ptr(elts),
elts.len() as c_uint, elts.len() as c_uint,
@ -869,7 +871,7 @@ fn T_named_struct(name: ~str) -> TypeRef {
} }
} }
fn set_struct_body(t: TypeRef, elts: ~[TypeRef]) unsafe { fn set_struct_body(t: TypeRef, elts: ~[TypeRef]) {
unsafe { unsafe {
llvm::LLVMStructSetBody(t, llvm::LLVMStructSetBody(t,
to_ptr(elts), to_ptr(elts),
@ -908,7 +910,7 @@ fn T_task(targ_cfg: @session::config) -> TypeRef {
return t; return t;
} }
fn T_tydesc_field(cx: @crate_ctxt, field: uint) -> TypeRef unsafe { fn T_tydesc_field(cx: @crate_ctxt, field: uint) -> TypeRef {
// Bit of a kludge: pick the fn typeref out of the tydesc.. // Bit of a kludge: pick the fn typeref out of the tydesc..
unsafe { unsafe {
@ -1188,7 +1190,7 @@ fn C_postr(s: ~str) -> ValueRef {
} }
} }
fn C_zero_byte_arr(size: uint) -> ValueRef unsafe { fn C_zero_byte_arr(size: uint) -> ValueRef {
unsafe { unsafe {
let mut i = 0u; let mut i = 0u;
let mut elts: ~[ValueRef] = ~[]; let mut elts: ~[ValueRef] = ~[];
@ -1215,14 +1217,14 @@ fn C_named_struct(T: TypeRef, elts: &[ValueRef]) -> ValueRef {
} }
} }
fn C_array(ty: TypeRef, elts: ~[ValueRef]) -> ValueRef unsafe { fn C_array(ty: TypeRef, elts: ~[ValueRef]) -> ValueRef {
unsafe { unsafe {
return llvm::LLVMConstArray(ty, vec::raw::to_ptr(elts), return llvm::LLVMConstArray(ty, vec::raw::to_ptr(elts),
elts.len() as c_uint); elts.len() as c_uint);
} }
} }
fn C_bytes(bytes: ~[u8]) -> ValueRef unsafe { fn C_bytes(bytes: ~[u8]) -> ValueRef {
unsafe { unsafe {
return llvm::LLVMConstString( return llvm::LLVMConstString(
cast::reinterpret_cast(&vec::raw::to_ptr(bytes)), cast::reinterpret_cast(&vec::raw::to_ptr(bytes)),
@ -1230,7 +1232,7 @@ fn C_bytes(bytes: ~[u8]) -> ValueRef unsafe {
} }
} }
fn C_bytes_plus_null(bytes: ~[u8]) -> ValueRef unsafe { fn C_bytes_plus_null(bytes: ~[u8]) -> ValueRef {
unsafe { unsafe {
return llvm::LLVMConstString( return llvm::LLVMConstString(
cast::reinterpret_cast(&vec::raw::to_ptr(bytes)), cast::reinterpret_cast(&vec::raw::to_ptr(bytes)),

View file

@ -86,7 +86,7 @@ fn lli64(val: int) -> ValueRef {
fn lli1(bval: bool) -> ValueRef { fn lli1(bval: bool) -> ValueRef {
C_bool(bval) C_bool(bval)
} }
fn llmdnode(elems: ~[ValueRef]) -> ValueRef unsafe { fn llmdnode(elems: ~[ValueRef]) -> ValueRef {
unsafe { unsafe {
llvm::LLVMMDNode(vec::raw::to_ptr(elems), llvm::LLVMMDNode(vec::raw::to_ptr(elems),
vec::len(elems) as libc::c_uint) vec::len(elems) as libc::c_uint)
@ -95,8 +95,10 @@ fn llmdnode(elems: ~[ValueRef]) -> ValueRef unsafe {
fn llunused() -> ValueRef { fn llunused() -> ValueRef {
lli32(0x0) lli32(0x0)
} }
fn llnull() -> ValueRef unsafe { fn llnull() -> ValueRef {
cast::reinterpret_cast(&ptr::null::<ValueRef>()) unsafe {
cast::reinterpret_cast(&ptr::null::<ValueRef>())
}
} }
fn add_named_metadata(cx: @crate_ctxt, name: ~str, val: ValueRef) { fn add_named_metadata(cx: @crate_ctxt, name: ~str, val: ValueRef) {
@ -154,68 +156,75 @@ enum debug_metadata {
retval_metadata(@metadata<retval_md>), retval_metadata(@metadata<retval_md>),
} }
fn cast_safely<T: Copy, U>(val: T) -> U unsafe { fn cast_safely<T: Copy, U>(val: T) -> U {
let val2 = val; unsafe {
return cast::transmute(move val2); let val2 = val;
return cast::transmute(move val2);
}
} }
fn md_from_metadata<T>(val: debug_metadata) -> T unsafe { fn md_from_metadata<T>(val: debug_metadata) -> T {
match val { unsafe {
file_metadata(md) => cast_safely(md), match val {
compile_unit_metadata(md) => cast_safely(md), file_metadata(md) => cast_safely(md),
subprogram_metadata(md) => cast_safely(md), compile_unit_metadata(md) => cast_safely(md),
local_var_metadata(md) => cast_safely(md), subprogram_metadata(md) => cast_safely(md),
tydesc_metadata(md) => cast_safely(md), local_var_metadata(md) => cast_safely(md),
block_metadata(md) => cast_safely(md), tydesc_metadata(md) => cast_safely(md),
argument_metadata(md) => cast_safely(md), block_metadata(md) => cast_safely(md),
retval_metadata(md) => cast_safely(md) argument_metadata(md) => cast_safely(md),
retval_metadata(md) => cast_safely(md)
}
} }
} }
fn cached_metadata<T: Copy>(cache: metadata_cache, mdtag: int, fn cached_metadata<T: Copy>(cache: metadata_cache, mdtag: int,
eq: fn(md: T) -> bool) -> Option<T> unsafe { eq: fn(md: T) -> bool) -> Option<T> {
if cache.contains_key(mdtag) { unsafe {
let items = cache.get(mdtag); if cache.contains_key(mdtag) {
for items.each |item| { let items = cache.get(mdtag);
let md: T = md_from_metadata::<T>(*item); for items.each |item| {
if eq(md) { let md: T = md_from_metadata::<T>(*item);
return option::Some(md); if eq(md) {
return option::Some(md);
}
} }
} }
return option::None;
} }
return option::None;
} }
fn create_compile_unit(cx: @crate_ctxt) fn create_compile_unit(cx: @crate_ctxt) -> @metadata<compile_unit_md> {
-> @metadata<compile_unit_md> unsafe { unsafe {
let cache = get_cache(cx); let cache = get_cache(cx);
let crate_name = /*bad*/copy (/*bad*/copy cx.dbg_cx).get().crate_file; let crate_name = /*bad*/copy (/*bad*/copy cx.dbg_cx).get().crate_file;
let tg = CompileUnitTag; let tg = CompileUnitTag;
match cached_metadata::<@metadata<compile_unit_md>>(cache, tg, match cached_metadata::<@metadata<compile_unit_md>>(cache, tg,
|md| md.data.name == crate_name) { |md| md.data.name == crate_name) {
option::Some(md) => return md, option::Some(md) => return md,
option::None => () option::None => ()
}
let (_, work_dir) = get_file_path_and_dir(
cx.sess.working_dir.to_str(), crate_name);
let unit_metadata = ~[lltag(tg),
llunused(),
lli32(DW_LANG_RUST),
llstr(copy crate_name),
llstr(work_dir),
llstr(env!("CFG_VERSION")),
lli1(true), // deprecated: main compile unit
lli1(cx.sess.opts.optimize != session::No),
llstr(~""), // flags (???)
lli32(0) // runtime version (???)
];
let unit_node = llmdnode(unit_metadata);
add_named_metadata(cx, ~"llvm.dbg.cu", unit_node);
let mdval = @{node: unit_node, data: {name: crate_name}};
update_cache(cache, tg, compile_unit_metadata(mdval));
return mdval;
} }
let (_, work_dir) = get_file_path_and_dir(cx.sess.working_dir.to_str(),
crate_name);
let unit_metadata = ~[lltag(tg),
llunused(),
lli32(DW_LANG_RUST),
llstr(copy crate_name),
llstr(work_dir),
llstr(env!("CFG_VERSION")),
lli1(true), // deprecated: main compile unit
lli1(cx.sess.opts.optimize != session::No),
llstr(~""), // flags (???)
lli32(0) // runtime version (???)
];
let unit_node = llmdnode(unit_metadata);
add_named_metadata(cx, ~"llvm.dbg.cu", unit_node);
let mdval = @{node: unit_node, data: {name: crate_name}};
update_cache(cache, tg, compile_unit_metadata(mdval));
return mdval;
} }
fn get_cache(cx: @crate_ctxt) -> metadata_cache { fn get_cache(cx: @crate_ctxt) -> metadata_cache {
@ -646,94 +655,99 @@ fn create_var(type_tag: int, context: ValueRef, +name: ~str, file: ValueRef,
} }
fn create_local_var(bcx: block, local: @ast::local) fn create_local_var(bcx: block, local: @ast::local)
-> @metadata<local_var_md> unsafe { -> @metadata<local_var_md> {
let cx = bcx.ccx(); unsafe {
let cache = get_cache(cx); let cx = bcx.ccx();
let tg = AutoVariableTag; let cache = get_cache(cx);
match cached_metadata::<@metadata<local_var_md>>( let tg = AutoVariableTag;
cache, tg, |md| md.data.id == local.node.id) { match cached_metadata::<@metadata<local_var_md>>(
option::Some(md) => return md, cache, tg, |md| md.data.id == local.node.id) {
option::None => () option::Some(md) => return md,
} option::None => ()
let name = match local.node.pat.node {
ast::pat_ident(_, pth, _) => ast_util::path_to_ident(pth),
// FIXME this should be handled (#2533)
_ => fail ~"no single variable name for local"
};
let loc = cx.sess.codemap.lookup_char_pos(local.span.lo);
let ty = node_id_type(bcx, local.node.id);
let tymd = create_ty(cx, ty, local.node.ty);
let filemd = create_file(cx, /*bad*/copy loc.file.name);
let context = match bcx.parent {
None => create_function(bcx.fcx).node,
Some(_) => create_block(bcx).node
};
let mdnode = create_var(tg, context, cx.sess.str_of(name), filemd.node,
loc.line as int, tymd.node);
let mdval = @{node: mdnode, data: {id: local.node.id}};
update_cache(cache, AutoVariableTag, local_var_metadata(mdval));
let llptr = match bcx.fcx.lllocals.find(local.node.id) {
option::Some(local_mem(v)) => v,
option::Some(_) => {
bcx.tcx().sess.span_bug(local.span, ~"local is bound to \
something weird");
}
option::None => {
match bcx.fcx.lllocals.get(local.node.pat.id) {
local_imm(v) => v,
_ => bcx.tcx().sess.span_bug(local.span, ~"local is bound to \
something weird")
} }
}
}; let name = match local.node.pat.node {
let declargs = ~[llmdnode(~[llptr]), mdnode]; ast::pat_ident(_, pth, _) => ast_util::path_to_ident(pth),
trans::build::Call(bcx, cx.intrinsics.get(~"llvm.dbg.declare"), // FIXME this should be handled (#2533)
declargs); _ => fail ~"no single variable name for local"
return mdval; };
let loc = cx.sess.codemap.lookup_char_pos(local.span.lo);
let ty = node_id_type(bcx, local.node.id);
let tymd = create_ty(cx, ty, local.node.ty);
let filemd = create_file(cx, /*bad*/copy loc.file.name);
let context = match bcx.parent {
None => create_function(bcx.fcx).node,
Some(_) => create_block(bcx).node
};
let mdnode = create_var(tg, context, cx.sess.str_of(name),
filemd.node, loc.line as int, tymd.node);
let mdval = @{node: mdnode, data: {id: local.node.id}};
update_cache(cache, AutoVariableTag, local_var_metadata(mdval));
let llptr = match bcx.fcx.lllocals.find(local.node.id) {
option::Some(local_mem(v)) => v,
option::Some(_) => {
bcx.tcx().sess.span_bug(local.span, ~"local is bound to \
something weird");
}
option::None => {
match bcx.fcx.lllocals.get(local.node.pat.id) {
local_imm(v) => v,
_ => bcx.tcx().sess.span_bug(local.span, ~"local is bound to \
something weird")
}
}
};
let declargs = ~[llmdnode(~[llptr]), mdnode];
trans::build::Call(bcx, cx.intrinsics.get(~"llvm.dbg.declare"),
declargs);
return mdval;
}
} }
fn create_arg(bcx: block, arg: ast::arg, sp: span) fn create_arg(bcx: block, arg: ast::arg, sp: span)
-> Option<@metadata<argument_md>> unsafe { -> Option<@metadata<argument_md>> {
let fcx = bcx.fcx, cx = fcx.ccx; unsafe {
let cache = get_cache(cx); let fcx = bcx.fcx, cx = fcx.ccx;
let tg = ArgVariableTag; let cache = get_cache(cx);
match cached_metadata::<@metadata<argument_md>>( let tg = ArgVariableTag;
cache, ArgVariableTag, |md| md.data.id == arg.id) { match cached_metadata::<@metadata<argument_md>>(
option::Some(md) => return Some(md), cache, ArgVariableTag, |md| md.data.id == arg.id) {
option::None => () option::Some(md) => return Some(md),
} option::None => ()
let loc = cx.sess.codemap.lookup_char_pos(sp.lo);
let ty = node_id_type(bcx, arg.id);
let tymd = create_ty(cx, ty, arg.ty);
let filemd = create_file(cx, /*bad*/copy loc.file.name);
let context = create_function(bcx.fcx);
match arg.pat.node {
ast::pat_ident(_, path, _) => {
// XXX: This is wrong; it should work for multiple bindings.
let mdnode = create_var(tg,
context.node,
cx.sess.str_of(path.idents.last()),
filemd.node,
loc.line as int,
tymd.node);
let mdval = @{node: mdnode, data: {id: arg.id}};
update_cache(cache, tg, argument_metadata(mdval));
let llptr = match fcx.llargs.get(arg.id) {
local_mem(v) | local_imm(v) => v,
};
let declargs = ~[llmdnode(~[llptr]), mdnode];
trans::build::Call(bcx, cx.intrinsics.get(~"llvm.dbg.declare"),
declargs);
return Some(mdval);
} }
_ => {
return None; let loc = cx.sess.codemap.lookup_char_pos(sp.lo);
let ty = node_id_type(bcx, arg.id);
let tymd = create_ty(cx, ty, arg.ty);
let filemd = create_file(cx, /*bad*/copy loc.file.name);
let context = create_function(bcx.fcx);
match arg.pat.node {
ast::pat_ident(_, path, _) => {
// XXX: This is wrong; it should work for multiple bindings.
let mdnode = create_var(tg,
context.node,
cx.sess.str_of(path.idents.last()),
filemd.node,
loc.line as int,
tymd.node);
let mdval = @{node: mdnode, data: {id: arg.id}};
update_cache(cache, tg, argument_metadata(mdval));
let llptr = match fcx.llargs.get(arg.id) {
local_mem(v) | local_imm(v) => v,
};
let declargs = ~[llmdnode(~[llptr]), mdnode];
trans::build::Call(bcx,
cx.intrinsics.get(~"llvm.dbg.declare"),
declargs);
return Some(mdval);
}
_ => {
return None;
}
} }
} }
} }

View file

@ -498,11 +498,13 @@ type t_box = @{sty: sty,
enum t_opaque {} enum t_opaque {}
type t = *t_opaque; type t = *t_opaque;
pure fn get(t: t) -> t_box unsafe { pure fn get(t: t) -> t_box {
let t2 = cast::reinterpret_cast::<t, t_box>(&t); unsafe {
let t3 = t2; let t2 = cast::reinterpret_cast::<t, t_box>(&t);
cast::forget(move t2); let t3 = t2;
t3 cast::forget(move t2);
t3
}
} }
pure fn tbox_has_flag(tb: t_box, flag: tbox_flag) -> bool { pure fn tbox_has_flag(tb: t_box, flag: tbox_flag) -> bool {

View file

@ -141,9 +141,11 @@ impl BigBitv {
let w0 = self.storage[i] & mask; let w0 = self.storage[i] & mask;
let w1 = b.storage[i] & mask; let w1 = b.storage[i] & mask;
let w = op(w0, w1) & mask; let w = op(w0, w1) & mask;
if w0 != w unsafe { if w0 != w {
changed = true; unsafe {
self.storage[i] = w; changed = true;
self.storage[i] = w;
}
} }
true true
} }

View file

@ -219,126 +219,128 @@ pub type Result = result::Result<Matches, Fail_>;
* `opt_str`, etc. to interrogate results. Returns `err(Fail_)` on failure. * `opt_str`, etc. to interrogate results. Returns `err(Fail_)` on failure.
* Use <fail_str> to get an error message. * Use <fail_str> to get an error message.
*/ */
pub fn getopts(args: &[~str], opts: &[Opt]) -> Result unsafe { pub fn getopts(args: &[~str], opts: &[Opt]) -> Result {
let n_opts = opts.len(); unsafe {
fn f(_x: uint) -> ~[Optval] { return ~[]; } let n_opts = opts.len();
let vals = vec::cast_to_mut(vec::from_fn(n_opts, f)); fn f(_x: uint) -> ~[Optval] { return ~[]; }
let mut free: ~[~str] = ~[]; let vals = vec::cast_to_mut(vec::from_fn(n_opts, f));
let l = args.len(); let mut free: ~[~str] = ~[];
let mut i = 0; let l = args.len();
while i < l { let mut i = 0;
let cur = args[i]; while i < l {
let curlen = cur.len(); let cur = args[i];
if !is_arg(cur) { let curlen = cur.len();
free.push(cur); if !is_arg(cur) {
} else if cur == ~"--" { free.push(cur);
let mut j = i + 1; } else if cur == ~"--" {
while j < l { free.push(args[j]); j += 1; } let mut j = i + 1;
break; while j < l { free.push(args[j]); j += 1; }
} else { break;
let mut names;
let mut i_arg = None;
if cur[1] == '-' as u8 {
let tail = str::slice(cur, 2, curlen);
let tail_eq = str::splitn_char(tail, '=', 1);
if tail_eq.len() <= 1 {
names = ~[Long(tail)];
} else {
names =
~[Long(tail_eq[0])];
i_arg = Some(tail_eq[1]);
}
} else { } else {
let mut j = 1; let mut names;
let mut last_valid_opt_id = None; let mut i_arg = None;
names = ~[]; if cur[1] == '-' as u8 {
while j < curlen { let tail = str::slice(cur, 2, curlen);
let range = str::char_range_at(cur, j); let tail_eq = str::splitn_char(tail, '=', 1);
let opt = Short(range.ch); if tail_eq.len() <= 1 {
names = ~[Long(tail)];
} else {
names =
~[Long(tail_eq[0])];
i_arg = Some(tail_eq[1]);
}
} else {
let mut j = 1;
let mut last_valid_opt_id = None;
names = ~[];
while j < curlen {
let range = str::char_range_at(cur, j);
let opt = Short(range.ch);
/* In a series of potential options (eg. -aheJ), if we see /* In a series of potential options (eg. -aheJ), if we
one which takes an argument, we assume all subsequent see one which takes an argument, we assume all
characters make up the argument. This allows options subsequent characters make up the argument. This
such as -L/usr/local/lib/foo to be interpreted allows options such as -L/usr/local/lib/foo to be
correctly interpreted correctly
*/ */
match find_opt(opts, opt) { match find_opt(opts, opt) {
Some(id) => last_valid_opt_id = Some(id), Some(id) => last_valid_opt_id = Some(id),
None => { None => {
let arg_follows = let arg_follows =
last_valid_opt_id.is_some() && last_valid_opt_id.is_some() &&
match opts[last_valid_opt_id.get()] match opts[last_valid_opt_id.get()]
.hasarg { .hasarg {
Yes | Maybe => true, Yes | Maybe => true,
No => false No => false
}; };
if arg_follows && j < curlen { if arg_follows && j < curlen {
i_arg = Some(cur.slice(j, curlen)); i_arg = Some(cur.slice(j, curlen));
break; break;
} else { } else {
last_valid_opt_id = None; last_valid_opt_id = None;
}
}
} }
names.push(opt);
j = range.next;
}
}
let mut name_pos = 0;
for names.each() |nm| {
name_pos += 1;
let optid = match find_opt(opts, *nm) {
Some(id) => id,
None => return Err(UnrecognizedOption(name_str(nm)))
};
match opts[optid].hasarg {
No => {
if !i_arg.is_none() {
return Err(UnexpectedArgument(name_str(nm)));
}
vals[optid].push(Given);
}
Maybe => {
if !i_arg.is_none() {
vals[optid].push(Val(i_arg.get()));
} else if name_pos < names.len() ||
i + 1 == l || is_arg(args[i + 1]) {
vals[optid].push(Given);
} else { i += 1; vals[optid].push(Val(args[i])); }
}
Yes => {
if !i_arg.is_none() {
vals[optid].push(Val(i_arg.get()));
} else if i + 1 == l {
return Err(ArgumentMissing(name_str(nm)));
} else { i += 1; vals[optid].push(Val(args[i])); }
} }
} }
names.push(opt);
j = range.next;
} }
} }
let mut name_pos = 0; i += 1;
for names.each() |nm| { }
name_pos += 1; i = 0u;
let optid = match find_opt(opts, *nm) { while i < n_opts {
Some(id) => id, let n = vals[i].len();
None => return Err(UnrecognizedOption(name_str(nm))) let occ = opts[i].occur;
}; if occ == Req {
match opts[optid].hasarg { if n == 0 {
No => { return Err(OptionMissing(name_str(&(opts[i].name))));
if !i_arg.is_none() {
return Err(UnexpectedArgument(name_str(nm)));
}
vals[optid].push(Given);
}
Maybe => {
if !i_arg.is_none() {
vals[optid].push(Val(i_arg.get()));
} else if name_pos < names.len() ||
i + 1 == l || is_arg(args[i + 1]) {
vals[optid].push(Given);
} else { i += 1; vals[optid].push(Val(args[i])); }
}
Yes => {
if !i_arg.is_none() {
vals[optid].push(Val(i_arg.get()));
} else if i + 1 == l {
return Err(ArgumentMissing(name_str(nm)));
} else { i += 1; vals[optid].push(Val(args[i])); }
}
} }
} }
} if occ != Multi {
i += 1; if n > 1 {
} return Err(OptionDuplicated(name_str(&(opts[i].name))));
i = 0u; }
while i < n_opts {
let n = vals[i].len();
let occ = opts[i].occur;
if occ == Req {
if n == 0 {
return Err(OptionMissing(name_str(&(opts[i].name))));
} }
i += 1;
} }
if occ != Multi { return Ok(Matches {opts: vec::from_slice(opts),
if n > 1 { vals: vec::cast_from_mut(move vals),
return Err(OptionDuplicated(name_str(&(opts[i].name)))); free: free});
}
}
i += 1;
} }
return Ok(Matches {opts: vec::from_slice(opts),
vals: vec::cast_from_mut(move vals),
free: free});
} }
fn opt_vals(mm: &Matches, nm: &str) -> ~[Optval] { fn opt_vals(mm: &Matches, nm: &str) -> ~[Optval] {

View file

@ -337,9 +337,11 @@ pub fn to_writer(wr: io::Writer, json: &Json) {
} }
/// Encodes a json value into a string /// Encodes a json value into a string
pub pure fn to_str(json: &Json) -> ~str unsafe { pub pure fn to_str(json: &Json) -> ~str {
// ugh, should be safe unsafe {
io::with_str_writer(|wr| to_writer(wr, json)) // ugh, should be safe
io::with_str_writer(|wr| to_writer(wr, json))
}
} }
/// Encodes a json value into a io::writer /// Encodes a json value into a io::writer

View file

@ -435,9 +435,11 @@ pub mod chained {
} }
impl<K:Eq IterBytes Hash Copy ToStr, V: ToStr Copy> T<K, V>: ToStr { impl<K:Eq IterBytes Hash Copy ToStr, V: ToStr Copy> T<K, V>: ToStr {
pure fn to_str() -> ~str unsafe { pure fn to_str() -> ~str {
// Meh -- this should be safe unsafe {
do io::with_str_writer |wr| { self.to_writer(wr) } // Meh -- this should be safe
do io::with_str_writer |wr| { self.to_writer(wr) }
}
} }
} }

View file

@ -117,32 +117,36 @@ enum IpGetAddrErr {
pub fn get_addr(node: &str, iotask: iotask) pub fn get_addr(node: &str, iotask: iotask)
-> result::Result<~[IpAddr], IpGetAddrErr> { -> result::Result<~[IpAddr], IpGetAddrErr> {
do oldcomm::listen |output_ch| { do oldcomm::listen |output_ch| {
do str::as_buf(node) |node_ptr, len| unsafe { do str::as_buf(node) |node_ptr, len| {
log(debug, fmt!("slice len %?", len)); unsafe {
let handle = create_uv_getaddrinfo_t(); log(debug, fmt!("slice len %?", len));
let handle_ptr = ptr::addr_of(&handle); let handle = create_uv_getaddrinfo_t();
let handle_data: GetAddrData = { let handle_ptr = ptr::addr_of(&handle);
output_ch: output_ch let handle_data: GetAddrData = {
}; output_ch: output_ch
let handle_data_ptr = ptr::addr_of(&handle_data); };
do interact(iotask) |loop_ptr| unsafe { let handle_data_ptr = ptr::addr_of(&handle_data);
let result = uv_getaddrinfo( do interact(iotask) |loop_ptr| {
loop_ptr, unsafe {
handle_ptr, let result = uv_getaddrinfo(
get_addr_cb, loop_ptr,
node_ptr, handle_ptr,
ptr::null(), get_addr_cb,
ptr::null()); node_ptr,
match result { ptr::null(),
0i32 => { ptr::null());
set_data_for_req(handle_ptr, handle_data_ptr); match result {
} 0i32 => {
_ => { set_data_for_req(handle_ptr, handle_data_ptr);
output_ch.send(result::Err(GetAddrUnknownError)); }
} _ => {
} output_ch.send(result::Err(GetAddrUnknownError));
}; }
output_ch.recv() }
}
};
output_ch.recv()
}
} }
} }
} }
@ -300,62 +304,64 @@ type GetAddrData = {
}; };
extern fn get_addr_cb(handle: *uv_getaddrinfo_t, status: libc::c_int, extern fn get_addr_cb(handle: *uv_getaddrinfo_t, status: libc::c_int,
res: *addrinfo) unsafe { res: *addrinfo) {
log(debug, ~"in get_addr_cb"); unsafe {
let handle_data = get_data_for_req(handle) as log(debug, ~"in get_addr_cb");
*GetAddrData; let handle_data = get_data_for_req(handle) as
if status == 0i32 { *GetAddrData;
if res != (ptr::null::<addrinfo>()) { if status == 0i32 {
let mut out_vec = ~[]; if res != (ptr::null::<addrinfo>()) {
log(debug, fmt!("initial addrinfo: %?", res)); let mut out_vec = ~[];
let mut curr_addr = res; log(debug, fmt!("initial addrinfo: %?", res));
loop { let mut curr_addr = res;
let new_ip_addr = if ll::is_ipv4_addrinfo(curr_addr) { loop {
Ipv4(copy(( let new_ip_addr = if ll::is_ipv4_addrinfo(curr_addr) {
*ll::addrinfo_as_sockaddr_in(curr_addr)))) Ipv4(copy((
} *ll::addrinfo_as_sockaddr_in(curr_addr))))
else if ll::is_ipv6_addrinfo(curr_addr) { }
Ipv6(copy(( else if ll::is_ipv6_addrinfo(curr_addr) {
*ll::addrinfo_as_sockaddr_in6(curr_addr)))) Ipv6(copy((
} *ll::addrinfo_as_sockaddr_in6(curr_addr))))
else { }
log(debug, ~"curr_addr is not of family AF_INET or "+ else {
~"AF_INET6. Error."); log(debug, ~"curr_addr is not of family AF_INET or "+
(*handle_data).output_ch.send( ~"AF_INET6. Error.");
result::Err(GetAddrUnknownError)); (*handle_data).output_ch.send(
break; result::Err(GetAddrUnknownError));
}; break;
out_vec.push(move new_ip_addr); };
out_vec.push(move new_ip_addr);
let next_addr = ll::get_next_addrinfo(curr_addr); let next_addr = ll::get_next_addrinfo(curr_addr);
if next_addr == ptr::null::<addrinfo>() as *addrinfo { if next_addr == ptr::null::<addrinfo>() as *addrinfo {
log(debug, ~"null next_addr encountered. no mas"); log(debug, ~"null next_addr encountered. no mas");
break; break;
} }
else { else {
curr_addr = next_addr; curr_addr = next_addr;
log(debug, fmt!("next_addr addrinfo: %?", curr_addr)); log(debug, fmt!("next_addr addrinfo: %?", curr_addr));
}
} }
log(debug, fmt!("successful process addrinfo result, len: %?",
vec::len(out_vec)));
(*handle_data).output_ch.send(result::Ok(move out_vec));
}
else {
log(debug, ~"addrinfo pointer is NULL");
(*handle_data).output_ch.send(
result::Err(GetAddrUnknownError));
} }
log(debug, fmt!("successful process addrinfo result, len: %?",
vec::len(out_vec)));
(*handle_data).output_ch.send(result::Ok(move out_vec));
} }
else { else {
log(debug, ~"addrinfo pointer is NULL"); log(debug, ~"status != 0 error in get_addr_cb");
(*handle_data).output_ch.send( (*handle_data).output_ch.send(
result::Err(GetAddrUnknownError)); result::Err(GetAddrUnknownError));
} }
if res != (ptr::null::<addrinfo>()) {
uv_freeaddrinfo(res);
}
log(debug, ~"leaving get_addr_cb");
} }
else {
log(debug, ~"status != 0 error in get_addr_cb");
(*handle_data).output_ch.send(
result::Err(GetAddrUnknownError));
}
if res != (ptr::null::<addrinfo>()) {
uv_freeaddrinfo(res);
}
log(debug, ~"leaving get_addr_cb");
} }
#[cfg(test)] #[cfg(test)]

File diff suppressed because it is too large Load diff

View file

@ -361,20 +361,22 @@ pure fn query_from_str(rawquery: &str) -> Query {
return query; return query;
} }
pub pure fn query_to_str(query: &Query) -> ~str unsafe { pub pure fn query_to_str(query: &Query) -> ~str {
// FIXME(#3722): unsafe only because decode_inner does (string) IO unsafe {
let mut strvec = ~[]; // FIXME(#3722): unsafe only because decode_inner does (string) IO
for query.each |kv| { let mut strvec = ~[];
match kv { for query.each |kv| {
&(ref k, ref v) => { match kv {
strvec.push(fmt!("%s=%s", &(ref k, ref v) => {
encode_component(*k), strvec.push(fmt!("%s=%s",
encode_component(*v)) encode_component(*k),
); encode_component(*v))
);
}
} }
} }
return str::connect(strvec, ~"&");
} }
return str::connect(strvec, ~"&");
} }
// returns the scheme and the rest of the url, or a parsing error // returns the scheme and the rest of the url, or a parsing error

View file

@ -131,41 +131,46 @@ impl <T: Ord> PriorityQueue<T> {
// vector over the junk element. This reduces the constant factor // vector over the junk element. This reduces the constant factor
// compared to using swaps, which involves twice as many moves. // compared to using swaps, which involves twice as many moves.
priv fn siftup(&mut self, start: uint, pos: uint) unsafe { priv fn siftup(&mut self, start: uint, pos: uint) {
let mut pos = pos; unsafe {
let new = move *addr_of(&self.data[pos]); let mut pos = pos;
let new = move *addr_of(&self.data[pos]);
while pos > start { while pos > start {
let parent = (pos - 1) >> 1; let parent = (pos - 1) >> 1;
if new > self.data[parent] { if new > self.data[parent] {
rusti::move_val_init(&mut self.data[pos], rusti::move_val_init(&mut self.data[pos],
move *addr_of(&self.data[parent])); move *addr_of(&self.data[parent]));
pos = parent; pos = parent;
loop loop
}
break
} }
break rusti::move_val_init(&mut self.data[pos], move new);
} }
rusti::move_val_init(&mut self.data[pos], move new);
} }
priv fn siftdown_range(&mut self, pos: uint, end: uint) unsafe { priv fn siftdown_range(&mut self, pos: uint, end: uint) {
let mut pos = pos; unsafe {
let start = pos; let mut pos = pos;
let new = move *addr_of(&self.data[pos]); let start = pos;
let new = move *addr_of(&self.data[pos]);
let mut child = 2 * pos + 1; let mut child = 2 * pos + 1;
while child < end { while child < end {
let right = child + 1; let right = child + 1;
if right < end && !(self.data[child] > self.data[right]) { if right < end && !(self.data[child] > self.data[right]) {
child = right; child = right;
}
rusti::move_val_init(&mut self.data[pos],
move *addr_of(&self.data[child]));
pos = child;
child = 2 * pos + 1;
} }
rusti::move_val_init(&mut self.data[pos],
move *addr_of(&self.data[child])); rusti::move_val_init(&mut self.data[pos], move new);
pos = child; self.siftup(start, pos);
child = 2 * pos + 1;
} }
rusti::move_val_init(&mut self.data[pos], move new);
self.siftup(start, pos);
} }
priv fn siftdown(&mut self, pos: uint) { priv fn siftdown(&mut self, pos: uint) {

View file

@ -55,11 +55,13 @@ pub unsafe fn load_history(file: ~str) -> bool {
/// Print out a prompt and then wait for input and return it /// Print out a prompt and then wait for input and return it
pub unsafe fn read(prompt: ~str) -> Option<~str> { pub unsafe fn read(prompt: ~str) -> Option<~str> {
do str::as_c_str(prompt) |buf| unsafe { do str::as_c_str(prompt) |buf| {
let line = rustrt::linenoise(buf); unsafe {
let line = rustrt::linenoise(buf);
if line.is_null() { None } if line.is_null() { None }
else { Some(str::raw::from_c_str(line)) } else { Some(str::raw::from_c_str(line)) }
}
} }
} }
@ -68,18 +70,23 @@ pub type CompletionCb = fn~(~str, fn(~str));
fn complete_key(_v: @CompletionCb) {} fn complete_key(_v: @CompletionCb) {}
/// Bind to the main completion callback /// Bind to the main completion callback
pub unsafe fn complete(cb: CompletionCb) unsafe { pub unsafe fn complete(cb: CompletionCb) {
task::local_data::local_data_set(complete_key, @(move cb)); unsafe {
task::local_data::local_data_set(complete_key, @(move cb));
extern fn callback(line: *c_char, completions: *()) unsafe { extern fn callback(line: *c_char, completions: *()) {
let cb = copy *task::local_data::local_data_get(complete_key).get(); unsafe {
let cb = copy *task::local_data::local_data_get(complete_key)
.get();
do cb(str::raw::from_c_str(line)) |suggestion| { do cb(str::raw::from_c_str(line)) |suggestion| {
do str::as_c_str(suggestion) |buf| { do str::as_c_str(suggestion) |buf| {
rustrt::linenoiseAddCompletion(completions, buf); rustrt::linenoiseAddCompletion(completions, buf);
}
}
} }
} }
}
rustrt::linenoiseSetCompletionCallback(callback); rustrt::linenoiseSetCompletionCallback(callback);
}
} }

View file

@ -831,28 +831,30 @@ pub mod node {
return forest[0]; return forest[0];
} }
pub fn serialize_node(node: @Node) -> ~str unsafe { pub fn serialize_node(node: @Node) -> ~str {
let mut buf = vec::cast_to_mut(vec::from_elem(byte_len(node), 0u8)); unsafe {
let mut offset = 0u;//Current position in the buffer let mut buf = vec::cast_to_mut(vec::from_elem(byte_len(node), 0));
let it = leaf_iterator::start(node); let mut offset = 0u;//Current position in the buffer
loop { let it = leaf_iterator::start(node);
match (leaf_iterator::next(&it)) { loop {
option::None => break, match (leaf_iterator::next(&it)) {
option::Some(x) => { option::None => break,
//FIXME (#2744): Replace with memcpy or something similar option::Some(x) => {
let mut local_buf: ~[u8] = //FIXME (#2744): Replace with memcpy or something similar
cast::reinterpret_cast(&*x.content); let mut local_buf: ~[u8] =
let mut i = x.byte_offset; cast::reinterpret_cast(&*x.content);
while i < x.byte_len { let mut i = x.byte_offset;
buf[offset] = local_buf[i]; while i < x.byte_len {
offset += 1u; buf[offset] = local_buf[i];
i += 1u; offset += 1u;
i += 1u;
}
cast::forget(move local_buf);
}
} }
cast::forget(move local_buf);
}
} }
return cast::transmute(move buf);
} }
return cast::transmute(move buf);
} }
/** /**
@ -862,17 +864,19 @@ pub mod node {
* *
* This function executes in linear time. * This function executes in linear time.
*/ */
pub fn flatten(node: @Node) -> @Node unsafe { pub fn flatten(node: @Node) -> @Node {
match (*node) { unsafe {
Leaf(_) => return node, match (*node) {
Concat(ref x) => { Leaf(_) => return node,
return @Leaf({ Concat(ref x) => {
byte_offset: 0u, return @Leaf({
byte_len: x.byte_len, byte_offset: 0u,
char_len: x.char_len, byte_len: x.byte_len,
content: @serialize_node(node) char_len: x.char_len,
}) content: @serialize_node(node)
} })
}
}
} }
} }
@ -1284,17 +1288,19 @@ mod tests {
node::Empty => return ~"", node::Empty => return ~"",
node::Content(x) => { node::Content(x) => {
let str = @mut ~""; let str = @mut ~"";
fn aux(str: @mut ~str, node: @node::Node) unsafe { fn aux(str: @mut ~str, node: @node::Node) {
match (*node) { unsafe {
node::Leaf(x) => { match (*node) {
*str += str::slice( node::Leaf(x) => {
*x.content, x.byte_offset, *str += str::slice(
x.byte_offset + x.byte_len); *x.content, x.byte_offset,
} x.byte_offset + x.byte_len);
node::Concat(ref x) => { }
aux(str, x.left); node::Concat(ref x) => {
aux(str, x.right); aux(str, x.left);
} aux(str, x.right);
}
}
} }
} }
aux(str, x); aux(str, x);

View file

@ -282,97 +282,99 @@ mod tests {
use core::vec; use core::vec;
#[test] #[test]
fn test() unsafe { fn test() {
type Test = {input: ~str, output: ~[u8]}; unsafe {
type Test = {input: ~str, output: ~[u8]};
fn a_million_letter_a() -> ~str { fn a_million_letter_a() -> ~str {
let mut i = 0; let mut i = 0;
let mut rs = ~""; let mut rs = ~"";
while i < 100000 { while i < 100000 {
str::push_str(&mut rs, ~"aaaaaaaaaa"); str::push_str(&mut rs, ~"aaaaaaaaaa");
i += 1; i += 1;
}
return rs;
} }
return rs; // Test messages from FIPS 180-1
}
// Test messages from FIPS 180-1
let fips_180_1_tests: ~[Test] = let fips_180_1_tests: ~[Test] =
~[{input: ~"abc", ~[{input: ~"abc",
output: output:
~[0xA9u8, 0x99u8, 0x3Eu8, 0x36u8, ~[0xA9u8, 0x99u8, 0x3Eu8, 0x36u8,
0x47u8, 0x06u8, 0x81u8, 0x6Au8, 0x47u8, 0x06u8, 0x81u8, 0x6Au8,
0xBAu8, 0x3Eu8, 0x25u8, 0x71u8, 0xBAu8, 0x3Eu8, 0x25u8, 0x71u8,
0x78u8, 0x50u8, 0xC2u8, 0x6Cu8, 0x78u8, 0x50u8, 0xC2u8, 0x6Cu8,
0x9Cu8, 0xD0u8, 0xD8u8, 0x9Du8]}, 0x9Cu8, 0xD0u8, 0xD8u8, 0x9Du8]},
{input: {input:
~"abcdbcdecdefdefgefghfghighij" + ~"abcdbcdecdefdefgefghfghighij" +
~"hijkijkljklmklmnlmnomnopnopq", ~"hijkijkljklmklmnlmnomnopnopq",
output: output:
~[0x84u8, 0x98u8, 0x3Eu8, 0x44u8, ~[0x84u8, 0x98u8, 0x3Eu8, 0x44u8,
0x1Cu8, 0x3Bu8, 0xD2u8, 0x6Eu8, 0x1Cu8, 0x3Bu8, 0xD2u8, 0x6Eu8,
0xBAu8, 0xAEu8, 0x4Au8, 0xA1u8, 0xBAu8, 0xAEu8, 0x4Au8, 0xA1u8,
0xF9u8, 0x51u8, 0x29u8, 0xE5u8, 0xF9u8, 0x51u8, 0x29u8, 0xE5u8,
0xE5u8, 0x46u8, 0x70u8, 0xF1u8]}, 0xE5u8, 0x46u8, 0x70u8, 0xF1u8]},
{input: a_million_letter_a(), {input: a_million_letter_a(),
output: output:
~[0x34u8, 0xAAu8, 0x97u8, 0x3Cu8, ~[0x34u8, 0xAAu8, 0x97u8, 0x3Cu8,
0xD4u8, 0xC4u8, 0xDAu8, 0xA4u8, 0xD4u8, 0xC4u8, 0xDAu8, 0xA4u8,
0xF6u8, 0x1Eu8, 0xEBu8, 0x2Bu8, 0xF6u8, 0x1Eu8, 0xEBu8, 0x2Bu8,
0xDBu8, 0xADu8, 0x27u8, 0x31u8, 0xDBu8, 0xADu8, 0x27u8, 0x31u8,
0x65u8, 0x34u8, 0x01u8, 0x6Fu8]}]; 0x65u8, 0x34u8, 0x01u8, 0x6Fu8]}];
// Examples from wikipedia // Examples from wikipedia
let wikipedia_tests: ~[Test] = let wikipedia_tests: ~[Test] =
~[{input: ~"The quick brown fox jumps over the lazy dog", ~[{input: ~"The quick brown fox jumps over the lazy dog",
output: output:
~[0x2fu8, 0xd4u8, 0xe1u8, 0xc6u8, ~[0x2fu8, 0xd4u8, 0xe1u8, 0xc6u8,
0x7au8, 0x2du8, 0x28u8, 0xfcu8, 0x7au8, 0x2du8, 0x28u8, 0xfcu8,
0xedu8, 0x84u8, 0x9eu8, 0xe1u8, 0xedu8, 0x84u8, 0x9eu8, 0xe1u8,
0xbbu8, 0x76u8, 0xe7u8, 0x39u8, 0xbbu8, 0x76u8, 0xe7u8, 0x39u8,
0x1bu8, 0x93u8, 0xebu8, 0x12u8]}, 0x1bu8, 0x93u8, 0xebu8, 0x12u8]},
{input: ~"The quick brown fox jumps over the lazy cog", {input: ~"The quick brown fox jumps over the lazy cog",
output: output:
~[0xdeu8, 0x9fu8, 0x2cu8, 0x7fu8, ~[0xdeu8, 0x9fu8, 0x2cu8, 0x7fu8,
0xd2u8, 0x5eu8, 0x1bu8, 0x3au8, 0xd2u8, 0x5eu8, 0x1bu8, 0x3au8,
0xfau8, 0xd3u8, 0xe8u8, 0x5au8, 0xfau8, 0xd3u8, 0xe8u8, 0x5au8,
0x0bu8, 0xd1u8, 0x7du8, 0x9bu8, 0x0bu8, 0xd1u8, 0x7du8, 0x9bu8,
0x10u8, 0x0du8, 0xb4u8, 0xb3u8]}]; 0x10u8, 0x0du8, 0xb4u8, 0xb3u8]}];
let tests = fips_180_1_tests + wikipedia_tests; let tests = fips_180_1_tests + wikipedia_tests;
fn check_vec_eq(v0: ~[u8], v1: ~[u8]) { fn check_vec_eq(v0: ~[u8], v1: ~[u8]) {
assert (vec::len::<u8>(v0) == vec::len::<u8>(v1)); assert (vec::len::<u8>(v0) == vec::len::<u8>(v1));
let len = vec::len::<u8>(v0); let len = vec::len::<u8>(v0);
let mut i = 0u; let mut i = 0u;
while i < len { while i < len {
let a = v0[i]; let a = v0[i];
let b = v1[i]; let b = v1[i];
assert (a == b); assert (a == b);
i += 1u; i += 1u;
}
} }
} // Test that it works when accepting the message all at once
// Test that it works when accepting the message all at once
let sh = sha1::sha1(); let sh = sha1::sha1();
for vec::each(tests) |t| { for vec::each(tests) |t| {
sh.input_str(t.input); sh.input_str(t.input);
let out = sh.result(); let out = sh.result();
check_vec_eq(t.output, out); check_vec_eq(t.output, out);
sh.reset(); sh.reset();
} }
// Test that it works when accepting the message in pieces // Test that it works when accepting the message in pieces
for vec::each(tests) |t| { for vec::each(tests) |t| {
let len = str::len(t.input); let len = str::len(t.input);
let mut left = len; let mut left = len;
while left > 0u { while left > 0u {
let take = (left + 1u) / 2u; let take = (left + 1u) / 2u;
sh.input_str(str::slice(t.input, len - left, sh.input_str(str::slice(t.input, len - left,
take + len - left)); take + len - left));
left = left - take; left = left - take;
}
let out = sh.result();
check_vec_eq(t.output, out);
sh.reset();
} }
let out = sh.result();
check_vec_eq(t.output, out);
sh.reset();
} }
} }

View file

@ -49,26 +49,28 @@ pub fn delayed_send<T: Owned>(iotask: IoTask,
let timer_done_ch_ptr = ptr::addr_of(&timer_done_ch); let timer_done_ch_ptr = ptr::addr_of(&timer_done_ch);
let timer = uv::ll::timer_t(); let timer = uv::ll::timer_t();
let timer_ptr = ptr::addr_of(&timer); let timer_ptr = ptr::addr_of(&timer);
do iotask::interact(iotask) |loop_ptr| unsafe { do iotask::interact(iotask) |loop_ptr| {
let init_result = uv::ll::timer_init(loop_ptr, timer_ptr); unsafe {
if (init_result == 0i32) { let init_result = uv::ll::timer_init(loop_ptr, timer_ptr);
let start_result = uv::ll::timer_start( if (init_result == 0i32) {
timer_ptr, delayed_send_cb, msecs, 0u); let start_result = uv::ll::timer_start(
if (start_result == 0i32) { timer_ptr, delayed_send_cb, msecs, 0u);
uv::ll::set_data_for_uv_handle( if (start_result == 0i32) {
timer_ptr, uv::ll::set_data_for_uv_handle(
timer_done_ch_ptr as *libc::c_void); timer_ptr,
} timer_done_ch_ptr as *libc::c_void);
else { } else {
let error_msg = uv::ll::get_last_err_info(
loop_ptr);
fail ~"timer::delayed_send() start failed: " +
error_msg;
}
} else {
let error_msg = uv::ll::get_last_err_info(loop_ptr); let error_msg = uv::ll::get_last_err_info(loop_ptr);
fail ~"timer::delayed_send() start failed: " + fail ~"timer::delayed_send() init failed: " +
error_msg; error_msg;
} }
} }
else {
let error_msg = uv::ll::get_last_err_info(loop_ptr);
fail ~"timer::delayed_send() init failed: "+error_msg;
}
}; };
// delayed_send_cb has been processed by libuv // delayed_send_cb has been processed by libuv
oldcomm::recv(timer_done_po); oldcomm::recv(timer_done_po);
@ -138,27 +140,31 @@ pub fn recv_timeout<T: Copy Owned>(iotask: IoTask,
// INTERNAL API // INTERNAL API
extern fn delayed_send_cb(handle: *uv::ll::uv_timer_t, extern fn delayed_send_cb(handle: *uv::ll::uv_timer_t,
status: libc::c_int) unsafe { status: libc::c_int) {
log(debug, fmt!("delayed_send_cb handle %? status %?", handle, status)); unsafe {
let timer_done_ch = log(debug,
*(uv::ll::get_data_for_uv_handle(handle) as *oldcomm::Chan<()>); fmt!("delayed_send_cb handle %? status %?", handle, status));
let stop_result = uv::ll::timer_stop(handle); let timer_done_ch =
if (stop_result == 0i32) { *(uv::ll::get_data_for_uv_handle(handle) as *oldcomm::Chan<()>);
oldcomm::send(timer_done_ch, ()); let stop_result = uv::ll::timer_stop(handle);
uv::ll::close(handle, delayed_send_close_cb); if (stop_result == 0i32) {
} oldcomm::send(timer_done_ch, ());
else { uv::ll::close(handle, delayed_send_close_cb);
let loop_ptr = uv::ll::get_loop_for_uv_handle(handle); } else {
let error_msg = uv::ll::get_last_err_info(loop_ptr); let loop_ptr = uv::ll::get_loop_for_uv_handle(handle);
fail ~"timer::sleep() init failed: "+error_msg; let error_msg = uv::ll::get_last_err_info(loop_ptr);
fail ~"timer::sleep() init failed: "+error_msg;
}
} }
} }
extern fn delayed_send_close_cb(handle: *uv::ll::uv_timer_t) unsafe { extern fn delayed_send_close_cb(handle: *uv::ll::uv_timer_t) {
log(debug, fmt!("delayed_send_close_cb handle %?", handle)); unsafe {
let timer_done_ch = log(debug, fmt!("delayed_send_close_cb handle %?", handle));
*(uv::ll::get_data_for_uv_handle(handle) as *oldcomm::Chan<()>); let timer_done_ch =
oldcomm::send(timer_done_ch, ()); *(uv::ll::get_data_for_uv_handle(handle) as *oldcomm::Chan<()>);
oldcomm::send(timer_done_ch, ());
}
} }
#[cfg(test)] #[cfg(test)]

View file

@ -51,14 +51,16 @@ impl <K: Eq Ord, V: Eq> TreeMap<K, V>: Eq {
} else { } else {
let mut x = self.iter(); let mut x = self.iter();
let mut y = other.iter(); let mut y = other.iter();
for self.len().times unsafe { // unsafe as a purity workaround for self.len().times {
// ICE: x.next() != y.next() unsafe { // unsafe as a purity workaround
// ICE: x.next() != y.next()
let (x1, x2) = x.next().unwrap(); let (x1, x2) = x.next().unwrap();
let (y1, y2) = y.next().unwrap(); let (y1, y2) = y.next().unwrap();
if x1 != y1 || x2 != y2 { if x1 != y1 || x2 != y2 {
return false return false
}
} }
} }
true true

View file

@ -47,55 +47,59 @@ pub fn get() -> IoTask {
} }
#[doc(hidden)] #[doc(hidden)]
fn get_monitor_task_gl() -> IoTask unsafe { fn get_monitor_task_gl() -> IoTask {
unsafe {
let monitor_loop_chan_ptr =
rustrt::rust_uv_get_kernel_global_chan_ptr();
let monitor_loop_chan_ptr = rustrt::rust_uv_get_kernel_global_chan_ptr(); debug!("ENTERING global_loop::get() loop chan: %?",
monitor_loop_chan_ptr);
debug!("ENTERING global_loop::get() loop chan: %?", debug!("before priv::chan_from_global_ptr");
monitor_loop_chan_ptr); type MonChan = Chan<IoTask>;
debug!("before priv::chan_from_global_ptr"); let monitor_ch =
type MonChan = Chan<IoTask>; do chan_from_global_ptr::<MonChan>(monitor_loop_chan_ptr,
|| {
task::task().sched_mode
(task::SingleThreaded)
.unlinked()
}) |msg_po| {
unsafe {
debug!("global monitor task starting");
let monitor_ch = // As a weak task the runtime will notify us when to exit
do chan_from_global_ptr::<MonChan>(monitor_loop_chan_ptr, do weaken_task() |weak_exit_po| {
|| { debug!("global monitor task is now weak");
task::task().sched_mode let hl_loop = spawn_loop();
(task::SingleThreaded) loop {
.unlinked() debug!("in outer_loop...");
}) |msg_po| unsafe { match select2(weak_exit_po, msg_po) {
debug!("global monitor task starting"); Left(weak_exit) => {
// all normal tasks have ended, tell the
// As a weak task the runtime will notify us when to exit // libuv loop to tear_down, then exit
do weaken_task() |weak_exit_po| { debug!("weak_exit_po recv'd msg: %?", weak_exit);
debug!("global monitor task is now weak"); iotask::exit(hl_loop);
let hl_loop = spawn_loop(); break;
loop { }
debug!("in outer_loop..."); Right(fetch_ch) => {
match select2(weak_exit_po, msg_po) { debug!("hl_loop req recv'd: %?", fetch_ch);
Left(weak_exit) => { fetch_ch.send(hl_loop);
// all normal tasks have ended, tell the }
// libuv loop to tear_down, then exit }
debug!("weak_exit_po recv'd msg: %?", weak_exit); }
iotask::exit(hl_loop); debug!("global monitor task is leaving weakend state");
break; };
} debug!("global monitor task exiting");
Right(fetch_ch) => {
debug!("hl_loop req recv'd: %?", fetch_ch);
fetch_ch.send(hl_loop);
}
}
} }
debug!("global monitor task is leaving weakend state");
}; };
debug!("global monitor task exiting");
};
// once we have a chan to the monitor loop, we ask it for // once we have a chan to the monitor loop, we ask it for
// the libuv loop's async handle // the libuv loop's async handle
do listen |fetch_ch| { do listen |fetch_ch| {
monitor_ch.send(fetch_ch); monitor_ch.send(fetch_ch);
fetch_ch.recv() fetch_ch.recv()
}
} }
} }
@ -135,91 +139,107 @@ mod test {
use core::ptr; use core::ptr;
use core::task; use core::task;
extern fn simple_timer_close_cb(timer_ptr: *ll::uv_timer_t) unsafe { extern fn simple_timer_close_cb(timer_ptr: *ll::uv_timer_t) {
let exit_ch_ptr = ll::get_data_for_uv_handle( unsafe {
timer_ptr as *libc::c_void) as *oldcomm::Chan<bool>; let exit_ch_ptr = ll::get_data_for_uv_handle(
let exit_ch = *exit_ch_ptr; timer_ptr as *libc::c_void) as *oldcomm::Chan<bool>;
oldcomm::send(exit_ch, true); let exit_ch = *exit_ch_ptr;
log(debug, fmt!("EXIT_CH_PTR simple_timer_close_cb exit_ch_ptr: %?", oldcomm::send(exit_ch, true);
exit_ch_ptr)); log(debug,
fmt!("EXIT_CH_PTR simple_timer_close_cb exit_ch_ptr: %?",
exit_ch_ptr));
}
} }
extern fn simple_timer_cb(timer_ptr: *ll::uv_timer_t, extern fn simple_timer_cb(timer_ptr: *ll::uv_timer_t,
_status: libc::c_int) unsafe { _status: libc::c_int) {
log(debug, ~"in simple timer cb"); unsafe {
ll::timer_stop(timer_ptr); log(debug, ~"in simple timer cb");
let hl_loop = get_gl(); ll::timer_stop(timer_ptr);
do iotask::interact(hl_loop) |_loop_ptr| unsafe { let hl_loop = get_gl();
log(debug, ~"closing timer"); do iotask::interact(hl_loop) |_loop_ptr| {
ll::close(timer_ptr, simple_timer_close_cb); unsafe {
log(debug, ~"about to deref exit_ch_ptr"); log(debug, ~"closing timer");
log(debug, ~"after msg sent on deref'd exit_ch"); ll::close(timer_ptr, simple_timer_close_cb);
}; log(debug, ~"about to deref exit_ch_ptr");
log(debug, ~"exiting simple timer cb"); log(debug, ~"after msg sent on deref'd exit_ch");
}
};
log(debug, ~"exiting simple timer cb");
}
} }
fn impl_uv_hl_simple_timer(iotask: IoTask) unsafe { fn impl_uv_hl_simple_timer(iotask: IoTask) {
let exit_po = oldcomm::Port::<bool>(); unsafe {
let exit_ch = oldcomm::Chan(&exit_po); let exit_po = oldcomm::Port::<bool>();
let exit_ch_ptr = ptr::addr_of(&exit_ch); let exit_ch = oldcomm::Chan(&exit_po);
log(debug, fmt!("EXIT_CH_PTR newly created exit_ch_ptr: %?", let exit_ch_ptr = ptr::addr_of(&exit_ch);
exit_ch_ptr)); log(debug, fmt!("EXIT_CH_PTR newly created exit_ch_ptr: %?",
let timer_handle = ll::timer_t(); exit_ch_ptr));
let timer_ptr = ptr::addr_of(&timer_handle); let timer_handle = ll::timer_t();
do iotask::interact(iotask) |loop_ptr| unsafe { let timer_ptr = ptr::addr_of(&timer_handle);
log(debug, ~"user code inside interact loop!!!"); do iotask::interact(iotask) |loop_ptr| {
let init_status = ll::timer_init(loop_ptr, timer_ptr); unsafe {
if(init_status == 0i32) { log(debug, ~"user code inside interact loop!!!");
ll::set_data_for_uv_handle( let init_status = ll::timer_init(loop_ptr, timer_ptr);
timer_ptr as *libc::c_void, if(init_status == 0i32) {
exit_ch_ptr as *libc::c_void); ll::set_data_for_uv_handle(
let start_status = ll::timer_start(timer_ptr, simple_timer_cb, timer_ptr as *libc::c_void,
1u, 0u); exit_ch_ptr as *libc::c_void);
if(start_status == 0i32) { let start_status = ll::timer_start(timer_ptr,
simple_timer_cb,
1u,
0u);
if start_status != 0 {
fail ~"failure on ll::timer_start()";
}
} else {
fail ~"failure on ll::timer_init()";
}
} }
else { };
fail ~"failure on ll::timer_start()"; oldcomm::recv(exit_po);
} log(debug,
} ~"global_loop timer test: msg recv on exit_po, done..");
else { }
fail ~"failure on ll::timer_init()";
}
};
oldcomm::recv(exit_po);
log(debug, ~"global_loop timer test: msg recv on exit_po, done..");
} }
#[test] #[test]
fn test_gl_uv_global_loop_high_level_global_timer() unsafe { fn test_gl_uv_global_loop_high_level_global_timer() {
let hl_loop = get_gl(); unsafe {
let exit_po = oldcomm::Port::<()>(); let hl_loop = get_gl();
let exit_ch = oldcomm::Chan(&exit_po); let exit_po = oldcomm::Port::<()>();
task::spawn_sched(task::ManualThreads(1u), || { let exit_ch = oldcomm::Chan(&exit_po);
task::spawn_sched(task::ManualThreads(1u), || {
impl_uv_hl_simple_timer(hl_loop);
oldcomm::send(exit_ch, ());
});
impl_uv_hl_simple_timer(hl_loop); impl_uv_hl_simple_timer(hl_loop);
oldcomm::send(exit_ch, ()); oldcomm::recv(exit_po);
}); }
impl_uv_hl_simple_timer(hl_loop);
oldcomm::recv(exit_po);
} }
// keeping this test ignored until some kind of stress-test-harness // keeping this test ignored until some kind of stress-test-harness
// is set up for the build bots // is set up for the build bots
#[test] #[test]
#[ignore] #[ignore]
fn test_stress_gl_uv_global_loop_high_level_global_timer() unsafe { fn test_stress_gl_uv_global_loop_high_level_global_timer() {
let hl_loop = get_gl(); unsafe {
let exit_po = oldcomm::Port::<()>(); let hl_loop = get_gl();
let exit_ch = oldcomm::Chan(&exit_po); let exit_po = oldcomm::Port::<()>();
let cycles = 5000u; let exit_ch = oldcomm::Chan(&exit_po);
for iter::repeat(cycles) { let cycles = 5000u;
task::spawn_sched(task::ManualThreads(1u), || { for iter::repeat(cycles) {
impl_uv_hl_simple_timer(hl_loop); task::spawn_sched(task::ManualThreads(1u), || {
oldcomm::send(exit_ch, ()); impl_uv_hl_simple_timer(hl_loop);
}); oldcomm::send(exit_ch, ());
}; });
for iter::repeat(cycles) { };
oldcomm::recv(exit_po); for iter::repeat(cycles) {
}; oldcomm::recv(exit_po);
log(debug, ~"test_stress_gl_uv_global_loop_high_level_global_timer"+ };
~" exiting sucessfully!"); log(debug,
~"test_stress_gl_uv_global_loop_high_level_global_timer"+
~" exiting sucessfully!");
}
} }
} }

View file

@ -83,8 +83,10 @@ pub unsafe fn interact(iotask: IoTask,
* async handle and do a sanity check to make sure that all other handles are * async handle and do a sanity check to make sure that all other handles are
* closed, causing a failure otherwise. * closed, causing a failure otherwise.
*/ */
pub fn exit(iotask: IoTask) unsafe { pub fn exit(iotask: IoTask) {
send_msg(iotask, TeardownLoop); unsafe {
send_msg(iotask, TeardownLoop);
}
} }
@ -96,38 +98,39 @@ enum IoTaskMsg {
} }
/// Run the loop and begin handling messages /// Run the loop and begin handling messages
fn run_loop(iotask_ch: Chan<IoTask>) unsafe { fn run_loop(iotask_ch: Chan<IoTask>) {
unsafe {
let loop_ptr = ll::loop_new();
let loop_ptr = ll::loop_new(); // set up the special async handle we'll use to allow multi-task
// communication with this loop
let async = ll::async_t();
let async_handle = addr_of(&async);
// set up the special async handle we'll use to allow multi-task // associate the async handle with the loop
// communication with this loop ll::async_init(loop_ptr, async_handle, wake_up_cb);
let async = ll::async_t();
let async_handle = addr_of(&async);
// associate the async handle with the loop // initialize our loop data and store it in the loop
ll::async_init(loop_ptr, async_handle, wake_up_cb); let data: IoTaskLoopData = {
async_handle: async_handle,
msg_po: Port()
};
ll::set_data_for_uv_handle(async_handle, addr_of(&data));
// initialize our loop data and store it in the loop // Send out a handle through which folks can talk to us
let data: IoTaskLoopData = { // while we dwell in the I/O loop
async_handle: async_handle, let iotask = IoTask_({
msg_po: Port() async_handle: async_handle,
}; op_chan: data.msg_po.chan()
ll::set_data_for_uv_handle(async_handle, addr_of(&data)); });
iotask_ch.send(iotask);
// Send out a handle through which folks can talk to us log(debug, ~"about to run uv loop");
// while we dwell in the I/O loop // enter the loop... this blocks until the loop is done..
let iotask = IoTask_({ ll::run(loop_ptr);
async_handle: async_handle, log(debug, ~"uv loop ended");
op_chan: data.msg_po.chan() ll::loop_delete(loop_ptr);
}); }
iotask_ch.send(iotask);
log(debug, ~"about to run uv loop");
// enter the loop... this blocks until the loop is done..
ll::run(loop_ptr);
log(debug, ~"uv loop ended");
ll::loop_delete(loop_ptr);
} }
// data that lives for the lifetime of the high-evel oo // data that lives for the lifetime of the high-evel oo
@ -136,43 +139,51 @@ type IoTaskLoopData = {
msg_po: Port<IoTaskMsg> msg_po: Port<IoTaskMsg>
}; };
fn send_msg(iotask: IoTask, fn send_msg(iotask: IoTask, msg: IoTaskMsg) {
msg: IoTaskMsg) unsafe { unsafe {
iotask.op_chan.send(move msg); iotask.op_chan.send(move msg);
ll::async_send(iotask.async_handle); ll::async_send(iotask.async_handle);
}
} }
/// Dispatch all pending messages /// Dispatch all pending messages
extern fn wake_up_cb(async_handle: *ll::uv_async_t, extern fn wake_up_cb(async_handle: *ll::uv_async_t,
status: int) unsafe { status: int) {
unsafe {
log(debug, fmt!("wake_up_cb extern.. handle: %? status: %?",
async_handle, status));
log(debug, fmt!("wake_up_cb extern.. handle: %? status: %?", let loop_ptr = ll::get_loop_for_uv_handle(async_handle);
async_handle, status)); let data = ll::get_data_for_uv_handle(async_handle)
as *IoTaskLoopData;
let msg_po = (*data).msg_po;
let loop_ptr = ll::get_loop_for_uv_handle(async_handle); while msg_po.peek() {
let data = ll::get_data_for_uv_handle(async_handle) as *IoTaskLoopData; match msg_po.recv() {
let msg_po = (*data).msg_po; Interaction(ref cb) => (*cb)(loop_ptr),
TeardownLoop => begin_teardown(data)
while msg_po.peek() { }
match msg_po.recv() {
Interaction(ref cb) => (*cb)(loop_ptr),
TeardownLoop => begin_teardown(data)
} }
} }
} }
fn begin_teardown(data: *IoTaskLoopData) unsafe { fn begin_teardown(data: *IoTaskLoopData) {
log(debug, ~"iotask begin_teardown() called, close async_handle"); unsafe {
let async_handle = (*data).async_handle; log(debug, ~"iotask begin_teardown() called, close async_handle");
ll::close(async_handle as *c_void, tear_down_close_cb); let async_handle = (*data).async_handle;
ll::close(async_handle as *c_void, tear_down_close_cb);
}
} }
extern fn tear_down_close_cb(handle: *ll::uv_async_t) unsafe { extern fn tear_down_close_cb(handle: *ll::uv_async_t) {
let loop_ptr = ll::get_loop_for_uv_handle(handle); unsafe {
let loop_refs = ll::loop_refcount(loop_ptr); let loop_ptr = ll::get_loop_for_uv_handle(handle);
log(debug, fmt!("tear_down_close_cb called, closing handle at %? refs %?", let loop_refs = ll::loop_refcount(loop_ptr);
handle, loop_refs)); log(debug,
assert loop_refs == 1i32; fmt!("tear_down_close_cb called, closing handle at %? refs %?",
handle, loop_refs));
assert loop_refs == 1i32;
}
} }
#[cfg(test)] #[cfg(test)]
@ -188,37 +199,46 @@ mod test {
use core::ptr; use core::ptr;
use core::task; use core::task;
extern fn async_close_cb(handle: *ll::uv_async_t) unsafe { extern fn async_close_cb(handle: *ll::uv_async_t) {
log(debug, fmt!("async_close_cb handle %?", handle));
let exit_ch = (*(ll::get_data_for_uv_handle(handle)
as *AhData)).exit_ch;
oldcomm::send(exit_ch, ());
}
extern fn async_handle_cb(handle: *ll::uv_async_t, status: libc::c_int)
unsafe { unsafe {
log(debug, fmt!("async_handle_cb handle %? status %?",handle,status)); log(debug, fmt!("async_close_cb handle %?", handle));
ll::close(handle, async_close_cb); let exit_ch = (*(ll::get_data_for_uv_handle(handle)
as *AhData)).exit_ch;
oldcomm::send(exit_ch, ());
}
}
extern fn async_handle_cb(handle: *ll::uv_async_t, status: libc::c_int) {
unsafe {
log(debug,
fmt!("async_handle_cb handle %? status %?",handle,status));
ll::close(handle, async_close_cb);
}
} }
type AhData = { type AhData = {
iotask: IoTask, iotask: IoTask,
exit_ch: oldcomm::Chan<()> exit_ch: oldcomm::Chan<()>
}; };
fn impl_uv_iotask_async(iotask: IoTask) unsafe { fn impl_uv_iotask_async(iotask: IoTask) {
let async_handle = ll::async_t(); unsafe {
let ah_ptr = ptr::addr_of(&async_handle); let async_handle = ll::async_t();
let exit_po = oldcomm::Port::<()>(); let ah_ptr = ptr::addr_of(&async_handle);
let exit_ch = oldcomm::Chan(&exit_po); let exit_po = oldcomm::Port::<()>();
let ah_data = { let exit_ch = oldcomm::Chan(&exit_po);
iotask: iotask, let ah_data = {
exit_ch: exit_ch iotask: iotask,
}; exit_ch: exit_ch
let ah_data_ptr = ptr::addr_of(&ah_data); };
do interact(iotask) |loop_ptr| unsafe { let ah_data_ptr = ptr::addr_of(&ah_data);
ll::async_init(loop_ptr, ah_ptr, async_handle_cb); do interact(iotask) |loop_ptr| {
ll::set_data_for_uv_handle(ah_ptr, ah_data_ptr as *libc::c_void); unsafe {
ll::async_send(ah_ptr); ll::async_init(loop_ptr, ah_ptr, async_handle_cb);
}; ll::set_data_for_uv_handle(ah_ptr,
oldcomm::recv(exit_po); ah_data_ptr as *libc::c_void);
ll::async_send(ah_ptr);
}
};
oldcomm::recv(exit_po);
}
} }
// this fn documents the bear minimum neccesary to roll your own // this fn documents the bear minimum neccesary to roll your own
@ -233,8 +253,10 @@ mod test {
return oldcomm::recv(iotask_port); return oldcomm::recv(iotask_port);
} }
extern fn lifetime_handle_close(handle: *libc::c_void) unsafe { extern fn lifetime_handle_close(handle: *libc::c_void) {
log(debug, fmt!("lifetime_handle_close ptr %?", handle)); unsafe {
log(debug, fmt!("lifetime_handle_close ptr %?", handle));
}
} }
extern fn lifetime_async_callback(handle: *libc::c_void, extern fn lifetime_async_callback(handle: *libc::c_void,
@ -244,31 +266,33 @@ mod test {
} }
#[test] #[test]
fn test_uv_iotask_async() unsafe { fn test_uv_iotask_async() {
let exit_po = oldcomm::Port::<()>(); unsafe {
let exit_ch = oldcomm::Chan(&exit_po); let exit_po = oldcomm::Port::<()>();
let iotask = spawn_test_loop(exit_ch); let exit_ch = oldcomm::Chan(&exit_po);
let iotask = spawn_test_loop(exit_ch);
// using this handle to manage the lifetime of the high_level_loop, // using this handle to manage the lifetime of the
// as it will exit the first time one of the impl_uv_hl_async() is // high_level_loop, as it will exit the first time one of the
// cleaned up with no one ref'd handles on the loop (Which can happen // impl_uv_hl_async() is cleaned up with no one ref'd handles on
// under race-condition type situations.. this ensures that the loop // the loop (Which can happen under race-condition type
// lives until, at least, all of the impl_uv_hl_async() runs have been // situations.. this ensures that the loop lives until, at least,
// called, at least. // all of the impl_uv_hl_async() runs have been called, at least.
let work_exit_po = oldcomm::Port::<()>(); let work_exit_po = oldcomm::Port::<()>();
let work_exit_ch = oldcomm::Chan(&work_exit_po); let work_exit_ch = oldcomm::Chan(&work_exit_po);
for iter::repeat(7u) { for iter::repeat(7u) {
do task::spawn_sched(task::ManualThreads(1u)) { do task::spawn_sched(task::ManualThreads(1u)) {
impl_uv_iotask_async(iotask); impl_uv_iotask_async(iotask);
oldcomm::send(work_exit_ch, ()); oldcomm::send(work_exit_ch, ());
};
}; };
}; for iter::repeat(7u) {
for iter::repeat(7u) { oldcomm::recv(work_exit_po);
oldcomm::recv(work_exit_po); };
}; log(debug, ~"sending teardown_loop msg..");
log(debug, ~"sending teardown_loop msg.."); exit(iotask);
exit(iotask); oldcomm::recv(exit_po);
oldcomm::recv(exit_po); log(debug, ~"after recv on exit_po.. exiting..");
log(debug, ~"after recv on exit_po.. exiting.."); }
} }
} }

View file

@ -1103,304 +1103,325 @@ pub mod test {
extern fn on_alloc_cb(handle: *libc::c_void, extern fn on_alloc_cb(handle: *libc::c_void,
suggested_size: libc::size_t) suggested_size: libc::size_t)
-> uv_buf_t unsafe { -> uv_buf_t {
log(debug, ~"on_alloc_cb!"); unsafe {
let char_ptr = malloc_buf_base_of(suggested_size); log(debug, ~"on_alloc_cb!");
log(debug, fmt!("on_alloc_cb h: %? char_ptr: %u sugsize: %u", let char_ptr = malloc_buf_base_of(suggested_size);
handle, log(debug, fmt!("on_alloc_cb h: %? char_ptr: %u sugsize: %u",
char_ptr as uint, handle,
suggested_size as uint)); char_ptr as uint,
return buf_init(char_ptr, suggested_size as uint); suggested_size as uint));
return buf_init(char_ptr, suggested_size as uint);
}
} }
extern fn on_read_cb(stream: *uv_stream_t, extern fn on_read_cb(stream: *uv_stream_t,
nread: libc::ssize_t, nread: libc::ssize_t,
++buf: uv_buf_t) unsafe { ++buf: uv_buf_t) {
let nread = nread as int; unsafe {
log(debug, fmt!("CLIENT entering on_read_cb nred: %d", let nread = nread as int;
nread)); log(debug, fmt!("CLIENT entering on_read_cb nred: %d",
if (nread > 0) { nread));
// we have data if (nread > 0) {
log(debug, fmt!("CLIENT read: data! nread: %d", nread)); // we have data
read_stop(stream); log(debug, fmt!("CLIENT read: data! nread: %d", nread));
let client_data = read_stop(stream);
get_data_for_uv_handle(stream as *libc::c_void) let client_data =
as *request_wrapper; get_data_for_uv_handle(stream as *libc::c_void)
let buf_base = get_base_from_buf(buf); as *request_wrapper;
let buf_len = get_len_from_buf(buf); let buf_base = get_base_from_buf(buf);
let bytes = vec::from_buf(buf_base, buf_len as uint); let buf_len = get_len_from_buf(buf);
let read_chan = *((*client_data).read_chan); let bytes = vec::from_buf(buf_base, buf_len as uint);
let msg_from_server = str::from_bytes(bytes); let read_chan = *((*client_data).read_chan);
oldcomm::send(read_chan, msg_from_server); let msg_from_server = str::from_bytes(bytes);
close(stream as *libc::c_void, after_close_cb) oldcomm::send(read_chan, msg_from_server);
close(stream as *libc::c_void, after_close_cb)
}
else if (nread == -1) {
// err .. possibly EOF
log(debug, ~"read: eof!");
}
else {
// nread == 0 .. do nothing, just free buf as below
log(debug, ~"read: do nothing!");
}
// when we're done
free_base_of_buf(buf);
log(debug, ~"CLIENT exiting on_read_cb");
} }
else if (nread == -1) {
// err .. possibly EOF
log(debug, ~"read: eof!");
}
else {
// nread == 0 .. do nothing, just free buf as below
log(debug, ~"read: do nothing!");
}
// when we're done
free_base_of_buf(buf);
log(debug, ~"CLIENT exiting on_read_cb");
} }
extern fn on_write_complete_cb(write_req: *uv_write_t, extern fn on_write_complete_cb(write_req: *uv_write_t,
status: libc::c_int) unsafe { status: libc::c_int) {
log(debug, fmt!("CLIENT beginning on_write_complete_cb status: %d", unsafe {
status as int)); log(debug,
let stream = get_stream_handle_from_write_req(write_req); fmt!("CLIENT beginning on_write_complete_cb status: %d",
log(debug, fmt!("CLIENT on_write_complete_cb: tcp:%d write_handle:%d", status as int));
stream as int, write_req as int)); let stream = get_stream_handle_from_write_req(write_req);
let result = read_start(stream, on_alloc_cb, on_read_cb); log(debug,
log(debug, fmt!("CLIENT ending on_write_complete_cb .. status: %d", fmt!("CLIENT on_write_complete_cb: tcp:%d write_handle:%d",
result as int)); stream as int, write_req as int));
let result = read_start(stream, on_alloc_cb, on_read_cb);
log(debug,
fmt!("CLIENT ending on_write_complete_cb .. status: %d",
result as int));
}
} }
extern fn on_connect_cb(connect_req_ptr: *uv_connect_t, extern fn on_connect_cb(connect_req_ptr: *uv_connect_t,
status: libc::c_int) unsafe { status: libc::c_int) {
log(debug, fmt!("beginning on_connect_cb .. status: %d", unsafe {
status as int)); log(debug, fmt!("beginning on_connect_cb .. status: %d",
let stream = status as int));
get_stream_handle_from_connect_req(connect_req_ptr); let stream =
if (status == 0i32) { get_stream_handle_from_connect_req(connect_req_ptr);
log(debug, ~"on_connect_cb: in status=0 if.."); if (status == 0i32) {
let client_data = get_data_for_req( log(debug, ~"on_connect_cb: in status=0 if..");
connect_req_ptr as *libc::c_void) let client_data = get_data_for_req(
as *request_wrapper; connect_req_ptr as *libc::c_void)
let write_handle = (*client_data).write_req; as *request_wrapper;
log(debug, fmt!("on_connect_cb: tcp: %d write_hdl: %d", let write_handle = (*client_data).write_req;
stream as int, write_handle as int)); log(debug, fmt!("on_connect_cb: tcp: %d write_hdl: %d",
let write_result = write(write_handle, stream as int, write_handle as int));
stream as *libc::c_void, let write_result = write(write_handle,
(*client_data).req_buf, stream as *libc::c_void,
on_write_complete_cb); (*client_data).req_buf,
log(debug, fmt!("on_connect_cb: write() status: %d", on_write_complete_cb);
write_result as int)); log(debug, fmt!("on_connect_cb: write() status: %d",
write_result as int));
}
else {
let test_loop = get_loop_for_uv_handle(
stream as *libc::c_void);
let err_msg = get_last_err_info(test_loop);
log(debug, err_msg);
assert false;
}
log(debug, ~"finishing on_connect_cb");
} }
else {
let test_loop = get_loop_for_uv_handle(
stream as *libc::c_void);
let err_msg = get_last_err_info(test_loop);
log(debug, err_msg);
assert false;
}
log(debug, ~"finishing on_connect_cb");
} }
fn impl_uv_tcp_request(ip: &str, port: int, req_str: &str, fn impl_uv_tcp_request(ip: &str, port: int, req_str: &str,
client_chan: *oldcomm::Chan<~str>) unsafe { client_chan: *oldcomm::Chan<~str>) {
let test_loop = loop_new(); unsafe {
let tcp_handle = tcp_t(); let test_loop = loop_new();
let tcp_handle_ptr = ptr::addr_of(&tcp_handle); let tcp_handle = tcp_t();
let connect_handle = connect_t(); let tcp_handle_ptr = ptr::addr_of(&tcp_handle);
let connect_req_ptr = ptr::addr_of(&connect_handle); let connect_handle = connect_t();
let connect_req_ptr = ptr::addr_of(&connect_handle);
// this is the persistent payload of data that we // this is the persistent payload of data that we
// need to pass around to get this example to work. // need to pass around to get this example to work.
// In C, this would be a malloc'd or stack-allocated // In C, this would be a malloc'd or stack-allocated
// struct that we'd cast to a void* and store as the // struct that we'd cast to a void* and store as the
// data field in our uv_connect_t struct // data field in our uv_connect_t struct
let req_str_bytes = str::to_bytes(req_str); let req_str_bytes = str::to_bytes(req_str);
let req_msg_ptr: *u8 = vec::raw::to_ptr(req_str_bytes); let req_msg_ptr: *u8 = vec::raw::to_ptr(req_str_bytes);
log(debug, fmt!("req_msg ptr: %u", req_msg_ptr as uint)); log(debug, fmt!("req_msg ptr: %u", req_msg_ptr as uint));
let req_msg = ~[ let req_msg = ~[
buf_init(req_msg_ptr, vec::len(req_str_bytes)) buf_init(req_msg_ptr, vec::len(req_str_bytes))
]; ];
// this is the enclosing record, we'll pass a ptr to // this is the enclosing record, we'll pass a ptr to
// this to C.. // this to C..
let write_handle = write_t(); let write_handle = write_t();
let write_handle_ptr = ptr::addr_of(&write_handle); let write_handle_ptr = ptr::addr_of(&write_handle);
log(debug, fmt!("tcp req: tcp stream: %d write_handle: %d", log(debug, fmt!("tcp req: tcp stream: %d write_handle: %d",
tcp_handle_ptr as int, tcp_handle_ptr as int,
write_handle_ptr as int)); write_handle_ptr as int));
let client_data = { writer_handle: write_handle_ptr, let client_data = { writer_handle: write_handle_ptr,
req_buf: ptr::addr_of(&req_msg), req_buf: ptr::addr_of(&req_msg),
read_chan: client_chan }; read_chan: client_chan };
let tcp_init_result = tcp_init( let tcp_init_result = tcp_init(
test_loop as *libc::c_void, tcp_handle_ptr); test_loop as *libc::c_void, tcp_handle_ptr);
if (tcp_init_result == 0i32) { if (tcp_init_result == 0i32) {
log(debug, ~"sucessful tcp_init_result"); log(debug, ~"sucessful tcp_init_result");
log(debug, ~"building addr..."); log(debug, ~"building addr...");
let addr = ip4_addr(ip, port); let addr = ip4_addr(ip, port);
// FIXME ref #2064 // FIXME ref #2064
let addr_ptr = ptr::addr_of(&addr); let addr_ptr = ptr::addr_of(&addr);
log(debug, fmt!("after build addr in rust. port: %u", log(debug, fmt!("after build addr in rust. port: %u",
addr.sin_port as uint)); addr.sin_port as uint));
// this should set up the connection request.. // this should set up the connection request..
log(debug, fmt!("b4 call tcp_connect connect cb: %u ", log(debug, fmt!("b4 call tcp_connect connect cb: %u ",
on_connect_cb as uint)); on_connect_cb as uint));
let tcp_connect_result = tcp_connect( let tcp_connect_result = tcp_connect(
connect_req_ptr, tcp_handle_ptr, connect_req_ptr, tcp_handle_ptr,
addr_ptr, on_connect_cb); addr_ptr, on_connect_cb);
if (tcp_connect_result == 0i32) { if (tcp_connect_result == 0i32) {
// not set the data on the connect_req // not set the data on the connect_req
// until its initialized // until its initialized
set_data_for_req( set_data_for_req(
connect_req_ptr as *libc::c_void, connect_req_ptr as *libc::c_void,
ptr::addr_of(&client_data) as *libc::c_void); ptr::addr_of(&client_data) as *libc::c_void);
set_data_for_uv_handle( set_data_for_uv_handle(
tcp_handle_ptr as *libc::c_void, tcp_handle_ptr as *libc::c_void,
ptr::addr_of(&client_data) as *libc::c_void); ptr::addr_of(&client_data) as *libc::c_void);
log(debug, ~"before run tcp req loop"); log(debug, ~"before run tcp req loop");
run(test_loop); run(test_loop);
log(debug, ~"after run tcp req loop"); log(debug, ~"after run tcp req loop");
}
else {
log(debug, ~"tcp_connect() failure");
assert false;
}
} }
else { else {
log(debug, ~"tcp_connect() failure"); log(debug, ~"tcp_init() failure");
assert false; assert false;
} }
loop_delete(test_loop);
} }
else {
log(debug, ~"tcp_init() failure");
assert false;
}
loop_delete(test_loop);
} }
extern fn server_after_close_cb(handle: *libc::c_void) unsafe { extern fn server_after_close_cb(handle: *libc::c_void) {
log(debug, fmt!("SERVER server stream closed, should exit.. h: %?",
handle));
}
extern fn client_stream_after_close_cb(handle: *libc::c_void)
unsafe { unsafe {
log(debug, log(debug, fmt!("SERVER server stream closed, should exit. h: %?",
~"SERVER: closed client stream, now closing server stream"); handle));
let client_data = get_data_for_uv_handle( }
handle) as
*tcp_server_data;
close((*client_data).server as *libc::c_void,
server_after_close_cb);
} }
extern fn after_server_resp_write(req: *uv_write_t) unsafe { extern fn client_stream_after_close_cb(handle: *libc::c_void) {
let client_stream_ptr = unsafe {
get_stream_handle_from_write_req(req); log(debug,
log(debug, ~"SERVER: resp sent... closing client stream"); ~"SERVER: closed client stream, now closing server stream");
close(client_stream_ptr as *libc::c_void, let client_data = get_data_for_uv_handle(
client_stream_after_close_cb) handle) as
*tcp_server_data;
close((*client_data).server as *libc::c_void,
server_after_close_cb);
}
}
extern fn after_server_resp_write(req: *uv_write_t) {
unsafe {
let client_stream_ptr =
get_stream_handle_from_write_req(req);
log(debug, ~"SERVER: resp sent... closing client stream");
close(client_stream_ptr as *libc::c_void,
client_stream_after_close_cb)
}
} }
extern fn on_server_read_cb(client_stream_ptr: *uv_stream_t, extern fn on_server_read_cb(client_stream_ptr: *uv_stream_t,
nread: libc::ssize_t, nread: libc::ssize_t,
++buf: uv_buf_t) unsafe { ++buf: uv_buf_t) {
let nread = nread as int; unsafe {
if (nread > 0) { let nread = nread as int;
// we have data if (nread > 0) {
log(debug, fmt!("SERVER read: data! nread: %d", nread)); // we have data
log(debug, fmt!("SERVER read: data! nread: %d", nread));
// pull out the contents of the write from the client // pull out the contents of the write from the client
let buf_base = get_base_from_buf(buf); let buf_base = get_base_from_buf(buf);
let buf_len = get_len_from_buf(buf) as uint; let buf_len = get_len_from_buf(buf) as uint;
log(debug, fmt!("SERVER buf base: %u, len: %u, nread: %d", log(debug, fmt!("SERVER buf base: %u, len: %u, nread: %d",
buf_base as uint, buf_base as uint,
buf_len as uint, buf_len as uint,
nread)); nread));
let bytes = vec::from_buf(buf_base, buf_len); let bytes = vec::from_buf(buf_base, buf_len);
let request_str = str::from_bytes(bytes); let request_str = str::from_bytes(bytes);
let client_data = get_data_for_uv_handle( let client_data = get_data_for_uv_handle(
client_stream_ptr as *libc::c_void) as *tcp_server_data; client_stream_ptr as *libc::c_void) as *tcp_server_data;
let server_kill_msg = (*client_data).server_kill_msg; let server_kill_msg = (*client_data).server_kill_msg;
let write_req = (*client_data).server_write_req; let write_req = (*client_data).server_write_req;
if (str::contains(request_str, server_kill_msg)) { if (str::contains(request_str, server_kill_msg)) {
log(debug, ~"SERVER: client req contains kill_msg!"); log(debug, ~"SERVER: client req contains kill_msg!");
log(debug, ~"SERVER: sending response to client"); log(debug, ~"SERVER: sending response to client");
read_stop(client_stream_ptr); read_stop(client_stream_ptr);
let server_chan = *((*client_data).server_chan); let server_chan = *((*client_data).server_chan);
oldcomm::send(server_chan, request_str); oldcomm::send(server_chan, request_str);
let write_result = write( let write_result = write(
write_req, write_req,
client_stream_ptr as *libc::c_void, client_stream_ptr as *libc::c_void,
(*client_data).server_resp_buf, (*client_data).server_resp_buf,
after_server_resp_write); after_server_resp_write);
log(debug, fmt!("SERVER: resp write result: %d", log(debug, fmt!("SERVER: resp write result: %d",
write_result as int)); write_result as int));
if (write_result != 0i32) { if (write_result != 0i32) {
log(debug, ~"bad result for server resp write()"); log(debug, ~"bad result for server resp write()");
log(debug, get_last_err_info( log(debug, get_last_err_info(
get_loop_for_uv_handle(client_stream_ptr get_loop_for_uv_handle(client_stream_ptr
as *libc::c_void))); as *libc::c_void)));
assert false; assert false;
}
}
else {
log(debug, ~"SERVER: client req !contain kill_msg!");
} }
} }
else { else if (nread == -1) {
log(debug, ~"SERVER: client req !contain kill_msg!"); // err .. possibly EOF
log(debug, ~"read: eof!");
} }
else {
// nread == 0 .. do nothing, just free buf as below
log(debug, ~"read: do nothing!");
}
// when we're done
free_base_of_buf(buf);
log(debug, ~"SERVER exiting on_read_cb");
} }
else if (nread == -1) {
// err .. possibly EOF
log(debug, ~"read: eof!");
}
else {
// nread == 0 .. do nothing, just free buf as below
log(debug, ~"read: do nothing!");
}
// when we're done
free_base_of_buf(buf);
log(debug, ~"SERVER exiting on_read_cb");
} }
extern fn server_connection_cb(server_stream_ptr: extern fn server_connection_cb(server_stream_ptr:
*uv_stream_t, *uv_stream_t,
status: libc::c_int) unsafe { status: libc::c_int) {
log(debug, ~"client connecting!"); unsafe {
let test_loop = get_loop_for_uv_handle( log(debug, ~"client connecting!");
server_stream_ptr as *libc::c_void); let test_loop = get_loop_for_uv_handle(
if status != 0i32 { server_stream_ptr as *libc::c_void);
let err_msg = get_last_err_info(test_loop); if status != 0i32 {
log(debug, fmt!("server_connect_cb: non-zero status: %?", let err_msg = get_last_err_info(test_loop);
err_msg)); log(debug, fmt!("server_connect_cb: non-zero status: %?",
return; err_msg));
} return;
let server_data = get_data_for_uv_handle( }
server_stream_ptr as *libc::c_void) as *tcp_server_data; let server_data = get_data_for_uv_handle(
let client_stream_ptr = (*server_data).client; server_stream_ptr as *libc::c_void) as *tcp_server_data;
let client_init_result = tcp_init(test_loop, let client_stream_ptr = (*server_data).client;
client_stream_ptr); let client_init_result = tcp_init(test_loop,
set_data_for_uv_handle( client_stream_ptr);
client_stream_ptr as *libc::c_void, set_data_for_uv_handle(
server_data as *libc::c_void); client_stream_ptr as *libc::c_void,
if (client_init_result == 0i32) { server_data as *libc::c_void);
log(debug, ~"successfully initialized client stream"); if (client_init_result == 0i32) {
let accept_result = accept(server_stream_ptr as log(debug, ~"successfully initialized client stream");
*libc::c_void, let accept_result = accept(server_stream_ptr as
client_stream_ptr as *libc::c_void,
*libc::c_void); client_stream_ptr as
if (accept_result == 0i32) { *libc::c_void);
// start reading if (accept_result == 0i32) {
let read_result = read_start( // start reading
client_stream_ptr as *uv_stream_t, let read_result = read_start(
on_alloc_cb, client_stream_ptr as *uv_stream_t,
on_server_read_cb); on_alloc_cb,
if (read_result == 0i32) { on_server_read_cb);
log(debug, ~"successful server read start"); if (read_result == 0i32) {
log(debug, ~"successful server read start");
}
else {
log(debug, fmt!("server_connection_cb: bad read:%d",
read_result as int));
assert false;
}
} }
else { else {
log(debug, fmt!("server_connection_cb: bad read:%d", log(debug, fmt!("server_connection_cb: bad accept: %d",
read_result as int)); accept_result as int));
assert false; assert false;
} }
} }
else { else {
log(debug, fmt!("server_connection_cb: bad accept: %d", log(debug, fmt!("server_connection_cb: bad client init: %d",
accept_result as int)); client_init_result as int));
assert false; assert false;
} }
} }
else {
log(debug, fmt!("server_connection_cb: bad client init: %d",
client_init_result as int));
assert false;
}
} }
type tcp_server_data = { type tcp_server_data = {
@ -1422,17 +1443,19 @@ pub mod test {
} }
extern fn continue_async_cb(async_handle: *uv_async_t, extern fn continue_async_cb(async_handle: *uv_async_t,
status: libc::c_int) unsafe { status: libc::c_int) {
// once we're in the body of this callback, unsafe {
// the tcp server's loop is set up, so we // once we're in the body of this callback,
// can continue on to let the tcp client // the tcp server's loop is set up, so we
// do its thang // can continue on to let the tcp client
let data = get_data_for_uv_handle( // do its thang
async_handle as *libc::c_void) as *async_handle_data; let data = get_data_for_uv_handle(
let continue_chan = *((*data).continue_chan); async_handle as *libc::c_void) as *async_handle_data;
let should_continue = status == 0i32; let continue_chan = *((*data).continue_chan);
oldcomm::send(continue_chan, should_continue); let should_continue = status == 0i32;
close(async_handle as *libc::c_void, async_close_cb); oldcomm::send(continue_chan, should_continue);
close(async_handle as *libc::c_void, async_close_cb);
}
} }
fn impl_uv_tcp_server(server_ip: &str, fn impl_uv_tcp_server(server_ip: &str,
@ -1440,144 +1463,148 @@ pub mod test {
+kill_server_msg: ~str, +kill_server_msg: ~str,
+server_resp_msg: ~str, +server_resp_msg: ~str,
server_chan: *oldcomm::Chan<~str>, server_chan: *oldcomm::Chan<~str>,
continue_chan: *oldcomm::Chan<bool>) unsafe { continue_chan: *oldcomm::Chan<bool>) {
let test_loop = loop_new(); unsafe {
let tcp_server = tcp_t(); let test_loop = loop_new();
let tcp_server_ptr = ptr::addr_of(&tcp_server); let tcp_server = tcp_t();
let tcp_server_ptr = ptr::addr_of(&tcp_server);
let tcp_client = tcp_t(); let tcp_client = tcp_t();
let tcp_client_ptr = ptr::addr_of(&tcp_client); let tcp_client_ptr = ptr::addr_of(&tcp_client);
let server_write_req = write_t(); let server_write_req = write_t();
let server_write_req_ptr = ptr::addr_of(&server_write_req); let server_write_req_ptr = ptr::addr_of(&server_write_req);
let resp_str_bytes = str::to_bytes(server_resp_msg); let resp_str_bytes = str::to_bytes(server_resp_msg);
let resp_msg_ptr: *u8 = vec::raw::to_ptr(resp_str_bytes); let resp_msg_ptr: *u8 = vec::raw::to_ptr(resp_str_bytes);
log(debug, fmt!("resp_msg ptr: %u", resp_msg_ptr as uint)); log(debug, fmt!("resp_msg ptr: %u", resp_msg_ptr as uint));
let resp_msg = ~[ let resp_msg = ~[
buf_init(resp_msg_ptr, vec::len(resp_str_bytes)) buf_init(resp_msg_ptr, vec::len(resp_str_bytes))
]; ];
let continue_async_handle = async_t(); let continue_async_handle = async_t();
let continue_async_handle_ptr = let continue_async_handle_ptr =
ptr::addr_of(&continue_async_handle); ptr::addr_of(&continue_async_handle);
let async_data = let async_data =
{ continue_chan: continue_chan }; { continue_chan: continue_chan };
let async_data_ptr = ptr::addr_of(&async_data); let async_data_ptr = ptr::addr_of(&async_data);
let server_data: tcp_server_data = { let server_data: tcp_server_data = {
client: tcp_client_ptr, client: tcp_client_ptr,
server: tcp_server_ptr, server: tcp_server_ptr,
server_kill_msg: kill_server_msg, server_kill_msg: kill_server_msg,
server_resp_buf: ptr::addr_of(&resp_msg), server_resp_buf: ptr::addr_of(&resp_msg),
server_chan: server_chan, server_chan: server_chan,
server_write_req: server_write_req_ptr server_write_req: server_write_req_ptr
}; };
let server_data_ptr = ptr::addr_of(&server_data); let server_data_ptr = ptr::addr_of(&server_data);
set_data_for_uv_handle(tcp_server_ptr as *libc::c_void, set_data_for_uv_handle(tcp_server_ptr as *libc::c_void,
server_data_ptr as *libc::c_void); server_data_ptr as *libc::c_void);
// uv_tcp_init() // uv_tcp_init()
let tcp_init_result = tcp_init( let tcp_init_result = tcp_init(
test_loop as *libc::c_void, tcp_server_ptr); test_loop as *libc::c_void, tcp_server_ptr);
if (tcp_init_result == 0i32) { if (tcp_init_result == 0i32) {
let server_addr = ip4_addr(server_ip, server_port); let server_addr = ip4_addr(server_ip, server_port);
// FIXME ref #2064 // FIXME ref #2064
let server_addr_ptr = ptr::addr_of(&server_addr); let server_addr_ptr = ptr::addr_of(&server_addr);
// uv_tcp_bind() // uv_tcp_bind()
let bind_result = tcp_bind(tcp_server_ptr, let bind_result = tcp_bind(tcp_server_ptr,
server_addr_ptr); server_addr_ptr);
if (bind_result == 0i32) { if (bind_result == 0i32) {
log(debug, ~"successful uv_tcp_bind, listening"); log(debug, ~"successful uv_tcp_bind, listening");
// uv_listen() // uv_listen()
let listen_result = listen(tcp_server_ptr as let listen_result = listen(tcp_server_ptr as
*libc::c_void, *libc::c_void,
128i32, 128i32,
server_connection_cb); server_connection_cb);
if (listen_result == 0i32) { if (listen_result == 0i32) {
// let the test know it can set up the tcp server, // let the test know it can set up the tcp server,
// now.. this may still present a race, not sure.. // now.. this may still present a race, not sure..
let async_result = async_init(test_loop, let async_result = async_init(test_loop,
continue_async_handle_ptr, continue_async_handle_ptr,
continue_async_cb); continue_async_cb);
if (async_result == 0i32) { if (async_result == 0i32) {
set_data_for_uv_handle( set_data_for_uv_handle(
continue_async_handle_ptr as *libc::c_void, continue_async_handle_ptr as *libc::c_void,
async_data_ptr as *libc::c_void); async_data_ptr as *libc::c_void);
async_send(continue_async_handle_ptr); async_send(continue_async_handle_ptr);
// uv_run() // uv_run()
run(test_loop); run(test_loop);
log(debug, ~"server uv::run() has returned"); log(debug, ~"server uv::run() has returned");
}
else {
log(debug, fmt!("uv_async_init failure: %d",
async_result as int));
assert false;
}
} }
else { else {
log(debug, fmt!("uv_async_init failure: %d", log(debug, fmt!("non-zero result on uv_listen: %d",
async_result as int)); listen_result as int));
assert false; assert false;
} }
} }
else { else {
log(debug, fmt!("non-zero result on uv_listen: %d", log(debug, fmt!("non-zero result on uv_tcp_bind: %d",
listen_result as int)); bind_result as int));
assert false; assert false;
} }
} }
else { else {
log(debug, fmt!("non-zero result on uv_tcp_bind: %d", log(debug, fmt!("non-zero result on uv_tcp_init: %d",
bind_result as int)); tcp_init_result as int));
assert false; assert false;
} }
loop_delete(test_loop);
} }
else {
log(debug, fmt!("non-zero result on uv_tcp_init: %d",
tcp_init_result as int));
assert false;
}
loop_delete(test_loop);
} }
// this is the impl for a test that is (maybe) ran on a // this is the impl for a test that is (maybe) ran on a
// per-platform/arch basis below // per-platform/arch basis below
fn impl_uv_tcp_server_and_request() unsafe { fn impl_uv_tcp_server_and_request() {
let bind_ip = ~"0.0.0.0"; unsafe {
let request_ip = ~"127.0.0.1"; let bind_ip = ~"0.0.0.0";
let port = 8886; let request_ip = ~"127.0.0.1";
let kill_server_msg = ~"does a dog have buddha nature?"; let port = 8886;
let server_resp_msg = ~"mu!"; let kill_server_msg = ~"does a dog have buddha nature?";
let client_port = oldcomm::Port::<~str>(); let server_resp_msg = ~"mu!";
let client_chan = oldcomm::Chan::<~str>(&client_port); let client_port = oldcomm::Port::<~str>();
let server_port = oldcomm::Port::<~str>(); let client_chan = oldcomm::Chan::<~str>(&client_port);
let server_chan = oldcomm::Chan::<~str>(&server_port); let server_port = oldcomm::Port::<~str>();
let server_chan = oldcomm::Chan::<~str>(&server_port);
let continue_port = oldcomm::Port::<bool>(); let continue_port = oldcomm::Port::<bool>();
let continue_chan = oldcomm::Chan::<bool>(&continue_port); let continue_chan = oldcomm::Chan::<bool>(&continue_port);
let continue_chan_ptr = ptr::addr_of(&continue_chan); let continue_chan_ptr = ptr::addr_of(&continue_chan);
do task::spawn_sched(task::ManualThreads(1)) { do task::spawn_sched(task::ManualThreads(1)) {
impl_uv_tcp_server(bind_ip, port, impl_uv_tcp_server(bind_ip, port,
kill_server_msg, kill_server_msg,
server_resp_msg, server_resp_msg,
ptr::addr_of(&server_chan), ptr::addr_of(&server_chan),
continue_chan_ptr); continue_chan_ptr);
}; };
// block until the server up is.. possibly a race? // block until the server up is.. possibly a race?
log(debug, ~"before receiving on server continue_port"); log(debug, ~"before receiving on server continue_port");
oldcomm::recv(continue_port); oldcomm::recv(continue_port);
log(debug, ~"received on continue port, set up tcp client"); log(debug, ~"received on continue port, set up tcp client");
do task::spawn_sched(task::ManualThreads(1u)) { do task::spawn_sched(task::ManualThreads(1u)) {
impl_uv_tcp_request(request_ip, port, impl_uv_tcp_request(request_ip, port,
kill_server_msg, kill_server_msg,
ptr::addr_of(&client_chan)); ptr::addr_of(&client_chan));
}; };
let msg_from_client = oldcomm::recv(server_port); let msg_from_client = oldcomm::recv(server_port);
let msg_from_server = oldcomm::recv(client_port); let msg_from_server = oldcomm::recv(client_port);
assert str::contains(msg_from_client, kill_server_msg); assert str::contains(msg_from_client, kill_server_msg);
assert str::contains(msg_from_server, server_resp_msg); assert str::contains(msg_from_server, server_resp_msg);
}
} }
// FIXME don't run on fbsd or linux 32 bit(#2064) // FIXME don't run on fbsd or linux 32 bit(#2064)
@ -1590,8 +1617,10 @@ pub mod test {
pub mod impl64 { pub mod impl64 {
use uv_ll::test::*; use uv_ll::test::*;
#[test] #[test]
pub fn test_uv_ll_tcp_server_and_request() unsafe { pub fn test_uv_ll_tcp_server_and_request() {
impl_uv_tcp_server_and_request(); unsafe {
impl_uv_tcp_server_and_request();
}
} }
} }
#[cfg(target_arch="x86")] #[cfg(target_arch="x86")]
@ -1600,8 +1629,10 @@ pub mod test {
use uv_ll::test::*; use uv_ll::test::*;
#[test] #[test]
#[ignore(cfg(target_os = "linux"))] #[ignore(cfg(target_os = "linux"))]
pub fn test_uv_ll_tcp_server_and_request() unsafe { pub fn test_uv_ll_tcp_server_and_request() {
impl_uv_tcp_server_and_request(); unsafe {
impl_uv_tcp_server_and_request();
}
} }
} }
} }

View file

@ -208,14 +208,16 @@ pub impl FileMap {
self.lines.push(pos); self.lines.push(pos);
} }
pub fn get_line(&self, line: int) -> ~str unsafe { pub fn get_line(&self, line: int) -> ~str {
let begin: BytePos = self.lines[line] - self.start_pos; unsafe {
let begin = begin.to_uint(); let begin: BytePos = self.lines[line] - self.start_pos;
let end = match str::find_char_from(*self.src, '\n', begin) { let begin = begin.to_uint();
Some(e) => e, let end = match str::find_char_from(*self.src, '\n', begin) {
None => str::len(*self.src) Some(e) => e,
}; None => str::len(*self.src)
str::slice(*self.src, begin, end) };
str::slice(*self.src, begin, end)
}
} }
pub fn record_multibyte_char(&self, pos: BytePos, bytes: uint) { pub fn record_multibyte_char(&self, pos: BytePos, bytes: uint) {

View file

@ -157,11 +157,13 @@ fn byte_offset(rdr: string_reader) -> BytePos {
(rdr.pos - rdr.filemap.start_pos) (rdr.pos - rdr.filemap.start_pos)
} }
fn get_str_from(rdr: string_reader, start: BytePos) -> ~str unsafe { fn get_str_from(rdr: string_reader, start: BytePos) -> ~str {
// I'm pretty skeptical about this subtraction. What if there's a unsafe {
// multi-byte character before the mark? // I'm pretty skeptical about this subtraction. What if there's a
return str::slice(*rdr.src, start.to_uint() - 1u, // multi-byte character before the mark?
byte_offset(rdr).to_uint() - 1u); return str::slice(*rdr.src, start.to_uint() - 1u,
byte_offset(rdr).to_uint() - 1u);
}
} }
fn bump(rdr: string_reader) { fn bump(rdr: string_reader) {

View file

@ -44,7 +44,8 @@ pub enum ObsoleteSyntax {
ObsoletePrivSection, ObsoletePrivSection,
ObsoleteModeInFnType, ObsoleteModeInFnType,
ObsoleteMoveInit, ObsoleteMoveInit,
ObsoleteBinaryMove ObsoleteBinaryMove,
ObsoleteUnsafeBlock
} }
impl ObsoleteSyntax : cmp::Eq { impl ObsoleteSyntax : cmp::Eq {
@ -118,6 +119,10 @@ impl Parser {
ObsoleteBinaryMove => ( ObsoleteBinaryMove => (
"binary move", "binary move",
"Write `foo = move bar` instead" "Write `foo = move bar` instead"
),
ObsoleteUnsafeBlock => (
"non-standalone unsafe block",
"use an inner `unsafe { ... }` block instead"
) )
}; };

View file

@ -69,6 +69,7 @@ use parse::obsolete::{ObsoleteLet, ObsoleteFieldTerminator};
use parse::obsolete::{ObsoleteMoveInit, ObsoleteBinaryMove}; use parse::obsolete::{ObsoleteMoveInit, ObsoleteBinaryMove};
use parse::obsolete::{ObsoleteStructCtor, ObsoleteWith, ObsoleteClassMethod}; use parse::obsolete::{ObsoleteStructCtor, ObsoleteWith, ObsoleteClassMethod};
use parse::obsolete::{ObsoleteSyntax, ObsoleteLowerCaseKindBounds}; use parse::obsolete::{ObsoleteSyntax, ObsoleteLowerCaseKindBounds};
use parse::obsolete::{ObsoleteUnsafeBlock};
use parse::prec::{as_prec, token_to_binop}; use parse::prec::{as_prec, token_to_binop};
use parse::token::{can_begin_expr, is_ident, is_ident_or_path}; use parse::token::{can_begin_expr, is_ident, is_ident_or_path};
use parse::token::{is_plain_ident, INTERPOLATED, special_idents}; use parse::token::{is_plain_ident, INTERPOLATED, special_idents};
@ -2336,12 +2337,13 @@ impl Parser {
} }
let lo = self.span.lo; let lo = self.span.lo;
let us = self.eat_keyword(~"unsafe"); if self.eat_keyword(~"unsafe") {
self.obsolete(copy self.span, ObsoleteUnsafeBlock);
}
self.expect(token::LBRACE); self.expect(token::LBRACE);
let {inner: move inner, next: move next} = let {inner: move inner, next: move next} =
maybe_parse_inner_attrs_and_next(self, parse_attrs); maybe_parse_inner_attrs_and_next(self, parse_attrs);
let blk_check_mode = if us { unsafe_blk } else { default_blk }; return (inner, self.parse_block_tail_(lo, default_blk, next));
return (inner, self.parse_block_tail_(lo, blk_check_mode, next));
} }
fn parse_block_no_value() -> blk { fn parse_block_no_value() -> blk {

View file

@ -21,16 +21,20 @@ fn recurse() {
struct r { struct r {
recursed: *mut bool, recursed: *mut bool,
drop unsafe { drop {
if !*(self.recursed) { unsafe {
*(self.recursed) = true; if !*(self.recursed) {
recurse(); *(self.recursed) = true;
recurse();
}
} }
} }
} }
fn r(recursed: *mut bool) -> r unsafe { fn r(recursed: *mut bool) -> r {
r { recursed: recursed } unsafe {
r { recursed: recursed }
}
} }
fn main() { fn main() {

View file

@ -32,11 +32,13 @@ fn r(v: *int) -> r {
} }
} }
fn main() unsafe { fn main() {
let i1 = ~0; unsafe {
let i1p = cast::reinterpret_cast(&i1); let i1 = ~0;
cast::forget(move i1); let i1p = cast::reinterpret_cast(&i1);
let x = @r(i1p); cast::forget(move i1);
failfn(); let x = @r(i1p);
log(error, x); failfn();
log(error, x);
}
} }

View file

@ -62,19 +62,21 @@ fn test_box() {
assert (@10 == @10); assert (@10 == @10);
} }
fn test_ptr() unsafe { fn test_ptr() {
let p1: *u8 = ::core::cast::reinterpret_cast(&0); unsafe {
let p2: *u8 = ::core::cast::reinterpret_cast(&0); let p1: *u8 = ::core::cast::reinterpret_cast(&0);
let p3: *u8 = ::core::cast::reinterpret_cast(&1); let p2: *u8 = ::core::cast::reinterpret_cast(&0);
let p3: *u8 = ::core::cast::reinterpret_cast(&1);
assert p1 == p2; assert p1 == p2;
assert p1 != p3; assert p1 != p3;
assert p1 < p3; assert p1 < p3;
assert p1 <= p3; assert p1 <= p3;
assert p3 > p1; assert p3 > p1;
assert p3 >= p3; assert p3 >= p3;
assert p1 <= p2; assert p1 <= p2;
assert p1 >= p2; assert p1 >= p2;
}
} }
#[abi = "cdecl"] #[abi = "cdecl"]

View file

@ -19,10 +19,12 @@ extern mod libc {
fn my_strlen(str: *u8) -> uint; fn my_strlen(str: *u8) -> uint;
} }
fn strlen(str: ~str) -> uint unsafe { fn strlen(str: ~str) -> uint {
// C string is terminated with a zero unsafe {
let bytes = str::to_bytes(str) + ~[0u8]; // C string is terminated with a zero
return libc::my_strlen(vec::raw::to_ptr(bytes)); let bytes = str::to_bytes(str) + ~[0u8];
return libc::my_strlen(vec::raw::to_ptr(bytes));
}
} }
fn main() { fn main() {

View file

@ -14,8 +14,10 @@ use core::cast;
use core::libc::{c_double, c_int}; use core::libc::{c_double, c_int};
use core::f64::*; use core::f64::*;
fn to_c_int(v: &mut int) -> &mut c_int unsafe { fn to_c_int(v: &mut int) -> &mut c_int {
cast::reinterpret_cast(&v) unsafe {
cast::reinterpret_cast(&v)
}
} }
fn lgamma(n: c_double, value: &mut int) -> c_double { fn lgamma(n: c_double, value: &mut int) -> c_double {

View file

@ -34,13 +34,15 @@ pub mod pipes {
mut payload: Option<T> mut payload: Option<T>
}; };
pub fn packet<T: Owned>() -> *packet<T> unsafe { pub fn packet<T: Owned>() -> *packet<T> {
let p: *packet<T> = cast::transmute(~{ unsafe {
mut state: empty, let p: *packet<T> = cast::transmute(~{
mut blocked_task: None::<task::Task>, mut state: empty,
mut payload: None::<T> mut blocked_task: None::<task::Task>,
}); mut payload: None::<T>
p });
p
}
} }
#[abi = "rust-intrinsic"] #[abi = "rust-intrinsic"]
@ -218,22 +220,26 @@ pub mod pingpong {
pub enum ping = ::pipes::send_packet<pong>; pub enum ping = ::pipes::send_packet<pong>;
pub enum pong = ::pipes::send_packet<ping>; pub enum pong = ::pipes::send_packet<ping>;
pub fn liberate_ping(-p: ping) -> ::pipes::send_packet<pong> unsafe { pub fn liberate_ping(-p: ping) -> ::pipes::send_packet<pong> {
let addr : *::pipes::send_packet<pong> = match &p { unsafe {
&ping(ref x) => { cast::transmute(ptr::addr_of(x)) } let addr : *::pipes::send_packet<pong> = match &p {
}; &ping(ref x) => { cast::transmute(ptr::addr_of(x)) }
let liberated_value = move *addr; };
cast::forget(move p); let liberated_value = move *addr;
move liberated_value cast::forget(move p);
move liberated_value
}
} }
pub fn liberate_pong(-p: pong) -> ::pipes::send_packet<ping> unsafe { pub fn liberate_pong(-p: pong) -> ::pipes::send_packet<ping> {
let addr : *::pipes::send_packet<ping> = match &p { unsafe {
&pong(ref x) => { cast::transmute(ptr::addr_of(x)) } let addr : *::pipes::send_packet<ping> = match &p {
}; &pong(ref x) => { cast::transmute(ptr::addr_of(x)) }
let liberated_value = move *addr; };
cast::forget(move p); let liberated_value = move *addr;
move liberated_value cast::forget(move p);
move liberated_value
}
} }
pub fn init() -> (client::ping, server::ping) { pub fn init() -> (client::ping, server::ping) {

View file

@ -14,6 +14,8 @@
extern mod issue_2723_a; extern mod issue_2723_a;
use issue_2723_a::*; use issue_2723_a::*;
fn main() unsafe { fn main() {
f(~[2]); unsafe {
f(~[2]);
}
} }

View file

@ -1,19 +0,0 @@
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// Tests that "loop unsafe" isn't misparsed.
fn main() {
loop unsafe {
io::println("Hello world!");
return ();
}
}

View file

@ -23,9 +23,11 @@ type ccx = {
x: int x: int
}; };
fn alloc(_bcx : &arena) -> &bcx unsafe { fn alloc(_bcx : &arena) -> &bcx {
return cast::reinterpret_cast( unsafe {
&libc::malloc(sys::size_of::<bcx/&blk>() as libc::size_t)); return cast::reinterpret_cast(
&libc::malloc(sys::size_of::<bcx/&blk>() as libc::size_t));
}
} }
fn h(bcx : &bcx) -> &bcx { fn h(bcx : &bcx) -> &bcx {

View file

@ -26,9 +26,11 @@ impl r : Drop {
} }
} }
fn r(v: *int) -> r unsafe { fn r(v: *int) -> r {
r { unsafe {
v: v r {
v: v
}
} }
} }
@ -37,41 +39,43 @@ enum t = {
r: r r: r
}; };
fn main() unsafe { fn main() {
let i1 = ~0; unsafe {
let i1p = cast::reinterpret_cast(&i1); let i1 = ~0;
cast::forget(move i1); let i1p = cast::reinterpret_cast(&i1);
let i2 = ~0; cast::forget(move i1);
let i2p = cast::reinterpret_cast(&i2); let i2 = ~0;
cast::forget(move i2); let i2p = cast::reinterpret_cast(&i2);
cast::forget(move i2);
let x1 = @t({ let x1 = @t({
mut next: None, mut next: None,
r: { r: {
let rs = r(i1p); let rs = r(i1p);
debug!("r = %x", debug!("r = %x",
cast::reinterpret_cast::<*r, uint>(&ptr::addr_of(&rs))); cast::reinterpret_cast::<*r, uint>(&ptr::addr_of(&rs)));
move rs } move rs }
}); });
debug!("x1 = %x, x1.r = %x", debug!("x1 = %x, x1.r = %x",
cast::reinterpret_cast::<@t, uint>(&x1), cast::reinterpret_cast::<@t, uint>(&x1),
cast::reinterpret_cast::<*r, uint>(&ptr::addr_of(&(x1.r)))); cast::reinterpret_cast::<*r, uint>(&ptr::addr_of(&(x1.r))));
let x2 = @t({ let x2 = @t({
mut next: None, mut next: None,
r: { r: {
let rs = r(i2p); let rs = r(i2p);
debug!("r2 = %x", debug!("r2 = %x",
cast::reinterpret_cast::<*r, uint>(&ptr::addr_of(&rs))); cast::reinterpret_cast::<*r, uint>(&ptr::addr_of(&rs)));
move rs move rs
} }
}); });
debug!("x2 = %x, x2.r = %x", debug!("x2 = %x, x2.r = %x",
cast::reinterpret_cast::<@t, uint>(&x2), cast::reinterpret_cast::<@t, uint>(&x2),
cast::reinterpret_cast::<*r, uint>(&ptr::addr_of(&(x2.r)))); cast::reinterpret_cast::<*r, uint>(&ptr::addr_of(&(x2.r))));
x1.next = Some(x2); x1.next = Some(x2);
x2.next = Some(x1); x2.next = Some(x1);
}
} }

View file

@ -39,25 +39,27 @@ enum t = {
r: r r: r
}; };
fn main() unsafe { fn main() {
let i1 = ~0xA; unsafe {
let i1p = cast::reinterpret_cast(&i1); let i1 = ~0xA;
cast::forget(move i1); let i1p = cast::reinterpret_cast(&i1);
let i2 = ~0xA; cast::forget(move i1);
let i2p = cast::reinterpret_cast(&i2); let i2 = ~0xA;
cast::forget(move i2); let i2p = cast::reinterpret_cast(&i2);
cast::forget(move i2);
let u1 = {a: 0xB, b: 0xC, c: i1p}; let u1 = {a: 0xB, b: 0xC, c: i1p};
let u2 = {a: 0xB, b: 0xC, c: i2p}; let u2 = {a: 0xB, b: 0xC, c: i2p};
let x1 = @t({ let x1 = @t({
mut next: None, mut next: None,
r: r(u1) r: r(u1)
}); });
let x2 = @t({ let x2 = @t({
mut next: None, mut next: None,
r: r(u2) r: r(u2)
}); });
x1.next = Some(x2); x1.next = Some(x2);
x2.next = Some(x1); x2.next = Some(x1);
}
} }

View file

@ -33,11 +33,13 @@ impl r : Drop {
} }
} }
fn r(v: u, w: int, _x: *int) -> r unsafe { fn r(v: u, w: int, _x: *int) -> r {
r { unsafe {
v: v, r {
w: w, v: v,
x: cast::reinterpret_cast(&0) w: w,
x: cast::reinterpret_cast(&0)
}
} }
} }
@ -46,25 +48,27 @@ enum t = {
r: r r: r
}; };
fn main() unsafe { fn main() {
let i1 = ~0xA; unsafe {
let i1p = cast::reinterpret_cast(&i1); let i1 = ~0xA;
cast::forget(move i1); let i1p = cast::reinterpret_cast(&i1);
let i2 = ~0xA; cast::forget(move i1);
let i2p = cast::reinterpret_cast(&i2); let i2 = ~0xA;
cast::forget(move i2); let i2p = cast::reinterpret_cast(&i2);
cast::forget(move i2);
let u1 = {a: 0xB, b: 0xC, c: i1p}; let u1 = {a: 0xB, b: 0xC, c: i1p};
let u2 = {a: 0xB, b: 0xC, c: i2p}; let u2 = {a: 0xB, b: 0xC, c: i2p};
let x1 = @t({ let x1 = @t({
mut next: None, mut next: None,
r: r(u1, 42, i1p) r: r(u1, 42, i1p)
}); });
let x2 = @t({ let x2 = @t({
mut next: None, mut next: None,
r: r(u2, 42, i2p) r: r(u2, 42, i2p)
}); });
x1.next = Some(x2); x1.next = Some(x2);
x2.next = Some(x1); x2.next = Some(x1);
}
} }

View file

@ -24,25 +24,27 @@ extern mod rustrt {
fn start_task(id: task_id, f: closure); fn start_task(id: task_id, f: closure);
} }
fn main() unsafe { fn main() {
let po = oldcomm::Port(); unsafe {
let ch = oldcomm::Chan(&po); let po = oldcomm::Port();
let parent_sched_id = rustrt::rust_get_sched_id(); let ch = oldcomm::Chan(&po);
error!("parent %?", parent_sched_id); let parent_sched_id = rustrt::rust_get_sched_id();
let num_threads = 1u; error!("parent %?", parent_sched_id);
let new_sched_id = rustrt::rust_new_sched(num_threads); let num_threads = 1u;
error!("new_sched_id %?", new_sched_id); let new_sched_id = rustrt::rust_new_sched(num_threads);
let new_task_id = rustrt::rust_new_task_in_sched(new_sched_id); error!("new_sched_id %?", new_sched_id);
assert !new_task_id.is_null(); let new_task_id = rustrt::rust_new_task_in_sched(new_sched_id);
let f = fn~() { assert !new_task_id.is_null();
let child_sched_id = rustrt::rust_get_sched_id(); let f = fn~() {
error!("child_sched_id %?", child_sched_id); let child_sched_id = rustrt::rust_get_sched_id();
assert child_sched_id != parent_sched_id; error!("child_sched_id %?", child_sched_id);
assert child_sched_id == new_sched_id; assert child_sched_id != parent_sched_id;
oldcomm::send(ch, ()); assert child_sched_id == new_sched_id;
}; oldcomm::send(ch, ());
let fptr = cast::reinterpret_cast(&ptr::addr_of(&f)); };
rustrt::start_task(new_task_id, fptr); let fptr = cast::reinterpret_cast(&ptr::addr_of(&f));
cast::forget(move f); rustrt::start_task(new_task_id, fptr);
oldcomm::recv(po); cast::forget(move f);
oldcomm::recv(po);
}
} }

View file

@ -37,7 +37,7 @@ fn main() {
test_color(orange, 4, ~"orange"); test_color(orange, 4, ~"orange");
} }
fn test_color(color: color, val: int, name: ~str) unsafe { fn test_color(color: color, val: int, name: ~str) {
//assert unsafe::reinterpret_cast(color) == val; //assert unsafe::reinterpret_cast(color) == val;
assert color as int == val; assert color as int == val;
assert color as float == val as float; assert color as float == val as float;

View file

@ -13,6 +13,10 @@
// in that type gets resolved. // in that type gets resolved.
extern mod std; extern mod std;
fn null<T>() -> *T unsafe { cast::reinterpret_cast(&0) } fn null<T>() -> *T {
unsafe {
cast::reinterpret_cast(&0)
}
}
fn main() { null::<int>(); } fn main() { null::<int>(); }

View file

@ -8,12 +8,14 @@
// option. This file may not be copied, modified, or distributed // option. This file may not be copied, modified, or distributed
// except according to those terms. // except according to those terms.
fn main() unsafe { fn main() {
let i = ~@1; unsafe {
let j = ~@2; let i = ~@1;
let rc1 = sys::refcount(*i); let j = ~@2;
let j = copy i; let rc1 = sys::refcount(*i);
let rc2 = sys::refcount(*i); let j = copy i;
error!("rc1: %u rc2: %u", rc1, rc2); let rc2 = sys::refcount(*i);
assert rc1 + 1u == rc2; error!("rc1: %u rc2: %u", rc1, rc2);
assert rc1 + 1u == rc2;
}
} }

View file

@ -20,9 +20,5 @@ fn g() {
} }
} }
fn h() unsafe {
f();
}
fn main() { fn main() {
} }