about summary refs log tree commit diff
diff options
context:
space:
mode:
authorHuon Wilson <dbau.pp+github@gmail.com>2014-03-22 18:12:22 +1100
committerHuon Wilson <dbau.pp+github@gmail.com>2014-03-26 00:25:17 +1100
commite9475b57be66a16e8a7c2b796dc60dff04f86fe9 (patch)
treee9fd5ce85335f978ca2f9961bd6aad23f2518648
parent2c7f3b850ce11c70d5bef2b2d5155a1f0fdaa421 (diff)
downloadrust-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.rs46
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