2016-03-05 21 views
8

Zauważam, że struktury Rusta Atomic* mają funkcje modyfikujące wartość, takie jak fetch_add. Na przykład, mogę napisać ten program:Dlaczego typy Rusta `Atomic *` używają niemodulujących funkcji do mutowania wartości?

use std::sync::atomic::{AtomicUsize, Ordering}; 

struct Tester { 
    counter: AtomicUsize 
} 

impl Tester { 
    fn run(&self) { 
     let counter = self.counter.fetch_add(1, Ordering::Relaxed); 
     println!("Hi there, this has been run {} times", counter); 
    } 
} 

fn main() { 
    let t = Tester { counter: AtomicUsize::new(0) }; 
    t.run(); 
    t.run(); 
} 

To kompiluje i działa poprawnie, ale jeśli mogę zmienić AtomicUsize do normalnej liczby całkowitej, to będą (prawidłowo) nie skompilować ze względu na zmienność dotyczy:

struct Tester { 
    counter: u64 
} 

impl Tester { 
    fn run(&self) { 
     self.counter = self.counter + 1; 
     println!("Hi there, this has been run {} times", self.counter); 
    } 
} 
+2

Oprócz odpowiedzi Chrisa Morgana: można przeczytać o tzw. Zmienności wnętrza [w oficjalnej dokumentacji 'std' (https://doc.rust-lang.org/std/cell/index.html). "RefCell" to kolejny przykład. –

Odpowiedz

11

Nie byłoby zbyt użyteczne, gdyby nie działał w ten sposób pod. Z odwołaniami &mut, tylko jeden może istnieć w tym czasie i nie ma wtedy odniesień &, więc cała kwestia atomowości operacji byłaby dyskusyjna.

Innym sposobem patrzenia na to jest &mutunikalne referencje i &aliasable referencje. W przypadku normalnych typów mutacja może nastąpić tylko bezpiecznie, jeśli masz unikalne odniesienie, ale typy atomowe dotyczą mutacji (poprzez wymianę) bez potrzeby unikalnego odniesienia.

Nazywanie & i &mut była obarczona względu na to, z dużo FUD we wspólnocie i dokumenty jak Focusing on Ownership wyjaśniając jak rzeczy faktycznie są. Język zakończył się pobytem z & i &mut, ale &mut jest tak naprawdę o unikalności, a nie zmienności (po prostu przez większość czasu są one równoważne).

Powiązane problemy