Skip to content

Commit e71c9cb

Browse files
committed
Update mutable static items example for modern Rust.
This updates the mutable static item example to fix some issues with how it works and how it is presented. First, the unsafe operations are wrapped in an `unsafe` block so that it doesn't trigger `unsafe_op_in_unsafe_fn`. Second, it switches the mutation example to use addr_of_mut to avoid the undefined behavior, and to compile correctly in 2024 edition. Third, it rewrites the second example to be safe with a different description. My understanding is that the original example was written at a time when it was considered that any potential race condition was considered unsafe. However, that is no longer a widely held view. The example has been rewritten to illustrate the two different ways you can wrap mutable static access.
1 parent b1d1060 commit e71c9cb

File tree

1 file changed

+17
-10
lines changed

1 file changed

+17
-10
lines changed

src/items/static-items.md

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -88,23 +88,30 @@ Mutable statics are still very useful, however. They can be used with C
8888
libraries and can also be bound from C libraries in an `extern` block.
8989

9090
```rust
91-
# fn atomic_add(_: &mut u32, _: u32) -> u32 { 2 }
91+
# fn atomic_add(_: *mut u32, _: u32) -> u32 { 2 }
9292

9393
static mut LEVELS: u32 = 0;
9494

9595
// This violates the idea of no shared state, and this doesn't internally
9696
// protect against races, so this function is `unsafe`
97-
unsafe fn bump_levels_unsafe1() -> u32 {
98-
let ret = LEVELS;
99-
LEVELS += 1;
100-
return ret;
97+
unsafe fn bump_levels_unsafe() -> u32 {
98+
unsafe {
99+
let ret = LEVELS;
100+
LEVELS += 1;
101+
return ret;
102+
}
101103
}
102104

103-
// Assuming that we have an atomic_add function which returns the old value,
104-
// this function is "safe" but the meaning of the return value may not be what
105-
// callers expect, so it's still marked as `unsafe`
106-
unsafe fn bump_levels_unsafe2() -> u32 {
107-
return atomic_add(&mut LEVELS, 1);
105+
// As an alternative to `bump_levels_unsafe`, this function is safe, assuming
106+
// that we have an atomic_add function which returns the old value. This
107+
// function is safe only if no other code accesses the static in a non-atomic
108+
// fashion. If such accesses are possible (such as in `bump_levels_unsafe`),
109+
// then this would need to be `unsafe` to indicate to the caller that they
110+
// must still guard against concurrent access.
111+
fn bump_levels_safe() -> u32 {
112+
unsafe {
113+
return atomic_add(std::ptr::addr_of_mut!(LEVELS), 1);
114+
}
108115
}
109116
```
110117

0 commit comments

Comments
 (0)