将外部加载的数据缓存在静态变量中

问题描述 投票:0回答:2

我想从文件加载数据,然后将此数据(包括相当大的数组)缓存在静态变量中。这显然不是首选的方法,但是:

  1. 我正在编写一个由 C(++) 程序调用的 Rust 库,并且当前没有任何超出 Rust 函数调用的对象。使用 static 可以避免我修改 C 代码。
  2. 程序内部不会同时执行任何操作,因此同步不是问题。

这如何在 Rust 中完成?

我发现 lazy-static 可以解决类似的问题,但仅限于不需要外部资源的代码(即理论上可以在编译时评估的项目)。

caching static rust ffi
2个回答
3
投票

不能在程序启动时进行初始化,但可以在第一次方法调用时进行初始化。所有进一步的调用都将访问缓存的值,而不是重新计算您的值。

由于 Rust 禁止在静态变量中使用析构函数,因此您需要自己进行清理管理。从逻辑上讲,这意味着您需要不安全的代码来破坏 Rust 的安全系统。以下示例使用

static mut
变量来缓存堆分配的对象(本例中为
i32
)。 缓存加载函数的工作方式类似于单例。

完成后记得从 c 调用cachefree()。

use std::{ptr, mem};

static mut cache: *const i32 = 0 as *const i32;

unsafe fn cacheload() -> i32 {
    if cache == ptr::null() {
        // do an expensive operation here
        cache = mem::transmute(Box::new(42));
    }
    return *cache;
}

unsafe fn cachefree() {
    if cache != ptr::null() {
        let temp: Box<i32> = mem::transmute(cache);
        cache = ptr::null();
        drop(temp);
    }
}

fn main() {
    let x;
    unsafe {
        x = cacheload();
        cachefree();
    }
    println!("{}" , x);
}

0
投票

我一直在寻找这个问题的答案。由于最好避免

unsafe
,我想出了以下方法,它也应该是线程安全的:

fn get_or_create_static_cache() -> &'static Something {
   static CACHE = RwLock<Option<&Something>> = RwLock::new(None);

   // If there is a previously cached value, return that.
   // Will potentially block while another thread is building the data.
   if let Some(s) = *CACHE.read().unwrap() {
        return s;
   }

   // Acquire write lock before constructing the data to
   // prevent any other threads from concurrently building the data too.
   let mut w = CACHE.write().unwrap();

   // Handle the improbable case that two threads simultaneously got 
   // through to acquiring the write lock.
   if let Some(s) = *w {
       return s;
   }

   let data:Something = ... // Construct the data that we want to cache.

   // Allocate it on the heap and leak into a 'static reference.
   let s = Box::new(data).leak();

   // Update the RwLock.
   *w = Some(s);

   // The write lock is automagically released on exit.
   return s;
}
© www.soinside.com 2019 - 2024. All rights reserved.