Recherche…


Syntaxe

  • const IDENTIFIER: type = constexpr;
  • static [mut] IDENTIFICATEUR: type = expr;
  • lazy_static! {static ref IDENTIFIER: type = expr; }

Remarques

  • const valeurs const sont toujours en ligne et n'ont pas d'adresse en mémoire.
  • static valeurs static ne sont jamais intégrées et comportent une instance avec une adresse fixe.
  • static mut valeurs de static mut ne sont pas sûres pour la mémoire et ne peuvent donc être accédées que dans un bloc unsafe .
  • Parfois, l'utilisation de variables mutables statiques globales dans du code multithread peut être dangereuse, alors envisagez d'utiliser std :: sync :: Mutex ou d'autres alternatives
  • lazy_static objets lazy_static sont immuables, ne sont initialisés qu'une seule fois, sont partagés entre tous les threads et peuvent être directement accessibles (il n'y a pas de type de wrapper). En revanche, les objets thread_local sont censés être mutables, sont initialisés une fois pour chaque thread et les accès sont indirects (impliquant le type de wrapper LocalKey<T> )

Const

Le mot-clé const déclare une liaison de constante globale.

const DEADBEEF: u64 = 0xDEADBEEF;

fn main() {
    println("{:X}", DEADBEEF);
}

Cette sorties

DEADBEEF

Statique

Le mot-clé static déclare une liaison statique globale, qui peut être mutable.

static HELLO_WORLD: &'static str = "Hello, world!";

fn main() {
    println("{}", HELLO_WORLD);
}

Cette sorties

Hello, world!

lazy_static!

Utilisez la caisse lazy_static pour créer des variables immuables globales qui sont initialisées à l'exécution. Nous utilisons HashMap comme démonstration.

Dans Cargo.toml :

[dependencies]
lazy_static = "0.1.*"

En main.rs :

#[macro_use]
extern crate lazy_static;

lazy_static! {
    static ref HASHMAP: HashMap<u32, &'static str> = {
        let mut m = HashMap::new();
        m.insert(0, "hello");
        m.insert(1, ",");
        m.insert(2, " ");
        m.insert(3, "world");
        m
    };
    static ref COUNT: usize = HASHMAP.len();
}

fn main() {
    // We dereference COUNT because it's type is &usize
    println!("The map has {} entries.", *COUNT);

    // Here we don't dereference with * because of Deref coercions
    println!("The entry for `0` is \"{}\".", HASHMAP.get(&0).unwrap());
}

Thread-local Objects

Un objet thread-local est initialisé lors de sa première utilisation dans un thread. Et comme son nom l'indique, chaque thread aura une nouvelle copie indépendante des autres threads.

use std::cell::RefCell;
use std::thread;

thread_local! {
    static FOO: RefCell<f32> = RefCell::new(1.0);
}

// When this macro expands, `FOO` gets type `thread::LocalKey<RefCell<f32>>`.
//
// Side note: One of its private member is a pointer to a function which is
// responsible for returning the thread-local object. Having all its members
// `Sync` [0], `LocalKey` is also implicitly `Sync`.
//
// [0]: As of writing this, `LocalKey` just has 2 function-pointers as members

fn main() {
    FOO.with(|foo| {
        // `foo` is of type `&RefCell<f64>`
        *foo.borrow_mut() = 3.0;
    });

    thread::spawn(move|| {
        // Note that static objects do not move (`FOO` is the same everywhere),
        // but the `foo` you get inside the closure will of course be different.
        FOO.with(|foo| {
            println!("inner: {}", *foo.borrow());
        });
    }).join().unwrap();

    FOO.with(|foo| {
        println!("main: {}", *foo.borrow());
    });
}

Les sorties:

inner: 1
main: 3

Mut statique sûr avec mut_static

Les éléments globaux mutables (appelés static mut , mettant en évidence la contradiction inhérente à leur utilisation) sont dangereux car il est difficile pour le compilateur de s’assurer qu’ils sont utilisés correctement.

Cependant, l'introduction de verrous mutuellement exclusifs autour des données permet des globaux mutables sécurisés par la mémoire. Cela ne signifie pas qu'ils sont logiquement sûrs, cependant!

#[macro_use]
extern crate lazy_static;
extern crate mut_static;

use mut_static::MutStatic;

pub struct MyStruct { value: usize }

impl MyStruct {
    pub fn new(v: usize) -> Self{
        MyStruct { value: v }
    }
    pub fn getvalue(&self) -> usize { self.value }
    pub fn setvalue(&mut self, v: usize) { self.value = v }
}

lazy_static! {
    static ref MY_GLOBAL_STATE: MutStatic<MyStruct> = MutStatic::new();
}

fn main() {
    // Here, I call .set on the MutStatic to put data inside it.
    // This can fail.
    MY_GLOBAL_STATE.set(MyStruct::new(0)).unwrap();
    {
        // Using the global state immutably is easy...
        println!("Before mut: {}", 
                 MY_GLOBAL_STATE.read().unwrap().getvalue());
    }
    {
         // Using it mutably is too...
         let mut mut_handle = MY_GLOBAL_STATE.write().unwrap();
         mut_handle.setvalue(3);
         println!("Changed value to 3.");
    } 
    {
        // As long as there's a scope change we can get the 
        // immutable version again...
        println!("After mut: {}", 
                 MY_GLOBAL_STATE.read().unwrap().getvalue());
    }
    {
        // But beware! Anything can change global state!
        foo();
        println!("After foo: {}", 
                 MY_GLOBAL_STATE.read().unwrap().getvalue());
    }
 
}

// Note that foo takes no parameters
fn foo() {
    let val;
    {
        val = MY_GLOBAL_STATE.read().unwrap().getvalue();
    }
    {
        let mut mut_handle = 
            MY_GLOBAL_STATE.write().unwrap();
        mut_handle.setvalue(val + 1);
    }
}

Ce code produit la sortie:

Before mut: 0
Changed value to 3.
After mut: 3
After foo: 4

Ce n'est pas quelque chose qui devrait arriver à Rust normalement. foo() n'a pas pris de référence mutable, alors ça n'aurait pas dû faire de mutations, et pourtant il l'a fait. Cela peut rendre très difficile le débogage des erreurs de logique.

D'un autre côté, c'est parfois exactement ce que vous voulez. Par exemple, de nombreux moteurs de jeu nécessitent un cache global d’images et d’autres ressources qui est chargé paresseusement (ou utilise une autre stratégie de chargement complexe) - MutStatic est parfait pour cela.



Modified text is an extract of the original Stack Overflow Documentation
Sous licence CC BY-SA 3.0
Non affilié à Stack Overflow