diff options
| author | Huon Wilson <dbau.pp+github@gmail.com> | 2014-03-22 18:12:22 +1100 |
|---|---|---|
| committer | Huon Wilson <dbau.pp+github@gmail.com> | 2014-03-26 00:25:17 +1100 |
| commit | e9475b57be66a16e8a7c2b796dc60dff04f86fe9 (patch) | |
| tree | e9fd5ce85335f978ca2f9961bd6aad23f2518648 | |
| parent | 2c7f3b850ce11c70d5bef2b2d5155a1f0fdaa421 (diff) | |
| download | rust-e9475b57be66a16e8a7c2b796dc60dff04f86fe9.tar.gz rust-e9475b57be66a16e8a7c2b796dc60dff04f86fe9.zip | |
std: expand the `Share` docs to make them more precise.
And give some examples about exactly what's `Share` and what's not.
| -rw-r--r-- | src/libstd/kinds.rs | 46 |
1 files changed, 45 insertions, 1 deletions
diff --git a/src/libstd/kinds.rs b/src/libstd/kinds.rs index 2ce41a33c29..f116f61509e 100644 --- a/src/libstd/kinds.rs +++ b/src/libstd/kinds.rs @@ -40,7 +40,51 @@ pub trait Pod { // Empty. } -/// Types that can be safely shared between threads, hence thread-safe. +/// Types that can be safely shared between tasks when aliased. +/// +/// The precise definition is: a type `T` is `Share` if `&T` is +/// thread-safe. In other words, there is no possibility of data races +/// when passing `&T` references between tasks. +/// +/// As one would expect, primitive types like `u8` and `f64` are all +/// `Share`, and so are simple aggregate types containing them (like +/// tuples, structs and enums). More instances of basic `Share` types +/// include "immutable" types like `&T` and those with simple +/// inherited mutability, such as `~T`, `Vec<T>` and most other +/// collection types. (Generic parameters need to be `Share` for their +/// container to be `Share`.) +/// +/// A somewhat surprising consequence of the definition is `&mut T` is +/// `Share` (if `T` is `Share`) even though it seems that it might +/// provide unsynchronised mutation. The trick is a mutable reference +/// stored in an aliasable reference (that is, `& &mut T`) becomes +/// read-only, as if it were a `& &T`, hence there is no risk of a data +/// race. +/// +/// Types that are not `Share` are those that have "interior +/// mutability" in a non-thread-safe way, such as `Cell` and `RefCell` +/// in `std::cell`. These types allow for mutation of their contents +/// even when in an immutable, aliasable slot, e.g. the contents of +/// `&Cell<T>` can be `.set`, and do not ensure data races are +/// impossible, hence they cannot be `Share`. A higher level example +/// of a non-`Share` type is the reference counted pointer +/// `std::rc::Rc`, because any reference `&Rc<T>` can clone a new +/// reference, which modifies the reference counts in a non-atomic +/// way. +/// +/// For cases when one does need thread-safe interior mutability, +/// types like the atomics in `std::sync` and `Mutex` & `RWLock` in +/// the `sync` crate do ensure that any mutation cannot cause data +/// races. Hence these types are `Share`. +/// +/// Users writing their own types with interior mutability (or anything +/// else that is not thread-safe) should use the `NoShare` marker type +/// (from `std::kinds::marker`) to ensure that the compiler doesn't +/// consider the user-defined type to be `Share`. Any types with +/// interior mutability must also use the `std::ty::Unsafe` wrapper +/// around the value(s) which can be mutated when behind a `&` +/// reference; not doing this is undefined behaviour (for example, +/// `transmute`-ing from `&T` to `&mut T` is illegal). #[lang="share"] pub trait Share { // Empty |
