我已经实现了一个过程宏来生成一个返回数字的方法:
extern crate unique_type_id;
#[macro_use]
extern crate unique_type_id_derive;
#[test]
fn sequential_simple() {
use unique_type_id::SequentialTypeId;
#[derive(SequentialTypeId)]
struct Test1;
#[derive(SequentialTypeId)]
struct Test2;
assert_eq!(Test1::id().0, 0u64);
assert_eq!(Test2::id().0, 1u64);
}
我有这个实现,但我不知道是否应该将静态ID
置于互斥锁之下:
fn inc_id() -> u64 {
unsafe {
static mut ID: u64 = 0u64;
let old_value = ID;
ID += 1;
old_value
}
}
fn sequential_implementor(ast: &syn::DeriveInput) -> quote::Tokens {
let name = &ast.ident;
let (impl_generics, ty_generics, where_clause) = ast.generics.split_for_impl();
let id = inc_id();
quote! {
impl #impl_generics unique_type_id::SequentialTypeId for #name #ty_generics #where_clause {
fn id() -> unique_type_id::TypeId {
unique_type_id::TypeId(#id)
}
}
}
}
如果程序宏只使用一个线程,则不需要互斥锁,但我不知道这一点。
答案 0 :(得分:3)
当你在多个文件甚至多个板条箱中使用它时会发生什么?我认为编译器不能保证任何东西,你根本就不应该使用全局状态(它可以为proc_macro
调用分叉,运行多个编译器实例,使用线程,......)。
为了使其线程安全(并避免使用unsafe
),您可以像这样使用AtomicUsize
:
fn inc_id() -> usize {
use std::sync::atomic::{AtomicUsize, Ordering, ATOMIC_USIZE_INIT};
static ID: AtomicUsize = ATOMIC_USIZE_INIT;
ID.fetch_add(1, Ordering::SeqCst)
}