futz with headers more
This commit is contained in:
parent
7d41c950c4
commit
edb29ec53d
5 changed files with 60 additions and 32 deletions
|
|
@ -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
|
||||
|
|
|
|||
30
data.md
30
data.md
|
|
@ -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).
|
||||
|
||||
|
|
|
|||
15
intro.md
15
intro.md
|
|
@ -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
|
||||
|
|
|
|||
20
lifetimes.md
20
lifetimes.md
|
|
@ -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
|
||||
|
|
|
|||
2
raii.md
2
raii.md
|
|
@ -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…
Add table
Add a link
Reference in a new issue