2014-01-15 11:34:05 -06:00
|
|
|
// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT
|
2013-04-21 18:28:17 -05:00
|
|
|
// 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.
|
|
|
|
|
|
|
|
//! Language-level runtime services that should reasonably expected
|
|
|
|
//! to be available 'everywhere'. Local heaps, GC, unwinding,
|
|
|
|
//! local storage, and logging. Even a 'freestanding' Rust would likely want
|
|
|
|
//! to implement this.
|
|
|
|
|
2014-05-19 19:33:40 -05:00
|
|
|
use alloc::arc::Arc;
|
|
|
|
|
2013-06-22 03:09:06 -05:00
|
|
|
use cleanup;
|
2014-01-06 18:48:51 -06:00
|
|
|
use clone::Clone;
|
2014-03-09 16:58:32 -05:00
|
|
|
use comm::Sender;
|
2013-12-05 20:19:06 -06:00
|
|
|
use io::Writer;
|
2013-12-18 11:57:58 -06:00
|
|
|
use iter::{Iterator, Take};
|
2014-03-08 20:21:49 -06:00
|
|
|
use kinds::Send;
|
2013-10-11 16:20:34 -05:00
|
|
|
use local_data;
|
core: Remove the cast module
This commit revisits the `cast` module in libcore and libstd, and scrutinizes
all functions inside of it. The result was to remove the `cast` module entirely,
folding all functionality into the `mem` module. Specifically, this is the fate
of each function in the `cast` module.
* transmute - This function was moved to `mem`, but it is now marked as
#[unstable]. This is due to planned changes to the `transmute`
function and how it can be invoked (see the #[unstable] comment).
For more information, see RFC 5 and #12898
* transmute_copy - This function was moved to `mem`, with clarification that is
is not an error to invoke it with T/U that are different
sizes, but rather that it is strongly discouraged. This
function is now #[stable]
* forget - This function was moved to `mem` and marked #[stable]
* bump_box_refcount - This function was removed due to the deprecation of
managed boxes as well as its questionable utility.
* transmute_mut - This function was previously deprecated, and removed as part
of this commit.
* transmute_mut_unsafe - This function doesn't serve much of a purpose when it
can be achieved with an `as` in safe code, so it was
removed.
* transmute_lifetime - This function was removed because it is likely a strong
indication that code is incorrect in the first place.
* transmute_mut_lifetime - This function was removed for the same reasons as
`transmute_lifetime`
* copy_lifetime - This function was moved to `mem`, but it is marked
`#[unstable]` now due to the likelihood of being removed in
the future if it is found to not be very useful.
* copy_mut_lifetime - This function was also moved to `mem`, but had the same
treatment as `copy_lifetime`.
* copy_lifetime_vec - This function was removed because it is not used today,
and its existence is not necessary with DST
(copy_lifetime will suffice).
In summary, the cast module was stripped down to these functions, and then the
functions were moved to the `mem` module.
transmute - #[unstable]
transmute_copy - #[stable]
forget - #[stable]
copy_lifetime - #[unstable]
copy_mut_lifetime - #[unstable]
[breaking-change]
2014-05-09 12:34:51 -05:00
|
|
|
use mem;
|
2013-12-12 20:01:59 -06:00
|
|
|
use ops::Drop;
|
2013-06-14 01:31:19 -05:00
|
|
|
use option::{Option, Some, None};
|
2014-05-13 16:58:29 -05:00
|
|
|
use owned::{AnyOwnExt, Box};
|
2013-12-12 20:01:59 -06:00
|
|
|
use prelude::drop;
|
|
|
|
use result::{Result, Ok, Err};
|
|
|
|
use rt::Runtime;
|
2013-05-19 17:45:39 -05:00
|
|
|
use rt::local::Local;
|
2013-12-12 20:01:59 -06:00
|
|
|
use rt::local_heap::LocalHeap;
|
|
|
|
use rt::rtio::LocalIo;
|
2013-12-15 19:17:07 -06:00
|
|
|
use rt::unwind::Unwinder;
|
2014-02-07 18:36:59 -06:00
|
|
|
use str::SendStr;
|
2013-12-30 02:55:27 -06:00
|
|
|
use sync::atomics::{AtomicUint, SeqCst};
|
2013-12-12 20:01:59 -06:00
|
|
|
use task::{TaskResult, TaskOpts};
|
2014-05-21 00:27:24 -05:00
|
|
|
use finally::Finally;
|
2013-12-12 20:01:59 -06:00
|
|
|
|
2014-01-15 11:34:05 -06:00
|
|
|
/// The Task struct represents all state associated with a rust
|
|
|
|
/// task. There are at this point two primary "subtypes" of task,
|
|
|
|
/// however instead of using a subtype we just have a "task_type" field
|
|
|
|
/// in the struct. This contains a pointer to another struct that holds
|
|
|
|
/// the type-specific state.
|
2013-05-19 03:04:01 -05:00
|
|
|
pub struct Task {
|
2014-03-27 17:09:47 -05:00
|
|
|
pub heap: LocalHeap,
|
|
|
|
pub gc: GarbageCollector,
|
|
|
|
pub storage: LocalStorage,
|
|
|
|
pub unwinder: Unwinder,
|
|
|
|
pub death: Death,
|
|
|
|
pub destroyed: bool,
|
|
|
|
pub name: Option<SendStr>,
|
2013-12-12 20:01:59 -06:00
|
|
|
|
2014-05-05 20:56:44 -05:00
|
|
|
pub stdout: Option<Box<Writer:Send>>,
|
|
|
|
pub stderr: Option<Box<Writer:Send>>,
|
2013-12-04 21:51:29 -06:00
|
|
|
|
2014-05-05 20:56:44 -05:00
|
|
|
imp: Option<Box<Runtime:Send>>,
|
2013-07-19 16:25:05 -05:00
|
|
|
}
|
|
|
|
|
2013-12-12 20:01:59 -06:00
|
|
|
pub struct GarbageCollector;
|
2014-03-31 21:01:01 -05:00
|
|
|
pub struct LocalStorage(pub Option<local_data::Map>);
|
2013-06-26 18:41:00 -05:00
|
|
|
|
2014-05-05 20:56:44 -05:00
|
|
|
/// A handle to a blocked task. Usually this means having the Box<Task>
|
|
|
|
/// pointer by ownership, but if the task is killable, a killer can steal it
|
|
|
|
/// at any time.
|
2013-12-12 20:01:59 -06:00
|
|
|
pub enum BlockedTask {
|
2014-05-05 20:56:44 -05:00
|
|
|
Owned(Box<Task>),
|
2014-05-19 19:33:40 -05:00
|
|
|
Shared(Arc<AtomicUint>),
|
2013-06-26 18:41:00 -05:00
|
|
|
}
|
|
|
|
|
2014-02-10 16:49:56 -06:00
|
|
|
pub enum DeathAction {
|
|
|
|
/// Action to be done with the exit code. If set, also makes the task wait
|
|
|
|
/// until all its watched children exit before collecting the status.
|
2014-04-07 15:30:48 -05:00
|
|
|
Execute(proc(TaskResult):Send),
|
2014-02-10 16:49:56 -06:00
|
|
|
/// A channel to send the result of the task on when the task exits
|
2014-03-09 16:58:32 -05:00
|
|
|
SendMessage(Sender<TaskResult>),
|
2014-02-10 16:49:56 -06:00
|
|
|
}
|
|
|
|
|
2013-12-12 20:01:59 -06:00
|
|
|
/// Per-task state related to task death, killing, failure, etc.
|
|
|
|
pub struct Death {
|
2014-03-27 17:09:47 -05:00
|
|
|
pub on_exit: Option<DeathAction>,
|
2013-04-21 18:28:17 -05:00
|
|
|
}
|
|
|
|
|
2014-01-14 21:32:24 -06:00
|
|
|
pub struct BlockedTasks {
|
2014-05-19 19:33:40 -05:00
|
|
|
inner: Arc<AtomicUint>,
|
2013-12-12 20:01:59 -06:00
|
|
|
}
|
2013-04-22 19:15:31 -05:00
|
|
|
|
2013-05-19 03:04:01 -05:00
|
|
|
impl Task {
|
2013-12-12 20:01:59 -06:00
|
|
|
pub fn new() -> Task {
|
2013-05-19 03:04:01 -05:00
|
|
|
Task {
|
2013-04-21 21:03:52 -05:00
|
|
|
heap: LocalHeap::new(),
|
2013-04-21 18:28:17 -05:00
|
|
|
gc: GarbageCollector,
|
2013-08-10 22:06:39 -05:00
|
|
|
storage: LocalStorage(None),
|
2013-12-12 20:01:59 -06:00
|
|
|
unwinder: Unwinder::new(),
|
2013-07-01 22:24:24 -05:00
|
|
|
death: Death::new(),
|
2013-06-26 18:41:00 -05:00
|
|
|
destroyed: false,
|
2013-07-30 18:20:59 -05:00
|
|
|
name: None,
|
2014-01-06 12:26:11 -06:00
|
|
|
stdout: None,
|
|
|
|
stderr: None,
|
2013-12-12 20:01:59 -06:00
|
|
|
imp: None,
|
2013-04-21 18:28:17 -05:00
|
|
|
}
|
|
|
|
}
|
2013-04-22 14:54:03 -05:00
|
|
|
|
2013-12-12 20:01:59 -06:00
|
|
|
/// Executes the given closure as if it's running inside this task. The task
|
|
|
|
/// is consumed upon entry, and the destroyed task is returned from this
|
|
|
|
/// function in order for the caller to free. This function is guaranteed to
|
|
|
|
/// not unwind because the closure specified is run inside of a `rust_try`
|
|
|
|
/// block. (this is the only try/catch block in the world).
|
|
|
|
///
|
|
|
|
/// This function is *not* meant to be abused as a "try/catch" block. This
|
|
|
|
/// is meant to be used at the absolute boundaries of a task's lifetime, and
|
|
|
|
/// only for that purpose.
|
2014-05-05 20:56:44 -05:00
|
|
|
pub fn run(~self, mut f: ||) -> Box<Task> {
|
2013-12-12 20:01:59 -06:00
|
|
|
// Need to put ourselves into TLS, but also need access to the unwinder.
|
|
|
|
// Unsafely get a handle to the task so we can continue to use it after
|
|
|
|
// putting it in tls (so we can invoke the unwinder).
|
|
|
|
let handle: *mut Task = unsafe {
|
core: Remove the cast module
This commit revisits the `cast` module in libcore and libstd, and scrutinizes
all functions inside of it. The result was to remove the `cast` module entirely,
folding all functionality into the `mem` module. Specifically, this is the fate
of each function in the `cast` module.
* transmute - This function was moved to `mem`, but it is now marked as
#[unstable]. This is due to planned changes to the `transmute`
function and how it can be invoked (see the #[unstable] comment).
For more information, see RFC 5 and #12898
* transmute_copy - This function was moved to `mem`, with clarification that is
is not an error to invoke it with T/U that are different
sizes, but rather that it is strongly discouraged. This
function is now #[stable]
* forget - This function was moved to `mem` and marked #[stable]
* bump_box_refcount - This function was removed due to the deprecation of
managed boxes as well as its questionable utility.
* transmute_mut - This function was previously deprecated, and removed as part
of this commit.
* transmute_mut_unsafe - This function doesn't serve much of a purpose when it
can be achieved with an `as` in safe code, so it was
removed.
* transmute_lifetime - This function was removed because it is likely a strong
indication that code is incorrect in the first place.
* transmute_mut_lifetime - This function was removed for the same reasons as
`transmute_lifetime`
* copy_lifetime - This function was moved to `mem`, but it is marked
`#[unstable]` now due to the likelihood of being removed in
the future if it is found to not be very useful.
* copy_mut_lifetime - This function was also moved to `mem`, but had the same
treatment as `copy_lifetime`.
* copy_lifetime_vec - This function was removed because it is not used today,
and its existence is not necessary with DST
(copy_lifetime will suffice).
In summary, the cast module was stripped down to these functions, and then the
functions were moved to the `mem` module.
transmute - #[unstable]
transmute_copy - #[stable]
forget - #[stable]
copy_lifetime - #[unstable]
copy_mut_lifetime - #[unstable]
[breaking-change]
2014-05-09 12:34:51 -05:00
|
|
|
*mem::transmute::<&Box<Task>, &*mut Task>(&self)
|
2013-12-12 20:01:59 -06:00
|
|
|
};
|
|
|
|
Local::put(self);
|
2013-04-22 19:15:31 -05:00
|
|
|
|
2013-08-03 16:43:16 -05:00
|
|
|
// The only try/catch block in the world. Attempt to run the task's
|
|
|
|
// client-specified code and catch any failures.
|
2013-12-12 20:01:59 -06:00
|
|
|
let try_block = || {
|
2013-06-26 18:41:00 -05:00
|
|
|
|
2013-08-03 16:43:16 -05:00
|
|
|
// Run the task main function, then do some cleanup.
|
2013-11-20 16:17:12 -06:00
|
|
|
f.finally(|| {
|
2014-01-29 18:33:57 -06:00
|
|
|
#[allow(unused_must_use)]
|
2014-01-06 12:26:11 -06:00
|
|
|
fn close_outputs() {
|
|
|
|
let mut task = Local::borrow(None::<Task>);
|
2014-04-13 16:39:04 -05:00
|
|
|
let stderr = task.stderr.take();
|
|
|
|
let stdout = task.stdout.take();
|
2014-01-06 12:26:11 -06:00
|
|
|
drop(task);
|
2014-01-29 18:33:57 -06:00
|
|
|
match stdout { Some(mut w) => { w.flush(); }, None => {} }
|
|
|
|
match stderr { Some(mut w) => { w.flush(); }, None => {} }
|
2013-12-12 20:01:59 -06:00
|
|
|
}
|
2013-10-24 19:30:36 -05:00
|
|
|
|
2014-01-06 12:26:11 -06:00
|
|
|
// First, flush/destroy the user stdout/logger because these
|
|
|
|
// destructors can run arbitrary code.
|
|
|
|
close_outputs();
|
|
|
|
|
2013-08-10 22:06:39 -05:00
|
|
|
// First, destroy task-local storage. This may run user dtors.
|
|
|
|
//
|
2013-08-05 02:32:46 -05:00
|
|
|
// FIXME #8302: Dear diary. I'm so tired and confused.
|
|
|
|
// There's some interaction in rustc between the box
|
|
|
|
// annihilator and the TLS dtor by which TLS is
|
|
|
|
// accessed from annihilated box dtors *after* TLS is
|
|
|
|
// destroyed. Somehow setting TLS back to null, as the
|
|
|
|
// old runtime did, makes this work, but I don't currently
|
|
|
|
// understand how. I would expect that, if the annihilator
|
|
|
|
// reinvokes TLS while TLS is uninitialized, that
|
|
|
|
// TLS would be reinitialized but never destroyed,
|
|
|
|
// but somehow this works. I have no idea what's going
|
|
|
|
// on but this seems to make things magically work. FML.
|
2013-08-10 22:06:39 -05:00
|
|
|
//
|
|
|
|
// (added after initial comment) A possible interaction here is
|
|
|
|
// that the destructors for the objects in TLS themselves invoke
|
|
|
|
// TLS, or possibly some destructors for those objects being
|
|
|
|
// annihilated invoke TLS. Sadly these two operations seemed to
|
|
|
|
// be intertwined, and miraculously work for now...
|
2013-12-12 20:01:59 -06:00
|
|
|
let mut task = Local::borrow(None::<Task>);
|
2013-11-01 20:06:31 -05:00
|
|
|
let storage_map = {
|
2014-04-13 16:39:04 -05:00
|
|
|
let &LocalStorage(ref mut optmap) = &mut task.storage;
|
2013-11-01 20:06:31 -05:00
|
|
|
optmap.take()
|
|
|
|
};
|
2013-12-12 20:01:59 -06:00
|
|
|
drop(task);
|
2013-11-01 20:06:31 -05:00
|
|
|
drop(storage_map);
|
2013-08-05 02:32:46 -05:00
|
|
|
|
2013-08-03 16:43:16 -05:00
|
|
|
// Destroy remaining boxes. Also may run user dtors.
|
|
|
|
unsafe { cleanup::annihilate(); }
|
2013-10-24 19:30:36 -05:00
|
|
|
|
2014-01-06 12:26:11 -06:00
|
|
|
// Finally, just in case user dtors printed/logged during TLS
|
|
|
|
// cleanup and annihilation, re-destroy stdout and the logger.
|
|
|
|
// Note that these will have been initialized with a
|
|
|
|
// runtime-provided type which we have control over what the
|
|
|
|
// destructor does.
|
|
|
|
close_outputs();
|
2013-11-20 16:17:12 -06:00
|
|
|
})
|
2013-12-12 20:01:59 -06:00
|
|
|
};
|
|
|
|
|
|
|
|
unsafe { (*handle).unwinder.try(try_block); }
|
2013-06-22 03:09:06 -05:00
|
|
|
|
2013-12-13 23:14:08 -06:00
|
|
|
// Here we must unsafely borrow the task in order to not remove it from
|
|
|
|
// TLS. When collecting failure, we may attempt to send on a channel (or
|
|
|
|
// just run aribitrary code), so we must be sure to still have a local
|
|
|
|
// task in TLS.
|
2013-12-12 23:38:57 -06:00
|
|
|
unsafe {
|
|
|
|
let me: *mut Task = Local::unsafe_borrow();
|
|
|
|
(*me).death.collect_failure((*me).unwinder.result());
|
|
|
|
}
|
2014-05-05 20:56:44 -05:00
|
|
|
let mut me: Box<Task> = Local::take();
|
2013-12-12 20:01:59 -06:00
|
|
|
me.destroyed = true;
|
|
|
|
return me;
|
2013-04-22 14:54:03 -05:00
|
|
|
}
|
2013-06-26 18:41:00 -05:00
|
|
|
|
2013-12-12 20:01:59 -06:00
|
|
|
/// Inserts a runtime object into this task, transferring ownership to the
|
|
|
|
/// task. It is illegal to replace a previous runtime object in this task
|
|
|
|
/// with this argument.
|
2014-05-05 20:56:44 -05:00
|
|
|
pub fn put_runtime(&mut self, ops: Box<Runtime:Send>) {
|
2013-12-12 20:01:59 -06:00
|
|
|
assert!(self.imp.is_none());
|
|
|
|
self.imp = Some(ops);
|
|
|
|
}
|
2013-06-26 18:41:00 -05:00
|
|
|
|
2013-12-12 20:01:59 -06:00
|
|
|
/// Attempts to extract the runtime as a specific type. If the runtime does
|
|
|
|
/// not have the provided type, then the runtime is not removed. If the
|
|
|
|
/// runtime does have the specified type, then it is removed and returned
|
|
|
|
/// (transfer of ownership).
|
|
|
|
///
|
|
|
|
/// It is recommended to only use this method when *absolutely necessary*.
|
|
|
|
/// This function may not be available in the future.
|
2014-05-05 20:56:44 -05:00
|
|
|
pub fn maybe_take_runtime<T: 'static>(&mut self) -> Option<Box<T>> {
|
2013-12-12 20:01:59 -06:00
|
|
|
// This is a terrible, terrible function. The general idea here is to
|
2014-05-05 20:56:44 -05:00
|
|
|
// take the runtime, cast it to Box<Any>, check if it has the right
|
|
|
|
// type, and then re-cast it back if necessary. The method of doing
|
|
|
|
// this is pretty sketchy and involves shuffling vtables of trait
|
|
|
|
// objects around, but it gets the job done.
|
2013-12-12 20:01:59 -06:00
|
|
|
//
|
2014-01-26 02:43:42 -06:00
|
|
|
// FIXME: This function is a serious code smell and should be avoided at
|
2013-12-12 20:01:59 -06:00
|
|
|
// all costs. I have yet to think of a method to avoid this
|
|
|
|
// function, and I would be saddened if more usage of the function
|
|
|
|
// crops up.
|
|
|
|
unsafe {
|
|
|
|
let imp = self.imp.take_unwrap();
|
core: Remove the cast module
This commit revisits the `cast` module in libcore and libstd, and scrutinizes
all functions inside of it. The result was to remove the `cast` module entirely,
folding all functionality into the `mem` module. Specifically, this is the fate
of each function in the `cast` module.
* transmute - This function was moved to `mem`, but it is now marked as
#[unstable]. This is due to planned changes to the `transmute`
function and how it can be invoked (see the #[unstable] comment).
For more information, see RFC 5 and #12898
* transmute_copy - This function was moved to `mem`, with clarification that is
is not an error to invoke it with T/U that are different
sizes, but rather that it is strongly discouraged. This
function is now #[stable]
* forget - This function was moved to `mem` and marked #[stable]
* bump_box_refcount - This function was removed due to the deprecation of
managed boxes as well as its questionable utility.
* transmute_mut - This function was previously deprecated, and removed as part
of this commit.
* transmute_mut_unsafe - This function doesn't serve much of a purpose when it
can be achieved with an `as` in safe code, so it was
removed.
* transmute_lifetime - This function was removed because it is likely a strong
indication that code is incorrect in the first place.
* transmute_mut_lifetime - This function was removed for the same reasons as
`transmute_lifetime`
* copy_lifetime - This function was moved to `mem`, but it is marked
`#[unstable]` now due to the likelihood of being removed in
the future if it is found to not be very useful.
* copy_mut_lifetime - This function was also moved to `mem`, but had the same
treatment as `copy_lifetime`.
* copy_lifetime_vec - This function was removed because it is not used today,
and its existence is not necessary with DST
(copy_lifetime will suffice).
In summary, the cast module was stripped down to these functions, and then the
functions were moved to the `mem` module.
transmute - #[unstable]
transmute_copy - #[stable]
forget - #[stable]
copy_lifetime - #[unstable]
copy_mut_lifetime - #[unstable]
[breaking-change]
2014-05-09 12:34:51 -05:00
|
|
|
let &(vtable, _): &(uint, uint) = mem::transmute(&imp);
|
2013-12-12 20:01:59 -06:00
|
|
|
match imp.wrap().move::<T>() {
|
|
|
|
Ok(t) => Some(t),
|
|
|
|
Err(t) => {
|
core: Remove the cast module
This commit revisits the `cast` module in libcore and libstd, and scrutinizes
all functions inside of it. The result was to remove the `cast` module entirely,
folding all functionality into the `mem` module. Specifically, this is the fate
of each function in the `cast` module.
* transmute - This function was moved to `mem`, but it is now marked as
#[unstable]. This is due to planned changes to the `transmute`
function and how it can be invoked (see the #[unstable] comment).
For more information, see RFC 5 and #12898
* transmute_copy - This function was moved to `mem`, with clarification that is
is not an error to invoke it with T/U that are different
sizes, but rather that it is strongly discouraged. This
function is now #[stable]
* forget - This function was moved to `mem` and marked #[stable]
* bump_box_refcount - This function was removed due to the deprecation of
managed boxes as well as its questionable utility.
* transmute_mut - This function was previously deprecated, and removed as part
of this commit.
* transmute_mut_unsafe - This function doesn't serve much of a purpose when it
can be achieved with an `as` in safe code, so it was
removed.
* transmute_lifetime - This function was removed because it is likely a strong
indication that code is incorrect in the first place.
* transmute_mut_lifetime - This function was removed for the same reasons as
`transmute_lifetime`
* copy_lifetime - This function was moved to `mem`, but it is marked
`#[unstable]` now due to the likelihood of being removed in
the future if it is found to not be very useful.
* copy_mut_lifetime - This function was also moved to `mem`, but had the same
treatment as `copy_lifetime`.
* copy_lifetime_vec - This function was removed because it is not used today,
and its existence is not necessary with DST
(copy_lifetime will suffice).
In summary, the cast module was stripped down to these functions, and then the
functions were moved to the `mem` module.
transmute - #[unstable]
transmute_copy - #[stable]
forget - #[stable]
copy_lifetime - #[unstable]
copy_mut_lifetime - #[unstable]
[breaking-change]
2014-05-09 12:34:51 -05:00
|
|
|
let (_, obj): (uint, uint) = mem::transmute(t);
|
2014-05-05 20:56:44 -05:00
|
|
|
let obj: Box<Runtime:Send> =
|
core: Remove the cast module
This commit revisits the `cast` module in libcore and libstd, and scrutinizes
all functions inside of it. The result was to remove the `cast` module entirely,
folding all functionality into the `mem` module. Specifically, this is the fate
of each function in the `cast` module.
* transmute - This function was moved to `mem`, but it is now marked as
#[unstable]. This is due to planned changes to the `transmute`
function and how it can be invoked (see the #[unstable] comment).
For more information, see RFC 5 and #12898
* transmute_copy - This function was moved to `mem`, with clarification that is
is not an error to invoke it with T/U that are different
sizes, but rather that it is strongly discouraged. This
function is now #[stable]
* forget - This function was moved to `mem` and marked #[stable]
* bump_box_refcount - This function was removed due to the deprecation of
managed boxes as well as its questionable utility.
* transmute_mut - This function was previously deprecated, and removed as part
of this commit.
* transmute_mut_unsafe - This function doesn't serve much of a purpose when it
can be achieved with an `as` in safe code, so it was
removed.
* transmute_lifetime - This function was removed because it is likely a strong
indication that code is incorrect in the first place.
* transmute_mut_lifetime - This function was removed for the same reasons as
`transmute_lifetime`
* copy_lifetime - This function was moved to `mem`, but it is marked
`#[unstable]` now due to the likelihood of being removed in
the future if it is found to not be very useful.
* copy_mut_lifetime - This function was also moved to `mem`, but had the same
treatment as `copy_lifetime`.
* copy_lifetime_vec - This function was removed because it is not used today,
and its existence is not necessary with DST
(copy_lifetime will suffice).
In summary, the cast module was stripped down to these functions, and then the
functions were moved to the `mem` module.
transmute - #[unstable]
transmute_copy - #[stable]
forget - #[stable]
copy_lifetime - #[unstable]
copy_mut_lifetime - #[unstable]
[breaking-change]
2014-05-09 12:34:51 -05:00
|
|
|
mem::transmute((vtable, obj));
|
2013-12-12 20:01:59 -06:00
|
|
|
self.put_runtime(obj);
|
|
|
|
None
|
|
|
|
}
|
2013-06-26 18:41:00 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-12-12 20:01:59 -06:00
|
|
|
/// Spawns a sibling to this task. The newly spawned task is configured with
|
|
|
|
/// the `opts` structure and will run `f` as the body of its code.
|
2014-04-07 15:30:48 -05:00
|
|
|
pub fn spawn_sibling(mut ~self, opts: TaskOpts, f: proc():Send) {
|
2013-12-12 20:01:59 -06:00
|
|
|
let ops = self.imp.take_unwrap();
|
|
|
|
ops.spawn_sibling(self, opts, f)
|
2013-06-26 18:41:00 -05:00
|
|
|
}
|
|
|
|
|
2013-12-12 20:01:59 -06:00
|
|
|
/// Deschedules the current task, invoking `f` `amt` times. It is not
|
|
|
|
/// recommended to use this function directly, but rather communication
|
|
|
|
/// primitives in `std::comm` should be used.
|
|
|
|
pub fn deschedule(mut ~self, amt: uint,
|
|
|
|
f: |BlockedTask| -> Result<(), BlockedTask>) {
|
|
|
|
let ops = self.imp.take_unwrap();
|
|
|
|
ops.deschedule(amt, self, f)
|
|
|
|
}
|
|
|
|
|
2014-02-17 05:53:45 -06:00
|
|
|
/// Wakes up a previously blocked task, optionally specifying whether the
|
2013-12-12 20:01:59 -06:00
|
|
|
/// current task can accept a change in scheduling. This function can only
|
|
|
|
/// be called on tasks that were previously blocked in `deschedule`.
|
2014-01-16 21:58:42 -06:00
|
|
|
pub fn reawaken(mut ~self) {
|
2013-12-12 20:01:59 -06:00
|
|
|
let ops = self.imp.take_unwrap();
|
2014-01-16 21:58:42 -06:00
|
|
|
ops.reawaken(self);
|
2013-12-12 20:01:59 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Yields control of this task to another task. This function will
|
|
|
|
/// eventually return, but possibly not immediately. This is used as an
|
|
|
|
/// opportunity to allow other tasks a chance to run.
|
|
|
|
pub fn yield_now(mut ~self) {
|
|
|
|
let ops = self.imp.take_unwrap();
|
|
|
|
ops.yield_now(self);
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Similar to `yield_now`, except that this function may immediately return
|
|
|
|
/// without yielding (depending on what the runtime decides to do).
|
|
|
|
pub fn maybe_yield(mut ~self) {
|
|
|
|
let ops = self.imp.take_unwrap();
|
|
|
|
ops.maybe_yield(self);
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Acquires a handle to the I/O factory that this task contains, normally
|
|
|
|
/// stored in the task's runtime. This factory may not always be available,
|
|
|
|
/// which is why the return type is `Option`
|
|
|
|
pub fn local_io<'a>(&'a mut self) -> Option<LocalIo<'a>> {
|
|
|
|
self.imp.get_mut_ref().local_io()
|
2013-06-26 18:41:00 -05:00
|
|
|
}
|
2014-01-04 02:06:13 -06:00
|
|
|
|
|
|
|
/// Returns the stack bounds for this task in (lo, hi) format. The stack
|
|
|
|
/// bounds may not be known for all tasks, so the return value may be
|
|
|
|
/// `None`.
|
2014-01-06 20:39:55 -06:00
|
|
|
pub fn stack_bounds(&self) -> (uint, uint) {
|
2014-01-04 02:06:13 -06:00
|
|
|
self.imp.get_ref().stack_bounds()
|
|
|
|
}
|
2014-01-16 21:58:42 -06:00
|
|
|
|
|
|
|
/// Returns whether it is legal for this task to block the OS thread that it
|
|
|
|
/// is running on.
|
|
|
|
pub fn can_block(&self) -> bool {
|
|
|
|
self.imp.get_ref().can_block()
|
|
|
|
}
|
2013-04-22 14:54:03 -05:00
|
|
|
}
|
|
|
|
|
2013-05-19 03:04:01 -05:00
|
|
|
impl Drop for Task {
|
2013-09-16 20:18:07 -05:00
|
|
|
fn drop(&mut self) {
|
2014-01-28 20:05:57 -06:00
|
|
|
rtdebug!("called drop for a task: {}", self as *mut Task as uint);
|
2013-10-24 19:30:36 -05:00
|
|
|
rtassert!(self.destroyed);
|
2013-07-19 16:25:05 -05:00
|
|
|
}
|
2013-04-21 18:28:17 -05:00
|
|
|
}
|
|
|
|
|
2014-01-14 21:32:24 -06:00
|
|
|
impl Iterator<BlockedTask> for BlockedTasks {
|
2013-12-12 20:01:59 -06:00
|
|
|
fn next(&mut self) -> Option<BlockedTask> {
|
|
|
|
Some(Shared(self.inner.clone()))
|
2013-06-26 18:41:00 -05:00
|
|
|
}
|
2013-12-12 20:01:59 -06:00
|
|
|
}
|
2013-06-26 18:41:00 -05:00
|
|
|
|
2013-12-12 20:01:59 -06:00
|
|
|
impl BlockedTask {
|
|
|
|
/// Returns Some if the task was successfully woken; None if already killed.
|
2014-05-05 20:56:44 -05:00
|
|
|
pub fn wake(self) -> Option<Box<Task>> {
|
2013-12-12 20:01:59 -06:00
|
|
|
match self {
|
|
|
|
Owned(task) => Some(task),
|
2014-05-19 19:33:40 -05:00
|
|
|
Shared(arc) => {
|
|
|
|
match arc.swap(0, SeqCst) {
|
2013-12-12 20:01:59 -06:00
|
|
|
0 => None,
|
2014-05-19 19:33:40 -05:00
|
|
|
n => Some(unsafe { mem::transmute(n) }),
|
2013-12-12 20:01:59 -06:00
|
|
|
}
|
|
|
|
}
|
2013-07-19 16:25:05 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-04-25 22:47:49 -05:00
|
|
|
/// Reawakens this task if ownership is acquired. If finer-grained control
|
|
|
|
/// is desired, use `wake` instead.
|
|
|
|
pub fn reawaken(self) {
|
|
|
|
self.wake().map(|t| t.reawaken());
|
|
|
|
}
|
|
|
|
|
2013-12-12 20:01:59 -06:00
|
|
|
// This assertion has two flavours because the wake involves an atomic op.
|
|
|
|
// In the faster version, destructors will fail dramatically instead.
|
|
|
|
#[cfg(not(test))] pub fn trash(self) { }
|
|
|
|
#[cfg(test)] pub fn trash(self) { assert!(self.wake().is_none()); }
|
2013-06-26 18:41:00 -05:00
|
|
|
|
2013-12-12 20:01:59 -06:00
|
|
|
/// Create a blocked task, unless the task was already killed.
|
2014-05-05 20:56:44 -05:00
|
|
|
pub fn block(task: Box<Task>) -> BlockedTask {
|
2013-12-12 20:01:59 -06:00
|
|
|
Owned(task)
|
|
|
|
}
|
2013-07-19 16:25:05 -05:00
|
|
|
|
2013-12-12 20:01:59 -06:00
|
|
|
/// Converts one blocked task handle to a list of many handles to the same.
|
2014-04-13 16:39:04 -05:00
|
|
|
pub fn make_selectable(self, num_handles: uint) -> Take<BlockedTasks> {
|
2013-12-12 20:01:59 -06:00
|
|
|
let arc = match self {
|
|
|
|
Owned(task) => {
|
core: Remove the cast module
This commit revisits the `cast` module in libcore and libstd, and scrutinizes
all functions inside of it. The result was to remove the `cast` module entirely,
folding all functionality into the `mem` module. Specifically, this is the fate
of each function in the `cast` module.
* transmute - This function was moved to `mem`, but it is now marked as
#[unstable]. This is due to planned changes to the `transmute`
function and how it can be invoked (see the #[unstable] comment).
For more information, see RFC 5 and #12898
* transmute_copy - This function was moved to `mem`, with clarification that is
is not an error to invoke it with T/U that are different
sizes, but rather that it is strongly discouraged. This
function is now #[stable]
* forget - This function was moved to `mem` and marked #[stable]
* bump_box_refcount - This function was removed due to the deprecation of
managed boxes as well as its questionable utility.
* transmute_mut - This function was previously deprecated, and removed as part
of this commit.
* transmute_mut_unsafe - This function doesn't serve much of a purpose when it
can be achieved with an `as` in safe code, so it was
removed.
* transmute_lifetime - This function was removed because it is likely a strong
indication that code is incorrect in the first place.
* transmute_mut_lifetime - This function was removed for the same reasons as
`transmute_lifetime`
* copy_lifetime - This function was moved to `mem`, but it is marked
`#[unstable]` now due to the likelihood of being removed in
the future if it is found to not be very useful.
* copy_mut_lifetime - This function was also moved to `mem`, but had the same
treatment as `copy_lifetime`.
* copy_lifetime_vec - This function was removed because it is not used today,
and its existence is not necessary with DST
(copy_lifetime will suffice).
In summary, the cast module was stripped down to these functions, and then the
functions were moved to the `mem` module.
transmute - #[unstable]
transmute_copy - #[stable]
forget - #[stable]
copy_lifetime - #[unstable]
copy_mut_lifetime - #[unstable]
[breaking-change]
2014-05-09 12:34:51 -05:00
|
|
|
let flag = unsafe { AtomicUint::new(mem::transmute(task)) };
|
2014-05-19 19:33:40 -05:00
|
|
|
Arc::new(flag)
|
2013-06-26 18:41:00 -05:00
|
|
|
}
|
2013-12-12 20:01:59 -06:00
|
|
|
Shared(arc) => arc.clone(),
|
2013-06-26 18:41:00 -05:00
|
|
|
};
|
2014-01-14 21:32:24 -06:00
|
|
|
BlockedTasks{ inner: arc }.take(num_handles)
|
2013-06-26 18:41:00 -05:00
|
|
|
}
|
|
|
|
|
2013-12-12 20:01:59 -06:00
|
|
|
/// Convert to an unsafe uint value. Useful for storing in a pipe's state
|
|
|
|
/// flag.
|
|
|
|
#[inline]
|
|
|
|
pub unsafe fn cast_to_uint(self) -> uint {
|
2013-06-26 18:41:00 -05:00
|
|
|
match self {
|
2013-12-12 20:01:59 -06:00
|
|
|
Owned(task) => {
|
core: Remove the cast module
This commit revisits the `cast` module in libcore and libstd, and scrutinizes
all functions inside of it. The result was to remove the `cast` module entirely,
folding all functionality into the `mem` module. Specifically, this is the fate
of each function in the `cast` module.
* transmute - This function was moved to `mem`, but it is now marked as
#[unstable]. This is due to planned changes to the `transmute`
function and how it can be invoked (see the #[unstable] comment).
For more information, see RFC 5 and #12898
* transmute_copy - This function was moved to `mem`, with clarification that is
is not an error to invoke it with T/U that are different
sizes, but rather that it is strongly discouraged. This
function is now #[stable]
* forget - This function was moved to `mem` and marked #[stable]
* bump_box_refcount - This function was removed due to the deprecation of
managed boxes as well as its questionable utility.
* transmute_mut - This function was previously deprecated, and removed as part
of this commit.
* transmute_mut_unsafe - This function doesn't serve much of a purpose when it
can be achieved with an `as` in safe code, so it was
removed.
* transmute_lifetime - This function was removed because it is likely a strong
indication that code is incorrect in the first place.
* transmute_mut_lifetime - This function was removed for the same reasons as
`transmute_lifetime`
* copy_lifetime - This function was moved to `mem`, but it is marked
`#[unstable]` now due to the likelihood of being removed in
the future if it is found to not be very useful.
* copy_mut_lifetime - This function was also moved to `mem`, but had the same
treatment as `copy_lifetime`.
* copy_lifetime_vec - This function was removed because it is not used today,
and its existence is not necessary with DST
(copy_lifetime will suffice).
In summary, the cast module was stripped down to these functions, and then the
functions were moved to the `mem` module.
transmute - #[unstable]
transmute_copy - #[stable]
forget - #[stable]
copy_lifetime - #[unstable]
copy_mut_lifetime - #[unstable]
[breaking-change]
2014-05-09 12:34:51 -05:00
|
|
|
let blocked_task_ptr: uint = mem::transmute(task);
|
2013-12-12 20:01:59 -06:00
|
|
|
rtassert!(blocked_task_ptr & 0x1 == 0);
|
|
|
|
blocked_task_ptr
|
|
|
|
}
|
|
|
|
Shared(arc) => {
|
core: Remove the cast module
This commit revisits the `cast` module in libcore and libstd, and scrutinizes
all functions inside of it. The result was to remove the `cast` module entirely,
folding all functionality into the `mem` module. Specifically, this is the fate
of each function in the `cast` module.
* transmute - This function was moved to `mem`, but it is now marked as
#[unstable]. This is due to planned changes to the `transmute`
function and how it can be invoked (see the #[unstable] comment).
For more information, see RFC 5 and #12898
* transmute_copy - This function was moved to `mem`, with clarification that is
is not an error to invoke it with T/U that are different
sizes, but rather that it is strongly discouraged. This
function is now #[stable]
* forget - This function was moved to `mem` and marked #[stable]
* bump_box_refcount - This function was removed due to the deprecation of
managed boxes as well as its questionable utility.
* transmute_mut - This function was previously deprecated, and removed as part
of this commit.
* transmute_mut_unsafe - This function doesn't serve much of a purpose when it
can be achieved with an `as` in safe code, so it was
removed.
* transmute_lifetime - This function was removed because it is likely a strong
indication that code is incorrect in the first place.
* transmute_mut_lifetime - This function was removed for the same reasons as
`transmute_lifetime`
* copy_lifetime - This function was moved to `mem`, but it is marked
`#[unstable]` now due to the likelihood of being removed in
the future if it is found to not be very useful.
* copy_mut_lifetime - This function was also moved to `mem`, but had the same
treatment as `copy_lifetime`.
* copy_lifetime_vec - This function was removed because it is not used today,
and its existence is not necessary with DST
(copy_lifetime will suffice).
In summary, the cast module was stripped down to these functions, and then the
functions were moved to the `mem` module.
transmute - #[unstable]
transmute_copy - #[stable]
forget - #[stable]
copy_lifetime - #[unstable]
copy_mut_lifetime - #[unstable]
[breaking-change]
2014-05-09 12:34:51 -05:00
|
|
|
let blocked_task_ptr: uint = mem::transmute(box arc);
|
2013-12-12 20:01:59 -06:00
|
|
|
rtassert!(blocked_task_ptr & 0x1 == 0);
|
|
|
|
blocked_task_ptr | 0x1
|
2013-06-26 18:41:00 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-12-12 20:01:59 -06:00
|
|
|
/// Convert from an unsafe uint value. Useful for retrieving a pipe's state
|
|
|
|
/// flag.
|
|
|
|
#[inline]
|
|
|
|
pub unsafe fn cast_from_uint(blocked_task_ptr: uint) -> BlockedTask {
|
|
|
|
if blocked_task_ptr & 0x1 == 0 {
|
core: Remove the cast module
This commit revisits the `cast` module in libcore and libstd, and scrutinizes
all functions inside of it. The result was to remove the `cast` module entirely,
folding all functionality into the `mem` module. Specifically, this is the fate
of each function in the `cast` module.
* transmute - This function was moved to `mem`, but it is now marked as
#[unstable]. This is due to planned changes to the `transmute`
function and how it can be invoked (see the #[unstable] comment).
For more information, see RFC 5 and #12898
* transmute_copy - This function was moved to `mem`, with clarification that is
is not an error to invoke it with T/U that are different
sizes, but rather that it is strongly discouraged. This
function is now #[stable]
* forget - This function was moved to `mem` and marked #[stable]
* bump_box_refcount - This function was removed due to the deprecation of
managed boxes as well as its questionable utility.
* transmute_mut - This function was previously deprecated, and removed as part
of this commit.
* transmute_mut_unsafe - This function doesn't serve much of a purpose when it
can be achieved with an `as` in safe code, so it was
removed.
* transmute_lifetime - This function was removed because it is likely a strong
indication that code is incorrect in the first place.
* transmute_mut_lifetime - This function was removed for the same reasons as
`transmute_lifetime`
* copy_lifetime - This function was moved to `mem`, but it is marked
`#[unstable]` now due to the likelihood of being removed in
the future if it is found to not be very useful.
* copy_mut_lifetime - This function was also moved to `mem`, but had the same
treatment as `copy_lifetime`.
* copy_lifetime_vec - This function was removed because it is not used today,
and its existence is not necessary with DST
(copy_lifetime will suffice).
In summary, the cast module was stripped down to these functions, and then the
functions were moved to the `mem` module.
transmute - #[unstable]
transmute_copy - #[stable]
forget - #[stable]
copy_lifetime - #[unstable]
copy_mut_lifetime - #[unstable]
[breaking-change]
2014-05-09 12:34:51 -05:00
|
|
|
Owned(mem::transmute(blocked_task_ptr))
|
2013-10-17 03:40:33 -05:00
|
|
|
} else {
|
2014-05-19 19:33:40 -05:00
|
|
|
let ptr: Box<Arc<AtomicUint>> =
|
core: Remove the cast module
This commit revisits the `cast` module in libcore and libstd, and scrutinizes
all functions inside of it. The result was to remove the `cast` module entirely,
folding all functionality into the `mem` module. Specifically, this is the fate
of each function in the `cast` module.
* transmute - This function was moved to `mem`, but it is now marked as
#[unstable]. This is due to planned changes to the `transmute`
function and how it can be invoked (see the #[unstable] comment).
For more information, see RFC 5 and #12898
* transmute_copy - This function was moved to `mem`, with clarification that is
is not an error to invoke it with T/U that are different
sizes, but rather that it is strongly discouraged. This
function is now #[stable]
* forget - This function was moved to `mem` and marked #[stable]
* bump_box_refcount - This function was removed due to the deprecation of
managed boxes as well as its questionable utility.
* transmute_mut - This function was previously deprecated, and removed as part
of this commit.
* transmute_mut_unsafe - This function doesn't serve much of a purpose when it
can be achieved with an `as` in safe code, so it was
removed.
* transmute_lifetime - This function was removed because it is likely a strong
indication that code is incorrect in the first place.
* transmute_mut_lifetime - This function was removed for the same reasons as
`transmute_lifetime`
* copy_lifetime - This function was moved to `mem`, but it is marked
`#[unstable]` now due to the likelihood of being removed in
the future if it is found to not be very useful.
* copy_mut_lifetime - This function was also moved to `mem`, but had the same
treatment as `copy_lifetime`.
* copy_lifetime_vec - This function was removed because it is not used today,
and its existence is not necessary with DST
(copy_lifetime will suffice).
In summary, the cast module was stripped down to these functions, and then the
functions were moved to the `mem` module.
transmute - #[unstable]
transmute_copy - #[stable]
forget - #[stable]
copy_lifetime - #[unstable]
copy_mut_lifetime - #[unstable]
[breaking-change]
2014-05-09 12:34:51 -05:00
|
|
|
mem::transmute(blocked_task_ptr & !1);
|
2013-12-12 20:01:59 -06:00
|
|
|
Shared(*ptr)
|
2013-10-17 03:40:33 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-12-12 20:01:59 -06:00
|
|
|
impl Death {
|
|
|
|
pub fn new() -> Death {
|
|
|
|
Death { on_exit: None, }
|
|
|
|
}
|
2013-10-11 16:20:34 -05:00
|
|
|
|
2013-12-12 20:01:59 -06:00
|
|
|
/// Collect failure exit codes from children and propagate them to a parent.
|
|
|
|
pub fn collect_failure(&mut self, result: TaskResult) {
|
|
|
|
match self.on_exit.take() {
|
2014-02-10 16:49:56 -06:00
|
|
|
Some(Execute(f)) => f(result),
|
std: Make std::comm return types consistent
There are currently a number of return values from the std::comm methods, not
all of which are necessarily completely expressive:
Sender::try_send(t: T) -> bool
This method currently doesn't transmit back the data `t` if the send fails
due to the other end having disconnected. Additionally, this shares the name
of the synchronous try_send method, but it differs in semantics in that it
only has one failure case, not two (the buffer can never be full).
SyncSender::try_send(t: T) -> TrySendResult<T>
This method accurately conveys all possible information, but it uses a
custom type to the std::comm module with no convenience methods on it.
Additionally, if you want to inspect the result you're forced to import
something from `std::comm`.
SyncSender::send_opt(t: T) -> Option<T>
This method uses Some(T) as an "error value" and None as a "success value",
but almost all other uses of Option<T> have Some/None the other way
Receiver::try_recv(t: T) -> TryRecvResult<T>
Similarly to the synchronous try_send, this custom return type is lacking in
terms of usability (no convenience methods).
With this number of drawbacks in mind, I believed it was time to re-work the
return types of these methods. The new API for the comm module is:
Sender::send(t: T) -> ()
Sender::send_opt(t: T) -> Result<(), T>
SyncSender::send(t: T) -> ()
SyncSender::send_opt(t: T) -> Result<(), T>
SyncSender::try_send(t: T) -> Result<(), TrySendError<T>>
Receiver::recv() -> T
Receiver::recv_opt() -> Result<T, ()>
Receiver::try_recv() -> Result<T, TryRecvError>
The notable changes made are:
* Sender::try_send => Sender::send_opt. This renaming brings the semantics in
line with the SyncSender::send_opt method. An asychronous send only has one
failure case, unlike the synchronous try_send method which has two failure
cases (full/disconnected).
* Sender::send_opt returns the data back to the caller if the send is guaranteed
to fail. This method previously returned `bool`, but then it was unable to
retrieve the data if the data was guaranteed to fail to send. There is still a
race such that when `Ok(())` is returned the data could still fail to be
received, but that's inherent to an asynchronous channel.
* Result is now the basis of all return values. This not only adds lots of
convenience methods to all return values for free, but it also means that you
can inspect the return values with no extra imports (Ok/Err are in the
prelude). Additionally, it's now self documenting when something failed or not
because the return value has "Err" in the name.
Things I'm a little uneasy about:
* The methods send_opt and recv_opt are not returning options, but rather
results. I felt more strongly that Option was the wrong return type than the
_opt prefix was wrong, and I coudn't think of a much better name for these
methods. One possible way to think about them is to read the _opt suffix as
"optionally".
* Result<T, ()> is often better expressed as Option<T>. This is only applicable
to the recv_opt() method, but I thought it would be more consistent for
everything to return Result rather than one method returning an Option.
Despite my two reasons to feel uneasy, I feel much better about the consistency
in return values at this point, and I think the only real open question is if
there's a better suffix for {send,recv}_opt.
Closes #11527
2014-04-10 12:53:49 -05:00
|
|
|
Some(SendMessage(ch)) => { let _ = ch.send_opt(result); }
|
2013-12-12 20:01:59 -06:00
|
|
|
None => {}
|
2013-10-11 16:20:34 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-12-12 20:01:59 -06:00
|
|
|
impl Drop for Death {
|
|
|
|
fn drop(&mut self) {
|
|
|
|
// make this type noncopyable
|
2013-10-09 12:34:27 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-04-21 21:03:52 -05:00
|
|
|
#[cfg(test)]
|
|
|
|
mod test {
|
2013-10-27 14:12:40 -05:00
|
|
|
use super::*;
|
2013-12-05 20:19:06 -06:00
|
|
|
use prelude::*;
|
2013-12-12 23:38:57 -06:00
|
|
|
use task;
|
2013-04-21 21:03:52 -05:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn local_heap() {
|
2013-12-12 23:38:57 -06:00
|
|
|
let a = @5;
|
|
|
|
let b = a;
|
|
|
|
assert!(*a == 5);
|
|
|
|
assert!(*b == 5);
|
2013-04-21 21:03:52 -05:00
|
|
|
}
|
2013-04-22 14:54:03 -05:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn tls() {
|
2014-05-22 18:57:53 -05:00
|
|
|
local_data_key!(key: @String)
|
2014-05-25 05:17:19 -05:00
|
|
|
key.replace(Some(@"data".to_string()));
|
2014-04-28 22:36:08 -05:00
|
|
|
assert_eq!(key.get().unwrap().as_slice(), "data");
|
2014-05-22 18:57:53 -05:00
|
|
|
local_data_key!(key2: @String)
|
2014-05-25 05:17:19 -05:00
|
|
|
key2.replace(Some(@"data".to_string()));
|
2014-04-28 22:36:08 -05:00
|
|
|
assert_eq!(key2.get().unwrap().as_slice(), "data");
|
2013-04-22 14:54:03 -05:00
|
|
|
}
|
2013-04-22 19:15:31 -05:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn unwind() {
|
2013-12-12 23:38:57 -06:00
|
|
|
let result = task::try(proc()());
|
|
|
|
rtdebug!("trying first assert");
|
|
|
|
assert!(result.is_ok());
|
|
|
|
let result = task::try::<()>(proc() fail!());
|
|
|
|
rtdebug!("trying second assert");
|
|
|
|
assert!(result.is_err());
|
2013-04-22 19:15:31 -05:00
|
|
|
}
|
2013-05-06 20:24:37 -05:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn rng() {
|
2014-03-17 16:34:25 -05:00
|
|
|
use rand::{StdRng, Rng};
|
2014-05-01 13:12:16 -05:00
|
|
|
let mut r = StdRng::new().ok().unwrap();
|
2013-12-12 23:38:57 -06:00
|
|
|
let _ = r.next_u32();
|
2013-05-06 20:24:37 -05:00
|
|
|
}
|
2013-04-27 20:57:15 -05:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn logging() {
|
2013-12-12 23:38:57 -06:00
|
|
|
info!("here i am. logging in a newsched task");
|
2013-04-27 20:57:15 -05:00
|
|
|
}
|
2013-05-17 01:12:22 -05:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn comm_stream() {
|
2014-03-09 16:58:32 -05:00
|
|
|
let (tx, rx) = channel();
|
|
|
|
tx.send(10);
|
|
|
|
assert!(rx.recv() == 10);
|
2013-05-17 01:12:22 -05:00
|
|
|
}
|
2013-06-14 01:31:19 -05:00
|
|
|
|
2013-06-20 20:26:56 -05:00
|
|
|
#[test]
|
|
|
|
fn comm_shared_chan() {
|
2014-03-09 16:58:32 -05:00
|
|
|
let (tx, rx) = channel();
|
|
|
|
tx.send(10);
|
|
|
|
assert!(rx.recv() == 10);
|
2013-06-20 20:26:56 -05:00
|
|
|
}
|
|
|
|
|
2013-06-22 03:09:06 -05:00
|
|
|
#[test]
|
|
|
|
fn heap_cycles() {
|
2013-12-30 19:46:48 -06:00
|
|
|
use cell::RefCell;
|
2013-06-22 03:09:06 -05:00
|
|
|
use option::{Option, Some, None};
|
|
|
|
|
2013-12-12 23:38:57 -06:00
|
|
|
struct List {
|
2013-12-30 19:46:48 -06:00
|
|
|
next: Option<@RefCell<List>>,
|
2013-12-12 23:38:57 -06:00
|
|
|
}
|
2013-06-22 03:09:06 -05:00
|
|
|
|
2013-12-30 19:46:48 -06:00
|
|
|
let a = @RefCell::new(List { next: None });
|
|
|
|
let b = @RefCell::new(List { next: Some(a) });
|
2013-06-22 03:09:06 -05:00
|
|
|
|
2013-12-30 19:46:48 -06:00
|
|
|
{
|
|
|
|
let mut a = a.borrow_mut();
|
2014-03-20 17:04:55 -05:00
|
|
|
a.next = Some(b);
|
2013-12-30 19:46:48 -06:00
|
|
|
}
|
2013-06-22 03:09:06 -05:00
|
|
|
}
|
2013-10-27 14:12:40 -05:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
#[should_fail]
|
2013-12-18 11:57:58 -06:00
|
|
|
fn test_begin_unwind() {
|
|
|
|
use rt::unwind::begin_unwind;
|
|
|
|
begin_unwind("cause", file!(), line!())
|
|
|
|
}
|
2013-12-12 20:01:59 -06:00
|
|
|
|
|
|
|
// Task blocking tests
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn block_and_wake() {
|
2014-04-25 03:08:02 -05:00
|
|
|
let task = box Task::new();
|
2013-12-12 23:38:57 -06:00
|
|
|
let mut task = BlockedTask::block(task).wake().unwrap();
|
|
|
|
task.destroyed = true;
|
2013-12-12 20:01:59 -06:00
|
|
|
}
|
2013-05-08 14:26:34 -05:00
|
|
|
}
|