我如何创build一个全局的,可变的单身人士?
在系统中只有一个实例创build和使用结构的最好方法是什么? 是的,这是必要的,这是OpenGL的子系统,并将其多个副本,并将其传递到任何地方会增加混淆,而不是缓解它。
单身人士需要尽可能高效。 在静态区域存储一个任意的对象似乎是不可能的,因为它包含一个具有析构函数的Vec
。 第二种select是在静态区域存储一个(不安全的)指针,指向一个堆分配的单例。 在保持语法简洁的同时,做到这一点最方便和最安全的方法是什么?
没有答案的答案
总体上避免全球状况。 相反,尽早构build对象(可能是main
),然后将可变引用传递给需要它的地方。 这通常会使你的代码更容易推理,并且不需要向后弯曲。
在决定你想要全局可变variables之前,先在自己的镜子里看看自己。 有一些很有用的情况,这就是为什么它值得知道如何去做。
还想做一个…?
使用懒惰静态
懒惰静态的箱子可以拿走一些创build单身(下)的苦工。 这是一个全局可变的向量:
#[macro_use] extern crate lazy_static; use std::sync::Mutex; lazy_static! { static ref ARRAY: Mutex<Vec<u8>> = Mutex::new(vec![]); } fn do_a_call() { ARRAY.lock().unwrap().push(1); } fn main() { do_a_call(); do_a_call(); do_a_call(); println!("called {}", ARRAY.lock().unwrap().len()); }
手动执行
这从stdin
的Rust 1.0实现中被大大地削弱了 。 我已经评论了每行的内容。
use std::sync::{Arc, Mutex, Once, ONCE_INIT}; use std::time::Duration; use std::{mem, thread}; #[derive(Clone)] struct SingletonReader { // Since we will be used in many threads, we need to protect // concurrent access inner: Arc<Mutex<u8>> } fn singleton() -> SingletonReader { // Initialize it to a null value static mut SINGLETON: *const SingletonReader = 0 as *const SingletonReader; static ONCE: Once = ONCE_INIT; unsafe { ONCE.call_once(|| { // Make it let singleton = SingletonReader { inner: Arc::new(Mutex::new(0)) }; // Put it in the heap so it can outlive this call SINGLETON = mem::transmute(Box::new(singleton)); }); // Now we give out a copy of the data that is safe to use concurrently. (*SINGLETON).clone() } } fn main() { // Let's use the singleton in a few threads let threads: Vec<_> = (0..10).map(|i| { thread::spawn(move || { thread::sleep(Duration::from_millis(i * 10)); let s = singleton(); let mut data = s.inner.lock().unwrap(); *data = i as u8; }) }).collect(); // And let's check the singleton every so often for _ in 0u8..20 { thread::sleep(Duration::from_millis(5)); let s = singleton(); let data = s.inner.lock().unwrap(); println!("It is: {}", *data); } for thread in threads.into_iter() { thread.join().unwrap(); } }
这打印出来:
It is: 0 It is: 1 It is: 1 It is: 2 It is: 2 It is: 3 It is: 3 It is: 4 It is: 4 It is: 5 It is: 5 It is: 6 It is: 6 It is: 7 It is: 7 It is: 8 It is: 8 It is: 9 It is: 9 It is: 9
此代码与Rust 1.9编译,但请注意分配的内存泄漏…
真的,你可能想要使SingletonReader
实现Deref
和DerefMut
所以你不必DerefMut
对象并自己locking。