Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[guide-task] Send and Sync are not properly described #18936

Closed
Kimundi opened this issue Nov 13, 2014 · 1 comment
Closed

[guide-task] Send and Sync are not properly described #18936

Kimundi opened this issue Nov 13, 2014 · 1 comment

Comments

@Kimundi
Copy link
Member

Kimundi commented Nov 13, 2014

At the introduction of spawn:

The spawn function has a very simple type signature: fn spawn(f: proc(): Send). Because it accepts only procs, and procs contain only owned data, spawn can safely move the entire proc and all its associated state into an entirely different task for execution. Like any closure, the function passed to spawn may capture an environment that it carries across tasks.

This doesn't explain what Send means, and instead talks about a simplified concept of owning the state. Something like this would be more correct (with the old proc closures):

The spawn function has a very simple type signature: fn spawn(f: proc():Send). A proc is a closure that captures its environment by value, and the Send bound restricts it to only allow the capture of sendable types, that is data that is safe to transfer across threads. Because all captured state is sendable, the closure is as well, and spawn can safely move the entire proc and all its associated state into an entirely different task for execution.

Then later in the Arc section, Sync is not mentioned at all. A possible introduction could look like this:

To tackle this issue, one can use an Atomically Reference Counted wrapper (Arc) as implemented in the sync library of Rust. With an Arc, the data will no longer be copied for each task. Instead, a single copy of the data exists that can be accessed through an Arc handle (Arc). This handle is send- and clonable, which means you can make as many of them as necessary and then send them to different tasks.

However, for a given type T you are only allowed to construct an Arc<T> if T fulfills the Sync bound. Syncis a build-in trait the expresses that a type is thread safe to access through an shared reference, that is a T should only implement Sync if having two &T in different threads that point to the same memory is safe. For the vast majority of types that are Sync, thread safety is given by simply not allowing any mutation through an shared reference, eg u32 is Share because you can't mutate it through an &u32.

(Remaining examples of read-only Arc usage)

Rust also enable safe mutation of data that is shared between threads, by providing library types that implement Sync and do some kind of runtime checking to safely pass out mutable reference one thread at a time. One example of this is the Mutex<T> type, which can be used to make any type T thread safe to access by using locks. For example you could construct an Arc<Mutex<u32>> to have an integer that can be shared and mutated across threads.

@pythonesque
Copy link
Contributor

I think this is a topic that needs to be approached carefully, since what types are actually Sync (resp. Send) can be very hard to reason about. For example, I believe it is currently possible to write (correct) types in Rust that are Sync but not Send even when bounded by 'static, which is not obvious currently from any of the documentation I've read. Also, any complete discussion of Send must include Rc (which is neither Sync nor Send no matter what its lifetime) as well as more normal edge cases like Cell (Send but not Sync). I think these edge cases are critical to understanding the types. Some of the definitions and rules are also currently in flux (see the default / unsafe traits RFC, for example).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants