Skip to content

Commit 57e7147

Browse files
committed
auto merge of #14644 : alexcrichton/rust/more-no-runtime-use-cases, r=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.
2 parents bb57e41 + 0c7c93b commit 57e7147

File tree

5 files changed

+277
-156
lines changed

5 files changed

+277
-156
lines changed

src/libstd/local_data.rs

+14-6
Original file line numberDiff line numberDiff line change
@@ -96,22 +96,24 @@ pub type Map = Vec<Option<(*u8, TLSValue, uint)>>;
9696
type TLSValue = Box<LocalData:Send>;
9797

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

102+
if !Local::exists(None::<Task>) { return None }
103+
102104
let task: *mut Task = Local::unsafe_borrow();
103105
match &mut (*task).storage {
104106
// If the at_exit function is already set, then we just need to take
105107
// a loan out on the TLS map stored inside
106108
&LocalStorage(Some(ref mut map_ptr)) => {
107-
return map_ptr;
109+
return Some(map_ptr);
108110
}
109111
// If this is the first time we've accessed TLS, perform similar
110112
// actions to the oldsched way of doing things.
111113
&LocalStorage(ref mut slot) => {
112114
*slot = Some(vec!());
113115
match *slot {
114-
Some(ref mut map_ptr) => { return map_ptr }
116+
Some(ref mut map_ptr) => { return Some(map_ptr) }
115117
None => unreachable!(),
116118
}
117119
}
@@ -156,7 +158,10 @@ impl<T: 'static> KeyValue<T> {
156158
/// assert_eq!(foo.replace(None), Some(4));
157159
/// ```
158160
pub fn replace(&'static self, data: Option<T>) -> Option<T> {
159-
let map = unsafe { get_local_map() };
161+
let map = match unsafe { get_local_map() } {
162+
Some(map) => map,
163+
None => fail!("must have a local task to insert into TLD"),
164+
};
160165
let keyval = key_to_key_value(self);
161166

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

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

265273
let (_, _, ref mut loan) = *map.get_mut(self._index).get_mut_ref();
266274
*loan -= 1;

src/libstd/rt/rtio.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,10 @@ impl<'a> LocalIo<'a> {
171171
//
172172
// In order to get around this, we just transmute a copy out of the task
173173
// in order to have what is likely a static lifetime (bad).
174-
let mut t: Box<Task> = Local::take();
174+
let mut t: Box<Task> = match Local::try_take() {
175+
Some(t) => t,
176+
None => return None,
177+
};
175178
let ret = t.local_io().map(|t| {
176179
unsafe { mem::transmute_copy(&t) }
177180
});

0 commit comments

Comments
 (0)