I'm somewhat skeptical of the article - I think it's not entirely accurate.
This is not a good example for a global counter:
static mut DATA_RACE_COUNTER: u32 = 1;
fn main() {
print!("{}", DATA_RACE_COUNTER);
// I solemny swear that I'm up to no good, and also single threaded.
unsafe {
DATA_RACE_COUNTER = 2;
}
print!("{}", DATA_RACE_COUNTER);
}
because there are safe APIs for this: static DATA_RACE_COUNTER: AtomicU32 = AtomicU32::new(1);
fn main() {
print!("{:?}", DATA_RACE_COUNTER);
DATA_RACE_COUNTER.store(2, Ordering::Relaxed);
print!("{:?}", DATA_RACE_COUNTER);
}
Two examples are actually presented about global mutable state, and they're both unfit.Also this:
[the linked list] will at least require a Rc or Arc to work.
But even this becomes cumbersome quickly, not to mention the overhead from reference counts.
AFAIK accessing an object via RC has no overhead per se (RCs introduce overhead when they're manipulated). Even if it had, it should be verified that the overhead has a measurable performance impact (which is something that can't be generalized).The point about array initialization is fair - custom initialization requires unsafe code (or a crate) - but it must be considered that it's a performance optimization.