我如何在 Rust 中获得一个简单的可变线程局部结构?

How do I get a simple mutable thread-local struct in Rust?

我正在构建一个带有垃圾收集器的解释器。我想要一个线程本地托儿所区域和一个共享的旧区域。我在设置托儿所时遇到问题。我有:

const NurserySize : usize = 25000;
#[thread_local]
static mut NurseryMemory : [usize;NurserySize] = [0;NurserySize];
thread_local! {
    static Nursery: AllocableRegion = AllocableRegion::makeLocal(unsafe{&mut NurseryMemory});
}
#[cfg(test)]
mod testMemory {
    use super::*;
    #[test]
    fn test1() {
        Nursery.with(|n| n.allocObject(10));
    }
}

第一个问题是为什么我需要不安全的 - NurseryMemory 是线程本地的,所以访问不能不安全?

第二个问题是我如何实际使用它?代码位于 playground,但它无法编译,我尝试修复它似乎使它变得更糟。

1。为什么需要不安全来获取对可变 ThreadLocal 的引用?

同样的原因,你需要一个普通的可变静态不安全, 您将能够在安全代码中创建别名 mut 指针。 以下错误地创建了两个对本地可变线程的可变引用。

#![feature(thread_local)]

#[thread_local]
static mut SomeValue: Result<&str, usize> = Ok("hello world");

pub fn main() {

let first = unsafe {&mut SomeValue};
let second = unsafe {&mut SomeValue};

  if let Ok(string) = first {
    *second = Err(0); // should invalidate the string reference, but it doesn't 
    println!("{}", string) // as first and second are considered to be disjunct
  } 
  
}

first 甚至不需要成为一个可变引用,这就会成为一个问题。

2。如何修复代码?

您可以在 AllocatableRegion 周围使用 RefCell 来动态强制借用内部值。

const NurserySize : usize = 25000;
#[thread_local]
static mut NurseryMemory : [usize;NurserySize] = [0;NurserySize];

thread_local! {
    static Nursery: RefCell<AllocableRegion> = RefCell::new(AllocableRegion::makeLocal(unsafe{&mut NurseryMemory}));
}

#[cfg(test)]
mod testMemory {
    use super::*;
    #[test]
    fn test1() {
        Nursery.with(|n| n.borrow_mut().allocObject(10));
    }
}