Merge remote-tracking branch 'remotes/origin/master' into remove-str-trailing-nulls
This commit is contained in:
commit
ee59aacac4
73 changed files with 1740 additions and 1109 deletions
|
|
@ -284,12 +284,6 @@ impl Not<bool> for bool {
|
|||
impl Ord for bool {
|
||||
#[inline]
|
||||
fn lt(&self, other: &bool) -> bool { to_bit(*self) < to_bit(*other) }
|
||||
#[inline]
|
||||
fn le(&self, other: &bool) -> bool { to_bit(*self) <= to_bit(*other) }
|
||||
#[inline]
|
||||
fn gt(&self, other: &bool) -> bool { to_bit(*self) > to_bit(*other) }
|
||||
#[inline]
|
||||
fn ge(&self, other: &bool) -> bool { to_bit(*self) >= to_bit(*other) }
|
||||
}
|
||||
|
||||
#[cfg(not(test))]
|
||||
|
|
|
|||
|
|
@ -322,12 +322,6 @@ impl Eq for char {
|
|||
impl Ord for char {
|
||||
#[inline]
|
||||
fn lt(&self, other: &char) -> bool { *self < *other }
|
||||
#[inline]
|
||||
fn le(&self, other: &char) -> bool { *self <= *other }
|
||||
#[inline]
|
||||
fn gt(&self, other: &char) -> bool { *self > *other }
|
||||
#[inline]
|
||||
fn ge(&self, other: &char) -> bool { *self >= *other }
|
||||
}
|
||||
|
||||
#[cfg(not(test))]
|
||||
|
|
|
|||
|
|
@ -101,12 +101,6 @@ impl TotalOrd for Ordering {
|
|||
impl Ord for Ordering {
|
||||
#[inline]
|
||||
fn lt(&self, other: &Ordering) -> bool { (*self as int) < (*other as int) }
|
||||
#[inline]
|
||||
fn le(&self, other: &Ordering) -> bool { (*self as int) <= (*other as int) }
|
||||
#[inline]
|
||||
fn gt(&self, other: &Ordering) -> bool { (*self as int) > (*other as int) }
|
||||
#[inline]
|
||||
fn ge(&self, other: &Ordering) -> bool { (*self as int) >= (*other as int) }
|
||||
}
|
||||
|
||||
macro_rules! totalord_impl(
|
||||
|
|
@ -174,8 +168,11 @@ pub fn lexical_ordering(o1: Ordering, o2: Ordering) -> Ordering {
|
|||
#[lang="ord"]
|
||||
pub trait Ord {
|
||||
fn lt(&self, other: &Self) -> bool;
|
||||
#[inline]
|
||||
fn le(&self, other: &Self) -> bool { !other.lt(self) }
|
||||
#[inline]
|
||||
fn gt(&self, other: &Self) -> bool { other.lt(self) }
|
||||
#[inline]
|
||||
fn ge(&self, other: &Self) -> bool { !self.lt(other) }
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -33,12 +33,6 @@ impl Eq for () {
|
|||
impl Ord for () {
|
||||
#[inline]
|
||||
fn lt(&self, _other: &()) -> bool { false }
|
||||
#[inline]
|
||||
fn le(&self, _other: &()) -> bool { true }
|
||||
#[inline]
|
||||
fn ge(&self, _other: &()) -> bool { true }
|
||||
#[inline]
|
||||
fn gt(&self, _other: &()) -> bool { false }
|
||||
}
|
||||
|
||||
#[cfg(not(test))]
|
||||
|
|
|
|||
|
|
@ -130,12 +130,6 @@ impl Num for $T {}
|
|||
impl Ord for $T {
|
||||
#[inline]
|
||||
fn lt(&self, other: &$T) -> bool { return (*self) < (*other); }
|
||||
#[inline]
|
||||
fn le(&self, other: &$T) -> bool { return (*self) <= (*other); }
|
||||
#[inline]
|
||||
fn ge(&self, other: &$T) -> bool { return (*self) >= (*other); }
|
||||
#[inline]
|
||||
fn gt(&self, other: &$T) -> bool { return (*self) > (*other); }
|
||||
}
|
||||
|
||||
#[cfg(not(test))]
|
||||
|
|
|
|||
|
|
@ -131,12 +131,6 @@ impl Num for $T {}
|
|||
impl Ord for $T {
|
||||
#[inline]
|
||||
fn lt(&self, other: &$T) -> bool { (*self) < (*other) }
|
||||
#[inline]
|
||||
fn le(&self, other: &$T) -> bool { (*self) <= (*other) }
|
||||
#[inline]
|
||||
fn ge(&self, other: &$T) -> bool { (*self) >= (*other) }
|
||||
#[inline]
|
||||
fn gt(&self, other: &$T) -> bool { (*self) > (*other) }
|
||||
}
|
||||
|
||||
#[cfg(not(test))]
|
||||
|
|
|
|||
|
|
@ -1152,9 +1152,9 @@ pub fn real_args() -> ~[~str] {
|
|||
#[cfg(target_os = "freebsd")]
|
||||
pub fn real_args() -> ~[~str] {
|
||||
use rt;
|
||||
use rt::TaskContext;
|
||||
use rt::NewRtContext;
|
||||
|
||||
if rt::context() == TaskContext {
|
||||
if rt::context() == NewRtContext {
|
||||
match rt::args::clone() {
|
||||
Some(args) => args,
|
||||
None => fail!("process arguments not initialized")
|
||||
|
|
|
|||
|
|
@ -21,13 +21,14 @@ use c_str;
|
|||
use clone::Clone;
|
||||
use cmp::Eq;
|
||||
use container::Container;
|
||||
use iterator::{Iterator, IteratorUtil};
|
||||
use iterator::{Iterator, IteratorUtil, range};
|
||||
use libc;
|
||||
use num;
|
||||
use option::{None, Option, Some};
|
||||
use str::{OwnedStr, Str, StrSlice, StrVector};
|
||||
use to_str::ToStr;
|
||||
use ascii::{AsciiCast, AsciiStr};
|
||||
use vec::{OwnedVector, ImmutableVector};
|
||||
use vec::{OwnedVector, ImmutableVector, OwnedCopyableVector};
|
||||
|
||||
#[cfg(windows)]
|
||||
pub use Path = self::WindowsPath;
|
||||
|
|
@ -126,6 +127,43 @@ pub trait GenericPath {
|
|||
|
||||
/// True if `self` is an ancestor of `other`. See `test_is_ancestor_of` for examples
|
||||
fn is_ancestor_of(&self, (&Self)) -> bool;
|
||||
|
||||
/// Find the relative path from one file to another
|
||||
fn get_relative_to(&self, abs2: (&Self)) -> Self {
|
||||
assert!(self.is_absolute());
|
||||
assert!(abs2.is_absolute());
|
||||
let abs1 = self.normalize();
|
||||
let abs2 = abs2.normalize();
|
||||
|
||||
let split1: &[~str] = abs1.components();
|
||||
let split2: &[~str] = abs2.components();
|
||||
let len1 = split1.len();
|
||||
let len2 = split2.len();
|
||||
assert!(len1 > 0);
|
||||
assert!(len2 > 0);
|
||||
|
||||
let max_common_path = num::min(len1, len2) - 1;
|
||||
let mut start_idx = 0;
|
||||
while start_idx < max_common_path
|
||||
&& split1[start_idx] == split2[start_idx] {
|
||||
start_idx += 1;
|
||||
}
|
||||
|
||||
let mut path: ~[~str] = ~[];
|
||||
for _ in range(start_idx, len1 - 1) { path.push(~".."); };
|
||||
|
||||
path.push_all(split2.slice(start_idx, len2 - 1));
|
||||
|
||||
let mut result: Self = GenericPath::from_str(".");
|
||||
if !path.is_empty() {
|
||||
// Without this type hint, the typechecker doesn't seem to like it
|
||||
let p: Self = GenericPath::from_str("");
|
||||
result = p.push_many(path);
|
||||
};
|
||||
result
|
||||
}
|
||||
|
||||
fn components(self) -> ~[~str];
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
|
|
@ -711,6 +749,7 @@ impl GenericPath for PosixPath {
|
|||
self.is_ancestor_of(&other.pop()))
|
||||
}
|
||||
|
||||
fn components(self) -> ~[~str] { self.components }
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -998,6 +1037,8 @@ impl GenericPath for WindowsPath {
|
|||
(!other.components.is_empty() && !(self.components.is_empty() && !self.is_absolute) &&
|
||||
self.is_ancestor_of(&other.pop()))
|
||||
}
|
||||
|
||||
fn components(self) -> ~[~str] { self.components }
|
||||
}
|
||||
|
||||
pub fn normalize(components: &[~str]) -> ~[~str] {
|
||||
|
|
@ -1354,4 +1395,124 @@ mod tests {
|
|||
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_relative_to1() {
|
||||
let p1 = PosixPath("/usr/bin/rustc");
|
||||
let p2 = PosixPath("/usr/lib/mylib");
|
||||
let res = p1.get_relative_to(&p2);
|
||||
assert_eq!(res, PosixPath("../lib"));
|
||||
|
||||
let p1 = WindowsPath("C:\\usr\\bin\\rustc");
|
||||
let p2 = WindowsPath("C:\\usr\\lib\\mylib");
|
||||
let res = p1.get_relative_to(&p2);
|
||||
assert_eq!(res, WindowsPath("..\\lib"));
|
||||
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_relative_to2() {
|
||||
let p1 = PosixPath("/usr/bin/rustc");
|
||||
let p2 = PosixPath("/usr/bin/../lib/mylib");
|
||||
let res = p1.get_relative_to(&p2);
|
||||
assert_eq!(res, PosixPath("../lib"));
|
||||
|
||||
let p1 = WindowsPath("C:\\usr\\bin\\rustc");
|
||||
let p2 = WindowsPath("C:\\usr\\bin\\..\\lib\\mylib");
|
||||
let res = p1.get_relative_to(&p2);
|
||||
assert_eq!(res, WindowsPath("..\\lib"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_relative_to3() {
|
||||
let p1 = PosixPath("/usr/bin/whatever/rustc");
|
||||
let p2 = PosixPath("/usr/lib/whatever/mylib");
|
||||
let res = p1.get_relative_to(&p2);
|
||||
assert_eq!(res, PosixPath("../../lib/whatever"));
|
||||
|
||||
let p1 = WindowsPath("C:\\usr\\bin\\whatever\\rustc");
|
||||
let p2 = WindowsPath("C:\\usr\\lib\\whatever\\mylib");
|
||||
let res = p1.get_relative_to(&p2);
|
||||
assert_eq!(res, WindowsPath("..\\..\\lib\\whatever"));
|
||||
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_relative_to4() {
|
||||
let p1 = PosixPath("/usr/bin/whatever/../rustc");
|
||||
let p2 = PosixPath("/usr/lib/whatever/mylib");
|
||||
let res = p1.get_relative_to(&p2);
|
||||
assert_eq!(res, PosixPath("../lib/whatever"));
|
||||
|
||||
let p1 = WindowsPath("C:\\usr\\bin\\whatever\\..\\rustc");
|
||||
let p2 = WindowsPath("C:\\usr\\lib\\whatever\\mylib");
|
||||
let res = p1.get_relative_to(&p2);
|
||||
assert_eq!(res, WindowsPath("..\\lib\\whatever"));
|
||||
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_relative_to5() {
|
||||
let p1 = PosixPath("/usr/bin/whatever/../rustc");
|
||||
let p2 = PosixPath("/usr/lib/whatever/../mylib");
|
||||
let res = p1.get_relative_to(&p2);
|
||||
assert_eq!(res, PosixPath("../lib"));
|
||||
|
||||
let p1 = WindowsPath("C:\\usr\\bin/whatever\\..\\rustc");
|
||||
let p2 = WindowsPath("C:\\usr\\lib\\whatever\\..\\mylib");
|
||||
let res = p1.get_relative_to(&p2);
|
||||
assert_eq!(res, WindowsPath("..\\lib"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_relative_to6() {
|
||||
let p1 = PosixPath("/1");
|
||||
let p2 = PosixPath("/2/3");
|
||||
let res = p1.get_relative_to(&p2);
|
||||
assert_eq!(res, PosixPath("2"));
|
||||
|
||||
let p1 = WindowsPath("C:\\1");
|
||||
let p2 = WindowsPath("C:\\2\\3");
|
||||
let res = p1.get_relative_to(&p2);
|
||||
assert_eq!(res, WindowsPath("2"));
|
||||
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_relative_to7() {
|
||||
let p1 = PosixPath("/1/2");
|
||||
let p2 = PosixPath("/3");
|
||||
let res = p1.get_relative_to(&p2);
|
||||
assert_eq!(res, PosixPath(".."));
|
||||
|
||||
let p1 = WindowsPath("C:\\1\\2");
|
||||
let p2 = WindowsPath("C:\\3");
|
||||
let res = p1.get_relative_to(&p2);
|
||||
assert_eq!(res, WindowsPath(".."));
|
||||
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_relative_to8() {
|
||||
let p1 = PosixPath("/home/brian/Dev/rust/build/").push_rel(
|
||||
&PosixPath("stage2/lib/rustc/i686-unknown-linux-gnu/lib/librustc.so"));
|
||||
let p2 = PosixPath("/home/brian/Dev/rust/build/stage2/bin/..").push_rel(
|
||||
&PosixPath("lib/rustc/i686-unknown-linux-gnu/lib/libstd.so"));
|
||||
let res = p1.get_relative_to(&p2);
|
||||
debug!("test_relative_to8: %s vs. %s",
|
||||
res.to_str(),
|
||||
PosixPath(".").to_str());
|
||||
assert_eq!(res, PosixPath("."));
|
||||
|
||||
let p1 = WindowsPath("C:\\home\\brian\\Dev\\rust\\build\\").push_rel(
|
||||
&WindowsPath("stage2\\lib\\rustc\\i686-unknown-linux-gnu\\lib\\librustc.so"));
|
||||
let p2 = WindowsPath("\\home\\brian\\Dev\\rust\\build\\stage2\\bin\\..").push_rel(
|
||||
&WindowsPath("lib\\rustc\\i686-unknown-linux-gnu\\lib\\libstd.so"));
|
||||
let res = p1.get_relative_to(&p2);
|
||||
debug!("test_relative_to8: %s vs. %s",
|
||||
res.to_str(),
|
||||
WindowsPath(".").to_str());
|
||||
assert_eq!(res, WindowsPath("."));
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ use cast;
|
|||
use ops::Drop;
|
||||
use rt::kill::BlockedTask;
|
||||
use kinds::Send;
|
||||
use rt;
|
||||
use rt::sched::Scheduler;
|
||||
use rt::local::Local;
|
||||
use rt::select::{Select, SelectPort};
|
||||
|
|
@ -24,7 +25,6 @@ use util::Void;
|
|||
use comm::{GenericChan, GenericSmartChan, GenericPort, Peekable};
|
||||
use cell::Cell;
|
||||
use clone::Clone;
|
||||
use rt::{context, SchedulerContext};
|
||||
use tuple::ImmutableTuple;
|
||||
|
||||
/// A combined refcount / BlockedTask-as-uint pointer.
|
||||
|
|
@ -113,7 +113,7 @@ impl<T> ChanOne<T> {
|
|||
// 'do_resched' configures whether the scheduler immediately switches to
|
||||
// the receiving task, or leaves the sending task still running.
|
||||
fn try_send_inner(self, val: T, do_resched: bool) -> bool {
|
||||
rtassert!(context() != SchedulerContext);
|
||||
rtassert!(!rt::in_sched_context());
|
||||
|
||||
let mut this = self;
|
||||
let mut recvr_active = true;
|
||||
|
|
|
|||
|
|
@ -9,7 +9,11 @@
|
|||
// except according to those terms.
|
||||
|
||||
use num::FromStrRadix;
|
||||
use vec::MutableCloneableVector;
|
||||
use to_str::ToStr;
|
||||
use from_str::FromStr;
|
||||
use option::{Option, None, Some};
|
||||
|
||||
|
||||
type Port = u16;
|
||||
|
||||
|
|
@ -39,7 +43,7 @@ impl ToStr for IpAddr {
|
|||
}
|
||||
|
||||
// Ipv4-Mapped address
|
||||
Ipv6Addr(0, 0, 0, 0, 0, 1, g, h) => {
|
||||
Ipv6Addr(0, 0, 0, 0, 0, 0xFFFF, g, h) => {
|
||||
let a = fmt!("%04x", g as uint);
|
||||
let b = FromStrRadix::from_str_radix(a.slice(2, 4), 16).unwrap();
|
||||
let a = FromStrRadix::from_str_radix(a.slice(0, 2), 16).unwrap();
|
||||
|
|
@ -73,3 +77,371 @@ impl ToStr for SocketAddr {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct Parser<'self> {
|
||||
// parsing as ASCII, so can use byte array
|
||||
s: &'self [u8],
|
||||
pos: uint,
|
||||
}
|
||||
|
||||
impl<'self> Parser<'self> {
|
||||
fn new(s: &'self str) -> Parser<'self> {
|
||||
Parser {
|
||||
s: s.as_bytes(),
|
||||
pos: 0,
|
||||
}
|
||||
}
|
||||
|
||||
fn is_eof(&self) -> bool {
|
||||
self.pos == self.s.len()
|
||||
}
|
||||
|
||||
// Commit only if parser returns Some
|
||||
fn read_atomically<T>(&mut self, cb: &fn(&mut Parser) -> Option<T>) -> Option<T> {
|
||||
let pos = self.pos;
|
||||
let r = cb(self);
|
||||
if r.is_none() {
|
||||
self.pos = pos;
|
||||
}
|
||||
r
|
||||
}
|
||||
|
||||
// Commit only if parser read till EOF
|
||||
fn read_till_eof<T>(&mut self, cb: &fn(&mut Parser) -> Option<T>) -> Option<T> {
|
||||
do self.read_atomically |p| {
|
||||
cb(p).filtered(|_| p.is_eof())
|
||||
}
|
||||
}
|
||||
|
||||
// Return result of first successful parser
|
||||
fn read_or<T>(&mut self, parsers: &[&fn(&mut Parser) -> Option<T>]) -> Option<T> {
|
||||
for pf in parsers.iter() {
|
||||
match self.read_atomically(|p: &mut Parser| (*pf)(p)) {
|
||||
Some(r) => return Some(r),
|
||||
None => {}
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
// Apply 3 parsers sequentially
|
||||
fn read_seq_3<A, B, C>(&mut self,
|
||||
pa: &fn(&mut Parser) -> Option<A>,
|
||||
pb: &fn(&mut Parser) -> Option<B>,
|
||||
pc: &fn(&mut Parser) -> Option<C>
|
||||
) -> Option<(A, B, C)>
|
||||
{
|
||||
do self.read_atomically |p| {
|
||||
let a = pa(p);
|
||||
let b = if a.is_some() { pb(p) } else { None };
|
||||
let c = if b.is_some() { pc(p) } else { None };
|
||||
match (a, b, c) {
|
||||
(Some(a), Some(b), Some(c)) => Some((a, b, c)),
|
||||
_ => None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Read next char
|
||||
fn read_char(&mut self) -> Option<char> {
|
||||
if self.is_eof() {
|
||||
None
|
||||
} else {
|
||||
let r = self.s[self.pos] as char;
|
||||
self.pos += 1;
|
||||
Some(r)
|
||||
}
|
||||
}
|
||||
|
||||
// Return char and advance iff next char is equal to requested
|
||||
fn read_given_char(&mut self, c: char) -> Option<char> {
|
||||
do self.read_atomically |p| {
|
||||
p.read_char().filtered(|&next| next == c)
|
||||
}
|
||||
}
|
||||
|
||||
// Read digit
|
||||
fn read_digit(&mut self, radix: u8) -> Option<u8> {
|
||||
fn parse_digit(c: char, radix: u8) -> Option<u8> {
|
||||
// assuming radix is either 10 or 16
|
||||
if c >= '0' && c <= '9' {
|
||||
Some((c - '0') as u8)
|
||||
} else if radix > 10 && c >= 'a' && c < 'a' + (radix - 10) as char {
|
||||
Some((c - 'a' + (10 as char)) as u8)
|
||||
} else if radix > 10 && c >= 'A' && c < 'A' + (radix - 10) as char {
|
||||
Some((c - 'A' + (10 as char)) as u8)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
do self.read_atomically |p| {
|
||||
p.read_char().chain(|c| parse_digit(c, radix))
|
||||
}
|
||||
}
|
||||
|
||||
fn read_number_impl(&mut self, radix: u8, max_digits: u32, upto: u32) -> Option<u32> {
|
||||
let mut r = 0u32;
|
||||
let mut digit_count = 0;
|
||||
loop {
|
||||
match self.read_digit(radix) {
|
||||
Some(d) => {
|
||||
r = r * (radix as u32) + (d as u32);
|
||||
digit_count += 1;
|
||||
if digit_count > max_digits || r >= upto {
|
||||
return None
|
||||
}
|
||||
}
|
||||
None => {
|
||||
if digit_count == 0 {
|
||||
return None
|
||||
} else {
|
||||
return Some(r)
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// Read number, failing if max_digits of number value exceeded
|
||||
fn read_number(&mut self, radix: u8, max_digits: u32, upto: u32) -> Option<u32> {
|
||||
do self.read_atomically |p| {
|
||||
p.read_number_impl(radix, max_digits, upto)
|
||||
}
|
||||
}
|
||||
|
||||
fn read_ipv4_addr_impl(&mut self) -> Option<IpAddr> {
|
||||
let mut bs = [0u8, ..4];
|
||||
let mut i = 0;
|
||||
while i < 4 {
|
||||
if i != 0 && self.read_given_char('.').is_none() {
|
||||
return None;
|
||||
}
|
||||
|
||||
let octet = self.read_number(10, 3, 0x100).map(|&n| n as u8);
|
||||
match octet {
|
||||
Some(d) => bs[i] = d,
|
||||
None => return None,
|
||||
};
|
||||
i += 1;
|
||||
}
|
||||
Some(Ipv4Addr(bs[0], bs[1], bs[2], bs[3]))
|
||||
}
|
||||
|
||||
// Read IPv4 address
|
||||
fn read_ipv4_addr(&mut self) -> Option<IpAddr> {
|
||||
do self.read_atomically |p| {
|
||||
p.read_ipv4_addr_impl()
|
||||
}
|
||||
}
|
||||
|
||||
fn read_ipv6_addr_impl(&mut self) -> Option<IpAddr> {
|
||||
fn ipv6_addr_from_head_tail(head: &[u16], tail: &[u16]) -> IpAddr {
|
||||
assert!(head.len() + tail.len() <= 8);
|
||||
let mut gs = [0u16, ..8];
|
||||
gs.copy_from(head);
|
||||
gs.mut_slice(8 - tail.len(), 8).copy_from(tail);
|
||||
Ipv6Addr(gs[0], gs[1], gs[2], gs[3], gs[4], gs[5], gs[6], gs[7])
|
||||
}
|
||||
|
||||
fn read_groups(p: &mut Parser, groups: &mut [u16, ..8], limit: uint) -> (uint, bool) {
|
||||
let mut i = 0;
|
||||
while i < limit {
|
||||
if i < limit - 1 {
|
||||
let ipv4 = do p.read_atomically |p| {
|
||||
if i == 0 || p.read_given_char(':').is_some() {
|
||||
p.read_ipv4_addr()
|
||||
} else {
|
||||
None
|
||||
}
|
||||
};
|
||||
match ipv4 {
|
||||
Some(Ipv4Addr(a, b, c, d)) => {
|
||||
groups[i + 0] = (a as u16 << 8) | (b as u16);
|
||||
groups[i + 1] = (c as u16 << 8) | (d as u16);
|
||||
return (i + 2, true);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
let group = do p.read_atomically |p| {
|
||||
if i == 0 || p.read_given_char(':').is_some() {
|
||||
p.read_number(16, 4, 0x10000).map(|&n| n as u16)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
};
|
||||
match group {
|
||||
Some(g) => groups[i] = g,
|
||||
None => return (i, false)
|
||||
}
|
||||
i += 1;
|
||||
}
|
||||
(i, false)
|
||||
}
|
||||
|
||||
let mut head = [0u16, ..8];
|
||||
let (head_size, head_ipv4) = read_groups(self, &mut head, 8);
|
||||
|
||||
if head_size == 8 {
|
||||
return Some(Ipv6Addr(
|
||||
head[0], head[1], head[2], head[3],
|
||||
head[4], head[5], head[6], head[7]))
|
||||
}
|
||||
|
||||
// IPv4 part is not allowed before `::`
|
||||
if head_ipv4 {
|
||||
return None
|
||||
}
|
||||
|
||||
// read `::` if previous code parsed less than 8 groups
|
||||
if !self.read_given_char(':').is_some() || !self.read_given_char(':').is_some() {
|
||||
return None;
|
||||
}
|
||||
|
||||
let mut tail = [0u16, ..8];
|
||||
let (tail_size, _) = read_groups(self, &mut tail, 8 - head_size);
|
||||
Some(ipv6_addr_from_head_tail(head.slice(0, head_size), tail.slice(0, tail_size)))
|
||||
}
|
||||
|
||||
fn read_ipv6_addr(&mut self) -> Option<IpAddr> {
|
||||
do self.read_atomically |p| {
|
||||
p.read_ipv6_addr_impl()
|
||||
}
|
||||
}
|
||||
|
||||
fn read_ip_addr(&mut self) -> Option<IpAddr> {
|
||||
let ipv4_addr = |p: &mut Parser| p.read_ipv4_addr();
|
||||
let ipv6_addr = |p: &mut Parser| p.read_ipv6_addr();
|
||||
self.read_or([ipv4_addr, ipv6_addr])
|
||||
}
|
||||
|
||||
fn read_socket_addr(&mut self) -> Option<SocketAddr> {
|
||||
let ip_addr = |p: &mut Parser| {
|
||||
let ipv4_p = |p: &mut Parser| p.read_ip_addr();
|
||||
let ipv6_p = |p: &mut Parser| {
|
||||
let open_br = |p: &mut Parser| p.read_given_char('[');
|
||||
let ip_addr = |p: &mut Parser| p.read_ipv6_addr();
|
||||
let clos_br = |p: &mut Parser| p.read_given_char(']');
|
||||
p.read_seq_3::<char, IpAddr, char>(open_br, ip_addr, clos_br)
|
||||
.map(|&t| match t { (_, ip, _) => ip })
|
||||
};
|
||||
p.read_or([ipv4_p, ipv6_p])
|
||||
};
|
||||
let colon = |p: &mut Parser| p.read_given_char(':');
|
||||
let port = |p: &mut Parser| p.read_number(10, 5, 0x10000).map(|&n| n as u16);
|
||||
|
||||
// host, colon, port
|
||||
self.read_seq_3::<IpAddr, char, u16>(ip_addr, colon, port)
|
||||
.map(|&t| match t { (ip, _, port) => SocketAddr { ip: ip, port: port } })
|
||||
}
|
||||
}
|
||||
|
||||
impl FromStr for IpAddr {
|
||||
fn from_str(s: &str) -> Option<IpAddr> {
|
||||
do Parser::new(s).read_till_eof |p| {
|
||||
p.read_ip_addr()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl FromStr for SocketAddr {
|
||||
fn from_str(s: &str) -> Option<SocketAddr> {
|
||||
do Parser::new(s).read_till_eof |p| {
|
||||
p.read_socket_addr()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
use from_str::FromStr;
|
||||
use option::{Some, None};
|
||||
|
||||
#[test]
|
||||
fn test_from_str_ipv4() {
|
||||
assert_eq!(Some(Ipv4Addr(127, 0, 0, 1)), FromStr::from_str("127.0.0.1"));
|
||||
assert_eq!(Some(Ipv4Addr(255, 255, 255, 255)), FromStr::from_str("255.255.255.255"));
|
||||
assert_eq!(Some(Ipv4Addr(0, 0, 0, 0)), FromStr::from_str("0.0.0.0"));
|
||||
|
||||
// out of range
|
||||
assert_eq!(None, FromStr::from_str::<IpAddr>("256.0.0.1"));
|
||||
// too short
|
||||
assert_eq!(None, FromStr::from_str::<IpAddr>("255.0.0"));
|
||||
// too long
|
||||
assert_eq!(None, FromStr::from_str::<IpAddr>("255.0.0.1.2"));
|
||||
// no number between dots
|
||||
assert_eq!(None, FromStr::from_str::<IpAddr>("255.0..1"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_from_str_ipv6() {
|
||||
assert_eq!(Some(Ipv6Addr(0, 0, 0, 0, 0, 0, 0, 0)), FromStr::from_str("0:0:0:0:0:0:0:0"));
|
||||
assert_eq!(Some(Ipv6Addr(0, 0, 0, 0, 0, 0, 0, 1)), FromStr::from_str("0:0:0:0:0:0:0:1"));
|
||||
|
||||
assert_eq!(Some(Ipv6Addr(0, 0, 0, 0, 0, 0, 0, 1)), FromStr::from_str("::1"));
|
||||
assert_eq!(Some(Ipv6Addr(0, 0, 0, 0, 0, 0, 0, 0)), FromStr::from_str("::"));
|
||||
|
||||
assert_eq!(Some(Ipv6Addr(0x2a02, 0x6b8, 0, 0, 0, 0, 0x11, 0x11)),
|
||||
FromStr::from_str("2a02:6b8::11:11"));
|
||||
|
||||
// too long group
|
||||
assert_eq!(None, FromStr::from_str::<IpAddr>("::00000"));
|
||||
// too short
|
||||
assert_eq!(None, FromStr::from_str::<IpAddr>("1:2:3:4:5:6:7"));
|
||||
// too long
|
||||
assert_eq!(None, FromStr::from_str::<IpAddr>("1:2:3:4:5:6:7:8:9"));
|
||||
// triple colon
|
||||
assert_eq!(None, FromStr::from_str::<IpAddr>("1:2:::6:7:8"));
|
||||
// two double colons
|
||||
assert_eq!(None, FromStr::from_str::<IpAddr>("1:2::6::8"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_from_str_ipv4_in_ipv6() {
|
||||
assert_eq!(Some(Ipv6Addr(0, 0, 0, 0, 0, 0, 49152, 545)),
|
||||
FromStr::from_str("::192.0.2.33"));
|
||||
assert_eq!(Some(Ipv6Addr(0, 0, 0, 0, 0, 0xFFFF, 49152, 545)),
|
||||
FromStr::from_str("::FFFF:192.0.2.33"));
|
||||
assert_eq!(Some(Ipv6Addr(0x64, 0xff9b, 0, 0, 0, 0, 49152, 545)),
|
||||
FromStr::from_str("64:ff9b::192.0.2.33"));
|
||||
assert_eq!(Some(Ipv6Addr(0x2001, 0xdb8, 0x122, 0xc000, 0x2, 0x2100, 49152, 545)),
|
||||
FromStr::from_str("2001:db8:122:c000:2:2100:192.0.2.33"));
|
||||
|
||||
// colon after v4
|
||||
assert_eq!(None, FromStr::from_str::<IpAddr>("::127.0.0.1:"));
|
||||
// not enought groups
|
||||
assert_eq!(None, FromStr::from_str::<IpAddr>("1.2.3.4.5:127.0.0.1"));
|
||||
// too many groups
|
||||
assert_eq!(None, FromStr::from_str::<IpAddr>("1.2.3.4.5:6:7:127.0.0.1"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_from_str_socket_addr() {
|
||||
assert_eq!(Some(SocketAddr { ip: Ipv4Addr(77, 88, 21, 11), port: 80 }),
|
||||
FromStr::from_str("77.88.21.11:80"));
|
||||
assert_eq!(Some(SocketAddr { ip: Ipv6Addr(0x2a02, 0x6b8, 0, 1, 0, 0, 0, 1), port: 53 }),
|
||||
FromStr::from_str("[2a02:6b8:0:1::1]:53"));
|
||||
assert_eq!(Some(SocketAddr { ip: Ipv6Addr(0, 0, 0, 0, 0, 0, 0x7F00, 1), port: 22 }),
|
||||
FromStr::from_str("[::127.0.0.1]:22"));
|
||||
|
||||
// without port
|
||||
assert_eq!(None, FromStr::from_str::<SocketAddr>("127.0.0.1"));
|
||||
// without port
|
||||
assert_eq!(None, FromStr::from_str::<SocketAddr>("127.0.0.1:"));
|
||||
// wrong brackets around v4
|
||||
assert_eq!(None, FromStr::from_str::<SocketAddr>("[127.0.0.1]:22"));
|
||||
// port out of range
|
||||
assert_eq!(None, FromStr::from_str::<SocketAddr>("127.0.0.1:123456"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ipv6_addr_to_str() {
|
||||
let a1 = Ipv6Addr(0, 0, 0, 0, 0, 0xffff, 0xc000, 0x280);
|
||||
assert!(a1.to_str() == ~"::ffff:192.0.2.128" || a1.to_str() == ~"::FFFF:192.0.2.128");
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@
|
|||
use libc;
|
||||
use libc::{c_void, uintptr_t, size_t};
|
||||
use ops::Drop;
|
||||
use option::{Some, None};
|
||||
use rt;
|
||||
use rt::OldTaskContext;
|
||||
use rt::local::Local;
|
||||
|
|
@ -86,8 +87,12 @@ impl Drop for LocalHeap {
|
|||
|
||||
// A little compatibility function
|
||||
pub unsafe fn local_free(ptr: *libc::c_char) {
|
||||
match rt::context() {
|
||||
OldTaskContext => {
|
||||
// XXX: Unsafe borrow for speed. Lame.
|
||||
match Local::try_unsafe_borrow::<Task>() {
|
||||
Some(task) => {
|
||||
(*task).heap.free(ptr as *libc::c_void);
|
||||
}
|
||||
None => {
|
||||
rust_upcall_free_noswitch(ptr);
|
||||
|
||||
extern {
|
||||
|
|
@ -95,11 +100,6 @@ pub unsafe fn local_free(ptr: *libc::c_char) {
|
|||
fn rust_upcall_free_noswitch(ptr: *libc::c_char);
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
do Local::borrow::<Task,()> |task| {
|
||||
task.heap.free(ptr as *libc::c_void);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -119,20 +119,28 @@ pub fn live_allocs() -> *raw::Box<()> {
|
|||
}
|
||||
|
||||
extern {
|
||||
#[fast_ffi]
|
||||
fn rust_new_memory_region(synchronized: uintptr_t,
|
||||
detailed_leaks: uintptr_t,
|
||||
poison_on_free: uintptr_t) -> *MemoryRegion;
|
||||
#[fast_ffi]
|
||||
fn rust_delete_memory_region(region: *MemoryRegion);
|
||||
#[fast_ffi]
|
||||
fn rust_new_boxed_region(region: *MemoryRegion,
|
||||
poison_on_free: uintptr_t) -> *BoxedRegion;
|
||||
#[fast_ffi]
|
||||
fn rust_delete_boxed_region(region: *BoxedRegion);
|
||||
#[fast_ffi]
|
||||
fn rust_boxed_region_malloc(region: *BoxedRegion,
|
||||
td: *TypeDesc,
|
||||
size: size_t) -> *OpaqueBox;
|
||||
#[fast_ffi]
|
||||
fn rust_boxed_region_realloc(region: *BoxedRegion,
|
||||
ptr: *OpaqueBox,
|
||||
size: size_t) -> *OpaqueBox;
|
||||
#[fast_ffi]
|
||||
fn rust_boxed_region_free(region: *BoxedRegion, box: *OpaqueBox);
|
||||
#[fast_ffi]
|
||||
fn rust_current_boxed_region() -> *BoxedRegion;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -407,14 +407,10 @@ fn run_(main: ~fn(), use_main_sched: bool) -> int {
|
|||
/// or the old scheduler.
|
||||
#[deriving(Eq)]
|
||||
pub enum RuntimeContext {
|
||||
// Only the exchange heap is available
|
||||
GlobalContext,
|
||||
// The scheduler may be accessed
|
||||
SchedulerContext,
|
||||
// Full task services, e.g. local heap, unwinding
|
||||
TaskContext,
|
||||
// Running in an old-style task
|
||||
OldTaskContext
|
||||
OldTaskContext,
|
||||
// Not old task context
|
||||
NewRtContext
|
||||
}
|
||||
|
||||
/// Determine the current RuntimeContext
|
||||
|
|
@ -424,19 +420,8 @@ pub fn context() -> RuntimeContext {
|
|||
|
||||
if unsafe { rust_try_get_task().is_not_null() } {
|
||||
return OldTaskContext;
|
||||
} else if Local::exists::<Task>() {
|
||||
// In this case we know it is a new runtime context, but we
|
||||
// need to check which one. Going to try borrowing task to
|
||||
// check. Task should always be in TLS, so hopefully this
|
||||
// doesn't conflict with other ops that borrow.
|
||||
return do Local::borrow::<Task,RuntimeContext> |task| {
|
||||
match task.task_type {
|
||||
SchedTask => SchedulerContext,
|
||||
GreenTask(_) => TaskContext
|
||||
}
|
||||
};
|
||||
} else {
|
||||
return GlobalContext;
|
||||
return NewRtContext;
|
||||
}
|
||||
|
||||
extern {
|
||||
|
|
@ -444,3 +429,31 @@ pub fn context() -> RuntimeContext {
|
|||
pub fn rust_try_get_task() -> *rust_task;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn in_sched_context() -> bool {
|
||||
unsafe {
|
||||
match Local::try_unsafe_borrow::<Task>() {
|
||||
Some(task) => {
|
||||
match (*task).task_type {
|
||||
SchedTask => true,
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
None => false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn in_green_task_context() -> bool {
|
||||
unsafe {
|
||||
match Local::try_unsafe_borrow::<Task>() {
|
||||
Some(task) => {
|
||||
match (*task).task_type {
|
||||
GreenTask(_) => true,
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
None => false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -20,7 +20,6 @@ use rt::uv::last_uv_error;
|
|||
use vec;
|
||||
use str;
|
||||
use from_str::{FromStr};
|
||||
use num;
|
||||
|
||||
pub enum UvSocketAddr {
|
||||
UvIpv4SocketAddr(*sockaddr_in),
|
||||
|
|
@ -85,77 +84,10 @@ fn uv_socket_addr_as_socket_addr<T>(addr: UvSocketAddr, f: &fn(SocketAddr) -> T)
|
|||
port as u16
|
||||
};
|
||||
let ip_str = str::from_bytes_slice(ip_name).trim_right_chars(&'\x00');
|
||||
let ip = match addr {
|
||||
UvIpv4SocketAddr(*) => {
|
||||
let ip: ~[u8] =
|
||||
ip_str.split_iter('.')
|
||||
.transform(|s: &str| -> u8 { FromStr::from_str(s).unwrap() })
|
||||
.collect();
|
||||
assert_eq!(ip.len(), 4);
|
||||
SocketAddr {
|
||||
ip: Ipv4Addr(ip[0], ip[1], ip[2], ip[3]),
|
||||
port: ip_port
|
||||
}
|
||||
},
|
||||
UvIpv6SocketAddr(*) => {
|
||||
let ip: ~[u16] = {
|
||||
let expand_shorthand_and_convert = |s: &str| -> ~[~[u16]] {
|
||||
let convert_each_segment = |s: &str| -> ~[u16] {
|
||||
let read_hex_segment = |s: &str| -> u16 {
|
||||
num::FromStrRadix::from_str_radix(s, 16u).unwrap()
|
||||
};
|
||||
match s {
|
||||
"" => ~[],
|
||||
// IPv4-Mapped/Compatible IPv6 Address?
|
||||
s if s.find('.').is_some() => {
|
||||
let i = s.rfind(':').unwrap_or_default(-1);
|
||||
|
||||
let b = s.slice(i + 1, s.len()); // the ipv4 part
|
||||
|
||||
let h = b.split_iter('.')
|
||||
.transform(|s: &str| -> u8 { FromStr::from_str(s).unwrap() })
|
||||
.transform(|s: u8| -> ~str { fmt!("%02x", s as uint) })
|
||||
.collect::<~[~str]>();
|
||||
|
||||
if i == -1 {
|
||||
// Ipv4 Compatible Address (::x.x.x.x)
|
||||
// first 96 bits are zero leaving 32 bits
|
||||
// for the ipv4 part
|
||||
// (i.e ::127.0.0.1 == ::7F00:1)
|
||||
~[num::FromStrRadix::from_str_radix(h[0] + h[1], 16).unwrap(),
|
||||
num::FromStrRadix::from_str_radix(h[2] + h[3], 16).unwrap()]
|
||||
} else {
|
||||
// Ipv4-Mapped Address (::FFFF:x.x.x.x)
|
||||
// first 80 bits are zero, followed by all ones
|
||||
// for the next 16 bits, leaving 32 bits for
|
||||
// the ipv4 part
|
||||
// (i.e ::FFFF:127.0.0.1 == ::FFFF:7F00:1)
|
||||
~[1,
|
||||
num::FromStrRadix::from_str_radix(h[0] + h[1], 16).unwrap(),
|
||||
num::FromStrRadix::from_str_radix(h[2] + h[3], 16).unwrap()]
|
||||
}
|
||||
},
|
||||
s => s.split_iter(':').transform(read_hex_segment).collect()
|
||||
}
|
||||
};
|
||||
s.split_str_iter("::").transform(convert_each_segment).collect()
|
||||
};
|
||||
match expand_shorthand_and_convert(ip_str) {
|
||||
[x] => x, // no shorthand found
|
||||
[l, r] => l + vec::from_elem(8 - l.len() - r.len(), 0u16) + r, // fill the gap
|
||||
_ => fail!(), // impossible. only one shorthand allowed.
|
||||
}
|
||||
};
|
||||
assert_eq!(ip.len(), 8);
|
||||
SocketAddr {
|
||||
ip: Ipv6Addr(ip[0], ip[1], ip[2], ip[3], ip[4], ip[5], ip[6], ip[7]),
|
||||
port: ip_port
|
||||
}
|
||||
},
|
||||
};
|
||||
let ip_addr = FromStr::from_str(ip_str).unwrap();
|
||||
|
||||
// finally run the closure
|
||||
f(ip)
|
||||
f(SocketAddr { ip: ip_addr, port: ip_port })
|
||||
}
|
||||
|
||||
pub fn uv_socket_addr_to_socket_addr(addr: UvSocketAddr) -> SocketAddr {
|
||||
|
|
|
|||
|
|
@ -1329,11 +1329,11 @@ mod tests {
|
|||
let output = str::from_bytes(prog.finish_with_output().output);
|
||||
|
||||
let r = os::env();
|
||||
for &(k, v) in r.iter() {
|
||||
for &(ref k, ref v) in r.iter() {
|
||||
// don't check android RANDOM variables
|
||||
if k != ~"RANDOM" {
|
||||
assert!(output.contains(fmt!("%s=%s", k, v)) ||
|
||||
output.contains(fmt!("%s=\'%s\'", k, v)));
|
||||
if *k != ~"RANDOM" {
|
||||
assert!(output.contains(fmt!("%s=%s", *k, *v)) ||
|
||||
output.contains(fmt!("%s=\'%s\'", *k, *v)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1243,34 +1243,16 @@ pub mod traits {
|
|||
impl<'self> Ord for &'self str {
|
||||
#[inline]
|
||||
fn lt(&self, other: & &'self str) -> bool { self.cmp(other) == Less }
|
||||
#[inline]
|
||||
fn le(&self, other: & &'self str) -> bool { self.cmp(other) != Greater }
|
||||
#[inline]
|
||||
fn ge(&self, other: & &'self str) -> bool { self.cmp(other) != Less }
|
||||
#[inline]
|
||||
fn gt(&self, other: & &'self str) -> bool { self.cmp(other) == Greater }
|
||||
}
|
||||
|
||||
impl Ord for ~str {
|
||||
#[inline]
|
||||
fn lt(&self, other: &~str) -> bool { self.cmp(other) == Less }
|
||||
#[inline]
|
||||
fn le(&self, other: &~str) -> bool { self.cmp(other) != Greater }
|
||||
#[inline]
|
||||
fn ge(&self, other: &~str) -> bool { self.cmp(other) != Less }
|
||||
#[inline]
|
||||
fn gt(&self, other: &~str) -> bool { self.cmp(other) == Greater }
|
||||
}
|
||||
|
||||
impl Ord for @str {
|
||||
#[inline]
|
||||
fn lt(&self, other: &@str) -> bool { self.cmp(other) == Less }
|
||||
#[inline]
|
||||
fn le(&self, other: &@str) -> bool { self.cmp(other) != Greater }
|
||||
#[inline]
|
||||
fn ge(&self, other: &@str) -> bool { self.cmp(other) != Less }
|
||||
#[inline]
|
||||
fn gt(&self, other: &@str) -> bool { self.cmp(other) == Greater }
|
||||
}
|
||||
|
||||
impl<'self, S: Str> Equiv<S> for &'self str {
|
||||
|
|
|
|||
|
|
@ -136,7 +136,7 @@ impl FailWithCause for &'static str {
|
|||
pub fn begin_unwind_(msg: *c_char, file: *c_char, line: size_t) -> ! {
|
||||
use either::Left;
|
||||
use option::{Some, None};
|
||||
use rt::{context, OldTaskContext, TaskContext};
|
||||
use rt::{context, OldTaskContext, in_green_task_context};
|
||||
use rt::task::Task;
|
||||
use rt::local::Local;
|
||||
use rt::logging::Logger;
|
||||
|
|
@ -158,7 +158,7 @@ pub fn begin_unwind_(msg: *c_char, file: *c_char, line: size_t) -> ! {
|
|||
|
||||
// XXX: Logging doesn't work correctly in non-task context because it
|
||||
// invokes the local heap
|
||||
if context == TaskContext {
|
||||
if in_green_task_context() {
|
||||
// XXX: Logging doesn't work here - the check to call the log
|
||||
// function never passes - so calling the log function directly.
|
||||
do Local::borrow::<Task, ()> |task| {
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ use cmp::Eq;
|
|||
use comm::{stream, Chan, GenericChan, GenericPort, Port};
|
||||
use result::Result;
|
||||
use result;
|
||||
use rt::{context, OldTaskContext, TaskContext};
|
||||
use rt::{context, OldTaskContext, in_green_task_context};
|
||||
use rt::local::Local;
|
||||
use unstable::finally::Finally;
|
||||
use util;
|
||||
|
|
@ -527,14 +527,15 @@ pub fn try<T:Send>(f: ~fn() -> T) -> Result<T,()> {
|
|||
pub fn with_task_name<U>(blk: &fn(Option<&str>) -> U) -> U {
|
||||
use rt::task::Task;
|
||||
|
||||
match context() {
|
||||
TaskContext => do Local::borrow::<Task, U> |task| {
|
||||
if in_green_task_context() {
|
||||
do Local::borrow::<Task, U> |task| {
|
||||
match task.name {
|
||||
Some(ref name) => blk(Some(name.as_slice())),
|
||||
None => blk(None)
|
||||
}
|
||||
},
|
||||
_ => fail!("no task name exists in %?", context()),
|
||||
}
|
||||
} else {
|
||||
fail!("no task name exists in %?", context())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -614,7 +615,7 @@ pub fn unkillable<U>(f: &fn() -> U) -> U {
|
|||
rt::rust_task_allow_kill(t);
|
||||
}
|
||||
}
|
||||
TaskContext => {
|
||||
_ if in_green_task_context() => {
|
||||
// The inhibits/allows might fail and need to borrow the task.
|
||||
let t = Local::unsafe_borrow::<Task>();
|
||||
do (|| {
|
||||
|
|
@ -645,7 +646,7 @@ pub unsafe fn rekillable<U>(f: &fn() -> U) -> U {
|
|||
rt::rust_task_inhibit_kill(t);
|
||||
}
|
||||
}
|
||||
TaskContext => {
|
||||
_ if in_green_task_context() => {
|
||||
let t = Local::unsafe_borrow::<Task>();
|
||||
do (|| {
|
||||
(*t).death.allow_kill((*t).unwinder.unwinding);
|
||||
|
|
|
|||
|
|
@ -91,7 +91,7 @@ use to_bytes::IterBytes;
|
|||
use uint;
|
||||
use util;
|
||||
use unstable::sync::Exclusive;
|
||||
use rt::{OldTaskContext, TaskContext, SchedulerContext, GlobalContext, context};
|
||||
use rt::{OldTaskContext, NewRtContext, context, in_green_task_context};
|
||||
use rt::local::Local;
|
||||
use rt::task::{Task, Sched};
|
||||
use rt::kill::KillHandle;
|
||||
|
|
@ -526,7 +526,7 @@ impl RuntimeGlue {
|
|||
let me = rt::rust_get_task();
|
||||
blk(OldTask(me), rt::rust_task_is_unwinding(me))
|
||||
},
|
||||
TaskContext => unsafe {
|
||||
NewRtContext if in_green_task_context() => unsafe {
|
||||
// Can't use safe borrow, because the taskgroup destructor needs to
|
||||
// access the scheduler again to send kill signals to other tasks.
|
||||
let me = Local::unsafe_borrow::<Task>();
|
||||
|
|
@ -535,7 +535,7 @@ impl RuntimeGlue {
|
|||
blk(NewTask((*me).death.kill_handle.get_ref().clone()),
|
||||
(*me).unwinder.unwinding)
|
||||
},
|
||||
SchedulerContext | GlobalContext => rtabort!("task dying in bad context"),
|
||||
NewRtContext => rtabort!("task dying in bad context"),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -563,7 +563,7 @@ impl RuntimeGlue {
|
|||
}
|
||||
}
|
||||
},
|
||||
TaskContext => unsafe {
|
||||
NewRtContext if in_green_task_context() => unsafe {
|
||||
// Can't use safe borrow, because creating new hashmaps for the
|
||||
// tasksets requires an rng, which needs to borrow the sched.
|
||||
let me = Local::unsafe_borrow::<Task>();
|
||||
|
|
@ -588,7 +588,7 @@ impl RuntimeGlue {
|
|||
Some(ref group) => group,
|
||||
})
|
||||
},
|
||||
SchedulerContext | GlobalContext => rtabort!("spawning in bad context"),
|
||||
NewRtContext => rtabort!("spawning in bad context"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -666,10 +666,9 @@ fn enlist_many(child: TaskHandle, child_arc: &TaskGroupArc,
|
|||
|
||||
pub fn spawn_raw(opts: TaskOpts, f: ~fn()) {
|
||||
match context() {
|
||||
OldTaskContext => spawn_raw_oldsched(opts, f),
|
||||
TaskContext => spawn_raw_newsched(opts, f),
|
||||
SchedulerContext => fail!("can't spawn from scheduler context"),
|
||||
GlobalContext => fail!("can't spawn from global context"),
|
||||
OldTaskContext => spawn_raw_oldsched(opts, f),
|
||||
_ if in_green_task_context() => spawn_raw_newsched(opts, f),
|
||||
_ => fail!("can't spawn from this context")
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -13,9 +13,9 @@
|
|||
use c_str::ToCStr;
|
||||
use cast::transmute;
|
||||
use libc::{c_char, c_uchar, c_void, size_t, uintptr_t, c_int};
|
||||
use option::{Some, None};
|
||||
use str;
|
||||
use sys;
|
||||
use rt::{context, OldTaskContext};
|
||||
use rt::task::Task;
|
||||
use rt::local::Local;
|
||||
use rt::borrowck;
|
||||
|
|
@ -57,16 +57,13 @@ pub fn fail_bounds_check(file: *c_char, line: size_t,
|
|||
|
||||
#[lang="malloc"]
|
||||
pub unsafe fn local_malloc(td: *c_char, size: uintptr_t) -> *c_char {
|
||||
match context() {
|
||||
OldTaskContext => {
|
||||
return rustrt::rust_upcall_malloc_noswitch(td, size);
|
||||
// XXX: Unsafe borrow for speed. Lame.
|
||||
match Local::try_unsafe_borrow::<Task>() {
|
||||
Some(task) => {
|
||||
(*task).heap.alloc(td as *c_void, size as uint) as *c_char
|
||||
}
|
||||
_ => {
|
||||
let mut alloc = ::ptr::null();
|
||||
do Local::borrow::<Task,()> |task| {
|
||||
alloc = task.heap.alloc(td as *c_void, size as uint) as *c_char;
|
||||
}
|
||||
return alloc;
|
||||
None => {
|
||||
rustrt::rust_upcall_malloc_noswitch(td, size)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -282,7 +282,7 @@ pub unsafe fn atomically<U>(f: &fn() -> U) -> U {
|
|||
use rt::task::Task;
|
||||
use task::rt;
|
||||
use rt::local::Local;
|
||||
use rt::{context, OldTaskContext, TaskContext};
|
||||
use rt::{context, OldTaskContext};
|
||||
|
||||
match context() {
|
||||
OldTaskContext => {
|
||||
|
|
@ -296,17 +296,23 @@ pub unsafe fn atomically<U>(f: &fn() -> U) -> U {
|
|||
rt::rust_task_allow_kill(t);
|
||||
}
|
||||
}
|
||||
TaskContext => {
|
||||
let t = Local::unsafe_borrow::<Task>();
|
||||
do (|| {
|
||||
(*t).death.inhibit_yield();
|
||||
f()
|
||||
}).finally {
|
||||
(*t).death.allow_yield();
|
||||
_ => {
|
||||
let t = Local::try_unsafe_borrow::<Task>();
|
||||
match t {
|
||||
Some(t) => {
|
||||
do (|| {
|
||||
(*t).death.inhibit_yield();
|
||||
f()
|
||||
}).finally {
|
||||
(*t).death.allow_yield();
|
||||
}
|
||||
}
|
||||
None => {
|
||||
// FIXME(#3095): As in unkillable().
|
||||
f()
|
||||
}
|
||||
}
|
||||
}
|
||||
// FIXME(#3095): As in unkillable().
|
||||
_ => f()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue