about summary refs log tree commit diff
path: root/src/libstd
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2014-03-25 10:46:57 -0700
committerbors <bors@rust-lang.org>2014-03-25 10:46:57 -0700
commitde4473201a85bf8f5522f7def903a068f8a7d12a (patch)
tree31f798c418f9880603dfc8478805c8383c356c4f /src/libstd
parent1f5571abc222520537daa00fc8256040647eec86 (diff)
parente9475b57be66a16e8a7c2b796dc60dff04f86fe9 (diff)
downloadrust-de4473201a85bf8f5522f7def903a068f8a7d12a.tar.gz
rust-de4473201a85bf8f5522f7def903a068f8a7d12a.zip
auto merge of #13070 : huonw/rust/share-doc, r=alexcrichton
std: expand the `Share` docs to make them more precise.

And give some examples about exactly what's `Share` and what's not.
Diffstat (limited to 'src/libstd')
-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