Skip to content

Commit

Permalink
auto merge of #13050 : alexcrichton/rust/no-send-default, r=huonw
Browse files Browse the repository at this point in the history
See #10296 for the rationale, and commits for the implementation.
  • Loading branch information
bors committed Mar 27, 2014
2 parents 8eaada5 + 8d0be73 commit 13dafa0
Show file tree
Hide file tree
Showing 65 changed files with 405 additions and 392 deletions.
32 changes: 17 additions & 15 deletions src/doc/tutorial.md
Original file line number Diff line number Diff line change
Expand Up @@ -2103,7 +2103,7 @@ a `&T` pointer. `MutexArc` is an example of a *sharable* type with internal muta
These are types that do not contain any data whose lifetime is bound to
a particular stack frame. These are types that do not contain any
references, or types where the only contained references
have the `'static` lifetime. (For more on named lifetimes and their uses,
have the `'static` lifetime. (For more on named lifetimes and their uses,
see the [references and lifetimes guide][lifetimes].)

> ***Note:*** These two traits were referred to as 'kinds' in earlier
Expand Down Expand Up @@ -2430,23 +2430,25 @@ select the method to call at runtime.

This usage of traits is similar to Java interfaces.

By default, each of the three storage classes for traits enforce a
particular set of built-in kinds that their contents must fulfill in
order to be packaged up in a trait object of that storage class.
There are some built-in bounds, such as `Send` and `Share`, which are properties
of the components of types. By design, trait objects don't know the exact type
of their contents and so the compiler cannot reason about those properties.

* The contents of owned traits (`~Trait`) must fulfill the `Send` bound.
* The contents of reference traits (`&Trait`) are not constrained by any bound.
You can instruct the compiler, however, that the contents of a trait object must
acribe to a particular bound with a trailing colon (`:`). These are examples of
valid types:

Consequently, the trait objects themselves automatically fulfill their
respective kind bounds. However, this default behavior can be overridden by
specifying a list of bounds on the trait type, for example, by writing `~Trait:`
(which indicates that the contents of the owned trait need not fulfill any
bounds), or by writing `~Trait:Send+Share`, which indicates that in addition
to fulfilling `Send`, contents must also fulfill `Share`, and as a consequence,
the trait itself fulfills `Share`.
~~~rust
trait Foo {}
trait Bar<T> {}

* `~Trait:Send` is equivalent to `~Trait`.
* `&Trait:` is equivalent to `&Trait`.
fn sendable_foo(f: ~Foo:Send) { /* ... */ }
fn shareable_bar<T: Share>(b: &Bar<T>: Share) { /* ... */ }
~~~

When no colon is specified (such as the type `~Foo`), it is inferred that the
value ascribes to no bounds. They must be added manually if any bounds are
necessary for usage.

Builtin kind bounds can also be specified on closure types in the same way (for
example, by writing `fn:Send()`), and the default behaviours are the same as
Expand Down
24 changes: 13 additions & 11 deletions src/libgreen/basic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,14 @@ use std::rt::rtio::{EventLoop, IoFactory, RemoteCallback, PausableIdleCallback,
use std::unstable::sync::Exclusive;

/// This is the only exported function from this module.
pub fn event_loop() -> ~EventLoop {
~BasicLoop::new() as ~EventLoop
pub fn event_loop() -> ~EventLoop:Send {
~BasicLoop::new() as ~EventLoop:Send
}

struct BasicLoop {
work: ~[proc()], // pending work
work: ~[proc:Send()], // pending work
idle: Option<*mut BasicPausable>, // only one is allowed
remotes: ~[(uint, ~Callback)],
remotes: ~[(uint, ~Callback:Send)],
next_remote: uint,
messages: Exclusive<~[Message]>,
}
Expand Down Expand Up @@ -135,26 +135,28 @@ impl EventLoop for BasicLoop {
}
}

fn callback(&mut self, f: proc()) {
fn callback(&mut self, f: proc:Send()) {
self.work.push(f);
}

// FIXME: Seems like a really weird requirement to have an event loop provide.
fn pausable_idle_callback(&mut self, cb: ~Callback) -> ~PausableIdleCallback {
fn pausable_idle_callback(&mut self, cb: ~Callback:Send)
-> ~PausableIdleCallback:Send
{
let callback = ~BasicPausable::new(self, cb);
rtassert!(self.idle.is_none());
unsafe {
let cb_ptr: &*mut BasicPausable = cast::transmute(&callback);
self.idle = Some(*cb_ptr);
}
return callback as ~PausableIdleCallback;
callback as ~PausableIdleCallback:Send
}

fn remote_callback(&mut self, f: ~Callback) -> ~RemoteCallback {
fn remote_callback(&mut self, f: ~Callback:Send) -> ~RemoteCallback:Send {
let id = self.next_remote;
self.next_remote += 1;
self.remotes.push((id, f));
~BasicRemote::new(self.messages.clone(), id) as ~RemoteCallback
~BasicRemote::new(self.messages.clone(), id) as ~RemoteCallback:Send
}

fn io<'a>(&'a mut self) -> Option<&'a mut IoFactory> { None }
Expand Down Expand Up @@ -195,12 +197,12 @@ impl Drop for BasicRemote {

struct BasicPausable {
eloop: *mut BasicLoop,
work: ~Callback,
work: ~Callback:Send,
active: bool,
}

impl BasicPausable {
fn new(eloop: &mut BasicLoop, cb: ~Callback) -> BasicPausable {
fn new(eloop: &mut BasicLoop, cb: ~Callback:Send) -> BasicPausable {
BasicPausable {
active: false,
work: cb,
Expand Down
9 changes: 5 additions & 4 deletions src/libgreen/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,7 @@ pub mod task;
/// The return value is used as the process return code. 0 on success, 101 on
/// error.
pub fn start(argc: int, argv: **u8,
event_loop_factory: fn() -> ~rtio::EventLoop,
event_loop_factory: fn() -> ~rtio::EventLoop:Send,
main: proc()) -> int {
rt::init(argc, argv);
let mut main = Some(main);
Expand All @@ -268,7 +268,8 @@ pub fn start(argc: int, argv: **u8,
///
/// This function will not return until all schedulers in the associated pool
/// have returned.
pub fn run(event_loop_factory: fn() -> ~rtio::EventLoop, main: proc()) -> int {
pub fn run(event_loop_factory: fn() -> ~rtio::EventLoop:Send,
main: proc()) -> int {
// Create a scheduler pool and spawn the main task into this pool. We will
// get notified over a channel when the main task exits.
let mut cfg = PoolConfig::new();
Expand Down Expand Up @@ -298,7 +299,7 @@ pub struct PoolConfig {
threads: uint,
/// A factory function used to create new event loops. If this is not
/// specified then the default event loop factory is used.
event_loop_factory: fn() -> ~rtio::EventLoop,
event_loop_factory: fn() -> ~rtio::EventLoop:Send,
}

impl PoolConfig {
Expand All @@ -323,7 +324,7 @@ pub struct SchedPool {
priv stack_pool: StackPool,
priv deque_pool: deque::BufferPool<~task::GreenTask>,
priv sleepers: SleeperList,
priv factory: fn() -> ~rtio::EventLoop,
priv factory: fn() -> ~rtio::EventLoop:Send,
priv task_state: TaskState,
priv tasks_done: Receiver<()>,
}
Expand Down
19 changes: 9 additions & 10 deletions src/libgreen/sched.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ pub struct Scheduler {
/// A fast XorShift rng for scheduler use
rng: XorShiftRng,
/// A togglable idle callback
idle_callback: Option<~PausableIdleCallback>,
idle_callback: Option<~PausableIdleCallback:Send>,
/// A countdown that starts at a random value and is decremented
/// every time a yield check is performed. When it hits 0 a task
/// will yield.
Expand All @@ -99,7 +99,7 @@ pub struct Scheduler {
// destroyed before it's actually destroyed.

/// The event loop used to drive the scheduler and perform I/O
event_loop: ~EventLoop,
event_loop: ~EventLoop:Send,
}

/// An indication of how hard to work on a given operation, the difference
Expand All @@ -122,7 +122,7 @@ impl Scheduler {
// * Initialization Functions

pub fn new(pool_id: uint,
event_loop: ~EventLoop,
event_loop: ~EventLoop:Send,
work_queue: deque::Worker<~GreenTask>,
work_queues: ~[deque::Stealer<~GreenTask>],
sleeper_list: SleeperList,
Expand All @@ -135,7 +135,7 @@ impl Scheduler {
}

pub fn new_special(pool_id: uint,
event_loop: ~EventLoop,
event_loop: ~EventLoop:Send,
work_queue: deque::Worker<~GreenTask>,
work_queues: ~[deque::Stealer<~GreenTask>],
sleeper_list: SleeperList,
Expand Down Expand Up @@ -182,7 +182,7 @@ impl Scheduler {
pub fn bootstrap(mut ~self) {

// Build an Idle callback.
let cb = ~SchedRunner as ~Callback;
let cb = ~SchedRunner as ~Callback:Send;
self.idle_callback = Some(self.event_loop.pausable_idle_callback(cb));

// Create a task for the scheduler with an empty context.
Expand Down Expand Up @@ -230,7 +230,7 @@ impl Scheduler {
// mutable reference to the event_loop to give it the "run"
// command.
unsafe {
let event_loop: *mut ~EventLoop = &mut self.event_loop;
let event_loop: *mut ~EventLoop:Send = &mut self.event_loop;
// Our scheduler must be in the task before the event loop
// is started.
stask.put_with_sched(self);
Expand Down Expand Up @@ -868,7 +868,7 @@ impl Scheduler {
}

pub fn make_handle(&mut self) -> SchedHandle {
let remote = self.event_loop.remote_callback(~SchedRunner as ~Callback);
let remote = self.event_loop.remote_callback(~SchedRunner);

return SchedHandle {
remote: remote,
Expand All @@ -893,7 +893,7 @@ pub enum SchedMessage {
}

pub struct SchedHandle {
priv remote: ~RemoteCallback,
priv remote: ~RemoteCallback:Send,
priv queue: msgq::Producer<SchedMessage>,
sched_id: uint
}
Expand Down Expand Up @@ -1007,7 +1007,6 @@ mod test {

use std::comm;
use std::task::TaskOpts;
use std::rt::Runtime;
use std::rt::task::Task;
use std::rt::local::Local;

Expand All @@ -1034,7 +1033,7 @@ mod test {
match task.get().maybe_take_runtime::<GreenTask>() {
Some(green) => {
let ret = green.sched.get_ref().sched_id();
task.get().put_runtime(green as ~Runtime);
task.get().put_runtime(green);
return ret;
}
None => fail!()
Expand Down
6 changes: 3 additions & 3 deletions src/libgreen/simple.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ impl Runtime for SimpleTask {

let me = &mut *self as *mut SimpleTask;
let cur_dupe = &*cur_task as *Task;
cur_task.put_runtime(self as ~Runtime);
cur_task.put_runtime(self);
let task = BlockedTask::block(cur_task);

// See libnative/task.rs for what's going on here with the `awoken`
Expand All @@ -57,7 +57,7 @@ impl Runtime for SimpleTask {
}
fn reawaken(mut ~self, mut to_wake: ~Task) {
let me = &mut *self as *mut SimpleTask;
to_wake.put_runtime(self as ~Runtime);
to_wake.put_runtime(self);
unsafe {
cast::forget(to_wake);
let guard = (*me).lock.lock();
Expand Down Expand Up @@ -86,6 +86,6 @@ pub fn task() -> ~Task {
task.put_runtime(~SimpleTask {
lock: unsafe {NativeMutex::new()},
awoken: false,
} as ~Runtime);
});
return task;
}
5 changes: 2 additions & 3 deletions src/libgreen/task.rs
Original file line number Diff line number Diff line change
Expand Up @@ -287,7 +287,7 @@ impl GreenTask {

pub fn swap(mut ~self) -> ~Task {
let mut task = self.task.take_unwrap();
task.put_runtime(self as ~Runtime);
task.put_runtime(self);
return task;
}

Expand Down Expand Up @@ -482,7 +482,6 @@ impl Runtime for GreenTask {

#[cfg(test)]
mod tests {
use std::rt::Runtime;
use std::rt::local::Local;
use std::rt::task::Task;
use std::task;
Expand Down Expand Up @@ -576,7 +575,7 @@ mod tests {
let mut task: ~Task = Local::take();
match task.maybe_take_runtime::<GreenTask>() {
Some(ops) => {
task.put_runtime(ops as ~Runtime);
task.put_runtime(ops);
}
None => fail!(),
}
Expand Down
6 changes: 3 additions & 3 deletions src/liblog/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ pub static WARN: u32 = 2;
/// Error log level
pub static ERROR: u32 = 1;

local_data_key!(local_logger: ~Logger)
local_data_key!(local_logger: ~Logger:Send)

/// A trait used to represent an interface to a task-local logger. Each task
/// can have its own custom logger which can respond to logging messages
Expand Down Expand Up @@ -203,7 +203,7 @@ pub fn log(level: u32, args: &fmt::Arguments) {
// frob the slot while we're doing the logging. This will destroy any logger
// set during logging.
let mut logger = local_data::pop(local_logger).unwrap_or_else(|| {
~DefaultLogger { handle: io::stderr() } as ~Logger
~DefaultLogger { handle: io::stderr() } as ~Logger:Send
});
logger.log(level, args);
local_data::set(local_logger, logger);
Expand All @@ -217,7 +217,7 @@ pub fn log_level() -> u32 { unsafe { LOG_LEVEL } }

/// Replaces the task-local logger with the specified logger, returning the old
/// logger.
pub fn set_logger(logger: ~Logger) -> Option<~Logger> {
pub fn set_logger(logger: ~Logger:Send) -> Option<~Logger:Send> {
let prev = local_data::pop(local_logger);
local_data::set(local_logger, logger);
return prev;
Expand Down
4 changes: 2 additions & 2 deletions src/libnative/io/file_unix.rs
Original file line number Diff line number Diff line change
Expand Up @@ -176,8 +176,8 @@ impl rtio::RtioPipe for FileDesc {
fn write(&mut self, buf: &[u8]) -> Result<(), IoError> {
self.inner_write(buf)
}
fn clone(&self) -> ~rtio::RtioPipe {
~FileDesc { inner: self.inner.clone() } as ~rtio::RtioPipe
fn clone(&self) -> ~rtio::RtioPipe:Send {
~FileDesc { inner: self.inner.clone() } as ~rtio::RtioPipe:Send
}
}

Expand Down
4 changes: 2 additions & 2 deletions src/libnative/io/file_win32.rs
Original file line number Diff line number Diff line change
Expand Up @@ -206,8 +206,8 @@ impl rtio::RtioPipe for FileDesc {
fn write(&mut self, buf: &[u8]) -> Result<(), IoError> {
self.inner_write(buf)
}
fn clone(&self) -> ~rtio::RtioPipe {
~FileDesc { inner: self.inner.clone() } as ~rtio::RtioPipe
fn clone(&self) -> ~rtio::RtioPipe:Send {
~FileDesc { inner: self.inner.clone() } as ~rtio::RtioPipe:Send
}
}

Expand Down
Loading

0 comments on commit 13dafa0

Please sign in to comment.