libsyntax: Remove fn() unsafe { ... }
. r=graydon
This commit is contained in:
parent
1d1b81143b
commit
54b2cad8b3
59 changed files with 2807 additions and 2425 deletions
|
@ -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}];
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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],
|
||||||
|
|
|
@ -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)),
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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] {
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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) }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
@ -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
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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)]
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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!");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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..");
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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"
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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() {
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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"]
|
||||||
|
|
|
@ -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() {
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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]);
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -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 ();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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>(); }
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,9 +20,5 @@ fn g() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn h() unsafe {
|
|
||||||
f();
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue