Skip to content

Commit

Permalink
auto merge of #14644 : alexcrichton/rust/more-no-runtime-use-cases, r…
Browse files Browse the repository at this point in the history
…=brson

A few notable improvements were implemented to cut down on the number of aborts
triggered by the standard library when a local task is not found.

* Primarily, the unwinding functionality was restructured to support an unsafe
  top-level function, `try`. This function invokes a closure, capturing any
  failure which occurs inside of it. The purpose of this function is to be as
  lightweight of a "try block" as possible for rust, intended for use when the
  runtime is difficult to set up.

  This function is *not* meant to be used by normal rust code, nor should it be
  consider for use with normal rust code.

* When invoking spawn(), a `fail!()` is triggered rather than an abort.

* When invoking LocalIo::borrow(), which is transitively called by all I/O
  constructors, None is returned rather than aborting to indicate that there is
  no local I/O implementation.

A test case was also added showing the variety of things that you can do without
a runtime or task set up now. In general, this is just a refactoring to abort
less quickly in the standard library when a local task is not found.
  • Loading branch information
bors committed Jun 5, 2014
2 parents bb57e41 + 0c7c93b commit 57e7147
Show file tree
Hide file tree
Showing 5 changed files with 277 additions and 156 deletions.
20 changes: 14 additions & 6 deletions src/libstd/local_data.rs
Expand Up @@ -96,22 +96,24 @@ pub type Map = Vec<Option<(*u8, TLSValue, uint)>>;
type TLSValue = Box<LocalData:Send>;

// Gets the map from the runtime. Lazily initialises if not done so already.
unsafe fn get_local_map() -> &mut Map {
unsafe fn get_local_map() -> Option<&mut Map> {
use rt::local::Local;

if !Local::exists(None::<Task>) { return None }

let task: *mut Task = Local::unsafe_borrow();
match &mut (*task).storage {
// If the at_exit function is already set, then we just need to take
// a loan out on the TLS map stored inside
&LocalStorage(Some(ref mut map_ptr)) => {
return map_ptr;
return Some(map_ptr);
}
// If this is the first time we've accessed TLS, perform similar
// actions to the oldsched way of doing things.
&LocalStorage(ref mut slot) => {
*slot = Some(vec!());
match *slot {
Some(ref mut map_ptr) => { return map_ptr }
Some(ref mut map_ptr) => { return Some(map_ptr) }
None => unreachable!(),
}
}
Expand Down Expand Up @@ -156,7 +158,10 @@ impl<T: 'static> KeyValue<T> {
/// assert_eq!(foo.replace(None), Some(4));
/// ```
pub fn replace(&'static self, data: Option<T>) -> Option<T> {
let map = unsafe { get_local_map() };
let map = match unsafe { get_local_map() } {
Some(map) => map,
None => fail!("must have a local task to insert into TLD"),
};
let keyval = key_to_key_value(self);

// When the task-local map is destroyed, all the data needs to be
Expand Down Expand Up @@ -223,7 +228,10 @@ impl<T: 'static> KeyValue<T> {
/// assert_eq!(*key.get().unwrap(), 3);
/// ```
pub fn get(&'static self) -> Option<Ref<T>> {
let map = unsafe { get_local_map() };
let map = match unsafe { get_local_map() } {
Some(map) => map,
None => return None,
};

self.find(map).map(|(pos, data, loan)| {
*loan += 1;
Expand Down Expand Up @@ -260,7 +268,7 @@ impl<T: 'static> Deref<T> for Ref<T> {
#[unsafe_destructor]
impl<T: 'static> Drop for Ref<T> {
fn drop(&mut self) {
let map = unsafe { get_local_map() };
let map = unsafe { get_local_map().unwrap() };

let (_, _, ref mut loan) = *map.get_mut(self._index).get_mut_ref();
*loan -= 1;
Expand Down
5 changes: 4 additions & 1 deletion src/libstd/rt/rtio.rs
Expand Up @@ -171,7 +171,10 @@ impl<'a> LocalIo<'a> {
//
// In order to get around this, we just transmute a copy out of the task
// in order to have what is likely a static lifetime (bad).
let mut t: Box<Task> = Local::take();
let mut t: Box<Task> = match Local::try_take() {
Some(t) => t,
None => return None,
};
let ret = t.local_io().map(|t| {
unsafe { mem::transmute_copy(&t) }
});
Expand Down

0 comments on commit 57e7147

Please sign in to comment.