我可以避免在没有`static mut`的情况下重新编译平台层吗?

时间:2019-03-20 02:45:33

标签: static rust

我有一个库“业务逻辑”板条箱,我希望能够为其编写多个二进制板条箱“前端”或“平台层”。这些平台层倾向于使用调用平台API的库,这往往意味着较长的编译时间。我希望能够在业务逻辑板条箱上进行迭代,而无需重新编译平台层。但是,我希望能够针对每个平台将项目编译为一个二进制文件,并且如果不需要的话,我不希望弄乱共享的目标文件/ DLL。

我有一种方法可以使用fn指针和static mut,但是有this rust-lang/rust issue about potentially removing it,所以我想知道是否有办法获得结果想要而不使用它。

作为参考,我的工作方式如下:

use platform_types::{Input, Output};

fn update_and_render(input: Input) -> Output {
    static mut STATE: logic::State = logic::new();
    let state: &mut logic::State = unsafe { &mut STATE };

    logic::update_and_render(state, input)
}

fn main() {
    platform_layer::run(update_and_render);
}

上述代码位于主包装箱中,logic是业务逻辑包装箱,platform_layer是平台层包装箱,platform_types包含其他三个包装箱中的通用类型

我尝试将RefCelltry_borrow_mut一起使用,但收到错误std::cell::RefCell<State> cannot be shared between threads safely,并提到Sync未实现std::cell::RefCell<State>且错误未消除如果我尝试通过实验实现State的同步功能,则无需执行。然后,我尝试了Mutex,但据我所知我不能将其放在static中。

编辑:如果有所作为,我实际上并不希望需要从多个线程中调用函数指针,尽管我知道隐式地分发可以实现这一点。如果我曾经(偶然地?)确实从多个线程中调用了函数指针,那么失败的debug_assert!或类似方法显然比UB更可取。

2 个答案:

答案 0 :(得分:2)

您可以将state移至main()

fn main() {
    let mut state = logic::new();
    platform_layer::run(move |input| logic::update_and_render(&mut state, input));
}

答案 1 :(得分:2)

您可以使用静态互斥锁,并在需要时获取本地可变引用:

#[macro_use]
extern crate lazy_static;

use std::sync::Mutex;

fn update_and_render(input: Input) -> Output {
    lazy_static! {
        static ref STATE_MUTEX: Mutex<logic::State> = Mutex::new(logic::new());
    }
    let mut state = STATE_MUTEX.lock().unwrap();
    logic::update_and_render(state, input)
}

这是快速,安全的,并且可以从多个线程进行访问。