futz with headers more

pull/10/head
Alexis Beingessner 10 years ago committed by Manish Goregaokar
parent 65d5d6e85a
commit 8e11d0e637

@ -1,16 +1,8 @@
% Concurrency and Paralellism
```Not sure if I want this
Safe Rust features *a ton* of tooling to make concurrency and parallelism totally
safe, easy, and fearless. This is a case where we'll really just
[defer to TRPL][trpl-conc] for the basics.
TL;DR: The `Send` and `Sync` traits in conjunction with Rust's ownership model and
normal generic bounds make using concurrent APIs really easy and painless for
a user of Safe Rust.
```
## Data Races and Race Conditions
# Data Races and Race Conditions
Safe Rust guarantees an absence of data races, which are defined as:
@ -77,7 +69,10 @@ if idx.load(Ordering::SeqCst) < data.len() {
}
```
## Send and Sync
# Send and Sync
Not everything obeys inherited mutability, though. Some types allow you to multiply
alias a location in memory while mutating it. Unless these types use synchronization
@ -153,7 +148,10 @@ into the collection.
TODO: better explain what can or can't be Send or Sync. Sufficient to appeal
only to data races?
## Atomics
# Atomics
Rust pretty blatantly just inherits LLVM's model for atomics, which in turn is
largely based off of the C11 model for atomics. This is not due these models
@ -165,7 +163,10 @@ least, we can benefit from existing tooling and research around C's model.
Trying to fully explain these models is fairly hopeless, so we're just going to
drop that problem in LLVM's lap.
## Actually Doing Things Concurrently
# Actually Doing Things Concurrently
Rust as a language doesn't *really* have an opinion on how to do concurrency or
parallelism. The standard library exposes OS threads and blocking sys-calls

@ -4,7 +4,10 @@ Low-level programming cares a lot about data layout. It's a big deal. It also pe
influences the rest of the language, so we're going to start by digging into how data is
represented in Rust.
## The rust repr
# The rust repr
Rust gives you the following ways to lay out composite data:
@ -124,7 +127,7 @@ In principle enums can use fairly elaborate algorithms to cache bits throughout
with special constrained representations. As such it is *especially* desirable that we leave
enum layout unspecified today.
## Dynamically Sized Types (DSTs)
# Dynamically Sized Types (DSTs)
Rust also supports types without a statically known size. On the surface,
this is a bit nonsensical: Rust must know the size of something in order to
@ -150,6 +153,9 @@ struct Foo {
}
```
# Zero Sized Types (ZSTs)
Rust actually allows types to be specified that occupy *no* space:
@ -182,6 +188,9 @@ consequence of types with no size. In particular, pointer offsets are no-ops, an
standard allocators (including jemalloc, the one used by Rust) generally consider
passing in `0` as Undefined Behaviour.
# Drop Flags
For unfortunate legacy implementation reasons, Rust as of 1.0.0 will do a nasty trick to
@ -212,12 +221,17 @@ struct Foo {
For details as to *why* this is done, and how to make it not happen, check out
[SOME OTHER SECTION].
## Alternative representations
# Alternative representations
Rust allows you to specify alternative data layout strategies from the default Rust
one.
### repr(C)
## repr(C)
This is the most important `repr`. It has fairly simple intent: do what C does.
The order, size, and alignment of fields is exactly what you would expect from
@ -241,14 +255,18 @@ still consumes a byte of space.
* This is equivalent to repr(u32) for enums (see below)
### repr(packed)
## repr(packed)
`repr(packed)` forces rust to strip any padding it would normally apply.
This may improve the memory footprint of a type, but will have negative
side-effects from "field access is heavily penalized" to "completely breaks
everything" based on target platform.
### repr(u8), repr(u16), repr(u32), repr(u64)
## repr(u8), repr(u16), repr(u32), repr(u64)
These specify the size to make a c-like enum (one which has no values in its variants).

@ -7,7 +7,10 @@ Unsafe Rust. TURPL does not assume you have read TRPL, but does assume you know
the basics of the language and systems programming. We will not explain the
stack or heap, we will not explain the syntax.
## Sections
# Sections
* [Data Layout](data.html)
* [Ownership and Lifetimes](lifetimes.html)
@ -16,7 +19,10 @@ stack or heap, we will not explain the syntax.
* [Ownership-oriented resource management (RAII)](raii.html)
* [Concurrency](concurrency.html)
## A Tale Of Two Languages
# A Tale Of Two Languages
Rust can be thought of as two different languages: Safe Rust, and Unsafe Rust.
Any time someone opines the guarantees of Rust, they are almost surely talking about
@ -60,7 +66,10 @@ The fact that Rust is written with a healthy spoonful of Unsafe Rust is no diffe
However it *does* mean that Rust doesn't need to fall back to the pervasive unsafety of
C to do the nasty things that need to get done.
## What does `unsafe` mean?
# What does `unsafe` mean?
Rust tries to model memory safety through the `unsafe` keyword. Interestingly,
the meaning of `unsafe` largely revolves around what

@ -7,7 +7,7 @@ language-design problem.
## The Tagged Union Problem
# The Tagged Union Problem
The core of the lifetime and mutability system derives from a simple problem:
internal pointers to tagged unions. For instance, consider the following code:
@ -68,7 +68,7 @@ For more details see Dan Grossman's Existential Types for Imperative Languages:
## Lifetimes
# Lifetimes
Rust's static checks are managed by the *borrow checker* (borrowck), which tracks
mutability and outstanding loans. This analysis can in principle be done without
@ -101,7 +101,7 @@ more than a local lint against incorrect usage of a value.
## Weird Lifetimes
# Weird Lifetimes
Given the following code:
@ -150,7 +150,7 @@ a bug.
## Lifetime Elision
# Lifetime Elision
In order to make common patterns more ergonomic, Rust allows lifetimes to be
*elided* in function, impl, and type signatures.
@ -217,7 +217,7 @@ fn new<'a>(buf: &'a mut [u8]) -> BufWriter<'a> // expanded
## Unbounded Lifetimes
# Unbounded Lifetimes
Unsafe code can often end up producing references or lifetimes out of thin air.
Such lifetimes come into the world as *unbounded*. The most common source of this
@ -258,7 +258,7 @@ these are unstable due to their awkward nature and questionable utility.
## Higher-Rank Lifetimes
# Higher-Rank Lifetimes
Generics in Rust generally allow types to be instantiated with arbitrary
associated lifetimes, but this fixes the lifetimes they work with once
@ -328,7 +328,7 @@ maximally useful outside of the Fn traits.
## Subtyping and Variance
# Subtyping and Variance
Although Rust doesn't have any notion of inheritance, it *does* include subtyping.
In Rust, subtyping derives entirely from *lifetimes*. Since lifetimes are derived
@ -474,7 +474,7 @@ struct Foo<'a, 'b, A, B, C, D, E, F, G, H> {
## PhantomData
# PhantomData
When working with unsafe code, we can often end up in a situation where
types or lifetimes are logically associated with a struct, but not actually
@ -513,7 +513,7 @@ pub struct Iter<'a, T: 'a> {
## Dropck
# Dropck
When a type is going out of scope, Rust will try to Drop it. Drop executes
arbitrary code, and in fact allows us to "smuggle" arbitrary code execution
@ -557,7 +557,7 @@ standard library made a utility for itself called `Unique<T>` which:
## Splitting Lifetimes
# Splitting Lifetimes
The mutual exclusion property of mutable references can be very limiting when
working with a composite structure. Borrowck understands some basic stuff, but

@ -176,4 +176,4 @@ On balance this is an ok choice. Certainly if you're just getting started.
In the future, we expect there to be a first-class way to announce that a field
should be automatically dropped.
[uninit]:
[uninit]: uninitialized.html
Loading…
Cancel
Save