【问题标题】:Is there a clean way to have a global mutable state in a Rust plugin?有没有一种干净的方法可以在 Rust 插件中拥有全局可变状态?
【发布时间】:2015-09-13 23:40:18
【问题描述】:

我发现这样做的唯一方法是使用不安全的单例函数:

fn singleton() -> &'static mut HashSet<String> {
    static mut hash_map: *mut HashSet<String> = 0 as *mut HashSet<String>;

    let map: HashSet<String> = HashSet::new();
    unsafe {
        if hash_map == 0 as *mut HashSet<String> {
            hash_map = mem::transmute(Box::new(map));
        }
        &mut *hash_map
    }
}

有没有更好的方法?或许我们可以在plugin_registrar 函数中做点什么?

全局可变状态是指一个可变变量,可以被多个过程宏和/或属性使用。

更新:

我正在编写一个编译器插件来提供一个sql! 过程宏。我有一个 #[sql_table] 属性可用于结构,以便我可以获取 SQL 表的名称和列。

我需要全局可变状态来保存属性中struct的名称和字段,以便程序宏可以检查所有标识符是否存在。

【问题讨论】:

  • 你的意思是plugin for the Rust compiler,比如语法扩展?
  • 是的,我的意思是 Rust 编译器的插件。
  • 请注意,您的单例示例已损坏以进行并行访问。还有其他问题(123)可以帮助您正确创建问题。我相信(但不确定)编译器中很有可能并行访问。

标签: rust


【解决方案1】:

lazy_static! 宏有助于使全局初始化器不是静态的。 https://crates.io/crates/lazy_static/ 它的作用类似于您的 if hash_map == 0 as *mut HashSet&lt;String&gt;,但会处理数据竞争,以防多个线程同时尝试这样做。

至于可变性,为了避免更多的数据竞争,您必须以某种方式保护它,可能使用Mutex

大家一起:

#[macro_use] extern crate lazy_static;
use std::sync::Mutex;
use std::collections::HashSet;

lazy_static! {
    static ref THINGS: Mutex<HashSet<String>> = Mutex::new(HashSet::new());
}

fn usage() {
    // unwrap only fails if the lock is poisoned:
    // if another thread panicked while holding the lock.
    THINGS.lock().unwrap().insert("thing".to_owned())
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-03-08
    • 1970-01-01
    • 2020-02-26
    • 2018-06-30
    • 1970-01-01
    • 2021-10-14
    • 1970-01-01
    相关资源
    最近更新 更多