|
12 | 12 | //!
|
13 | 13 | //! ## The need for synchronization
|
14 | 14 | //!
|
15 |
| -//! On an ideal single-core CPU, the timeline of events happening in a program |
16 |
| -//! is linear, consistent with the order of operations in the code. |
| 15 | +//! Conceptually, a Rust program is simply a series of operations which will |
| 16 | +//! be executed on a computer. The timeline of events happening in the program |
| 17 | +//! is consistent with the order of the operations in the code. |
17 | 18 | //!
|
18 | 19 | //! Considering the following code, operating on some global static variables:
|
19 | 20 | //!
|
|
35 | 36 | //! ```
|
36 | 37 | //!
|
37 | 38 | //! It appears _as if_ some variables stored in memory are changed, an addition
|
38 |
| -//! is performed, result is stored in A and the variable C is modified twice. |
| 39 | +//! is performed, result is stored in `A` and the variable `C` is modified twice. |
39 | 40 | //! When only a single thread is involved, the results are as expected:
|
40 | 41 | //! the line `7 4 4` gets printed.
|
41 | 42 | //!
|
42 |
| -//! As for what happens behind the scenes, when an optimizing compiler is used |
43 |
| -//! the final generated machine code might look very different from the code: |
| 43 | +//! As for what happens behind the scenes, when optimizations are enabled the |
| 44 | +//! final generated machine code might look very different from the code: |
44 | 45 | //!
|
45 |
| -//! - first store to `C` might be moved before the store to `A` or `B`, |
46 |
| -//! _as if_ we had written `C = 4; A = 3; B = 4;` |
| 46 | +//! - The first store to `C` might be moved before the store to `A` or `B`, |
| 47 | +//! _as if_ we had written `C = 4; A = 3; B = 4`. |
47 | 48 | //!
|
48 |
| -//! - assignment of `A + B` to `A` might be removed, the sum can be stored in a |
49 |
| -//! in a register until it gets printed, and the global variable never gets |
50 |
| -//! updated. |
| 49 | +//! - Assignment of `A + B` to `A` might be removed, since the sum can be stored |
| 50 | +//! in a temporary location until it gets printed, with the global variable |
| 51 | +//! never getting updated. |
51 | 52 | //!
|
52 |
| -//! - the final result could be determined just by looking at the code at compile time, |
53 |
| -//! so [constant folding] might turn the whole block into a simple `println!("7 4 4")` |
| 53 | +//! - The final result could be determined just by looking at the code at compile time, |
| 54 | +//! so [constant folding] might turn the whole block into a simple `println!("7 4 4")`. |
54 | 55 | //!
|
55 | 56 | //! The compiler is allowed to perform any combination of these optimizations, as long
|
56 | 57 | //! as the final optimized code, when executed, produces the same results as the one
|
|
77 | 78 | //! might hoist memory loads at the top of a code block, so that the CPU can
|
78 | 79 | //! start [prefetching] the values from memory.
|
79 | 80 | //!
|
80 |
| -//! In single-threaded scenarios, this can cause issues when writing signal handlers |
81 |
| -//! or certain kinds of low-level code. |
| 81 | +//! In single-threaded scenarios, this can cause issues when writing |
| 82 | +//! signal handlers or certain kinds of low-level code. |
82 | 83 | //! Use [compiler fences] to prevent this reordering.
|
83 | 84 | //!
|
84 | 85 | //! - **Single processor** executing instructions [out-of-order]: modern CPUs are
|
|
0 commit comments