}
}
-/** Initiate task failure */
+/// Trait for initiating task failure.
+pub trait FailWithCause {
+ /// Fail the current task, taking ownership of `cause`
+ fn fail_with(cause: Self, file: &'static str, line: uint) -> !;
+}
+
+impl FailWithCause for ~str {
+ fn fail_with(cause: ~str, file: &'static str, line: uint) -> ! {
+ do str::as_buf(cause) |msg_buf, _msg_len| {
+ do str::as_buf(file) |file_buf, _file_len| {
+ unsafe {
+ let msg_buf = cast::transmute(msg_buf);
+ let file_buf = cast::transmute(file_buf);
+ begin_unwind_(msg_buf, file_buf, line as libc::size_t)
+ }
+ }
+ }
+ }
+}
+
+impl FailWithCause for &'static str {
+ fn fail_with(cause: &'static str, file: &'static str, line: uint) -> ! {
+ do str::as_buf(cause) |msg_buf, _msg_len| {
+ do str::as_buf(file) |file_buf, _file_len| {
+ unsafe {
+ let msg_buf = cast::transmute(msg_buf);
+ let file_buf = cast::transmute(file_buf);
+ begin_unwind_(msg_buf, file_buf, line as libc::size_t)
+ }
+ }
+ }
+ }
+}
+
+// NOTE: remove function after snapshot
+#[cfg(stage0)]
pub fn begin_unwind(msg: ~str, file: ~str, line: uint) -> ! {
- do str::as_buf(msg) |msg_buf, _msg_len| {
- do str::as_buf(file) |file_buf, _file_len| {
+
+ use rt::{context, OldTaskContext};
+ use rt::local_services::unsafe_borrow_local_services;
+
+ match context() {
+ OldTaskContext => {
+ do str::as_buf(msg) |msg_buf, _msg_len| {
+ do str::as_buf(file) |file_buf, _file_len| {
+ unsafe {
+ let msg_buf = cast::transmute(msg_buf);
+ let file_buf = cast::transmute(file_buf);
+ begin_unwind_(msg_buf, file_buf, line as libc::size_t)
+ }
+ }
+ }
+ }
+ _ => {
+ gc::cleanup_stack_for_failure();
unsafe {
- let msg_buf = cast::transmute(msg_buf);
- let file_buf = cast::transmute(file_buf);
- begin_unwind_(msg_buf, file_buf, line as libc::size_t)
+ let local_services = unsafe_borrow_local_services();
+ match local_services.unwinder {
+ Some(ref mut unwinder) => unwinder.begin_unwind(),
+ None => abort!("failure without unwinder. aborting process")
+ }
}
}
}
let map_ptr = rt::rust_get_task_local_data(task);
if map_ptr.is_null() {
let map: TaskLocalMap = @mut ~[];
- // Use reinterpret_cast -- transmute would take map away from us also.
- rt::rust_set_task_local_data(
- task, cast::transmute(map));
+ rt::rust_set_task_local_data(task, cast::transmute(map));
- rt::rust_task_local_data_atexit(task, cleanup_task_local_map);
+ rt::rust_task_local_data_atexit(task, cleanup_task_local_map_extern_cb);
// Also need to reference it an extra time to keep it for now.
let nonmut = cast::transmute::<TaskLocalMap,
@~[Option<TaskLocalElement>]>(map);
}
}
-unsafe fn key_to_key_value<T:Durable>(
- key: LocalDataKey<T>) -> *libc::c_void {
-
+ unsafe fn get_newsched_local_map(local: *mut LocalStorage) -> TaskLocalMap {
+ match &mut *local {
+ &LocalStorage(map_ptr, Some(_)) => {
+ assert!(map_ptr.is_not_null());
+ let map = cast::transmute(map_ptr);
+ let nonmut = cast::transmute::<TaskLocalMap,
+ @~[Option<TaskLocalElement>]>(map);
+ cast::bump_box_refcount(nonmut);
+ return map;
+ }
+ &LocalStorage(ref mut map_ptr, ref mut at_exit) => {
+ assert!((*map_ptr).is_null());
+ let map: TaskLocalMap = @mut ~[];
+ *map_ptr = cast::transmute(map);
+ let at_exit_fn: ~fn(*libc::c_void) = |p|cleanup_task_local_map(p);
+ *at_exit = Some(at_exit_fn);
+ return map;
+ }
+ }
+ }
+
+unsafe fn key_to_key_value<T:Durable>(key: LocalDataKey<T>) -> *libc::c_void {
// Keys are closures, which are (fnptr,envptr) pairs. Use fnptr.
// Use reintepret_cast -- transmute would leak (forget) the closure.
- let pair: (*libc::c_void, *libc::c_void) = cast::transmute(key);
+ let pair: (*libc::c_void, *libc::c_void) = cast::transmute_copy(&key);
pair.first()
}