0

I have a mutable global state used in my application instance, it is created during runtime; then I need to access the global state in another static struct (it's required to be static so I can't pass params from top down), which just needs an immutable global state reference. The global state doesn't implement Copy or Clone.

I was trying to create a global reference:

struct GlobalState;
struct Application;

static mut GLOB: Option<&GlobalState> = None;

// also use atomic bool to track, of course; for simplicity here
fn set_glob_singleton(glob: &'static GlobalState) {
    unsafe {
        GLOB = Some(glob);
    }
}

impl GlobalState {
    fn new() -> Self { Self }
}
impl Application {
  pub fn run(&mut self) {
    // set singleton?
    // the actual global state init requires runtime data
    let glob = GlobalState::new();
    // ...
    let g_singleton = Box::new(glob); // borrowed
    set_glob_singleton(Box::leak(g_singleton));

    // I need to use glob down there.
  }
}

The problem is if I create a static reference, it borrows the glob but I need to access and update it down that line.

knh190
  • 2,744
  • 1
  • 16
  • 30
  • Why a reference instead of a `GlobalState` directly? – kmdreko Apr 15 '21 at 03:20
  • Typically this is done with `lazy_static` and a `Mutex`: [How do I create a global, mutable singleton?](https://stackoverflow.com/questions/27791532/how-do-i-create-a-global-mutable-singleton) – kmdreko Apr 15 '21 at 03:21
  • @kmdreko lazy_static creates the state without dependency, but in my case glob needs to know some information from runtime. – knh190 Apr 15 '21 at 03:22
  • 1
    Right, but that's what the `Option` is for, no? Does [this](https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=51c1d70ffbd9897e4d8ef476dd1bdc59) not work? – kmdreko Apr 15 '21 at 03:24
  • @kmdreko that'll work! My initial attempt was to prevent global mutable access to the state, thus a global reference would be good. – knh190 Apr 15 '21 at 03:27
  • If you want to enforce that its only set *once* and afterwards is un-modifyable, I'd instead recommend `once_cell`. See it [here](https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=54bfab74a5adba553f9966c18d3155d2) – kmdreko Apr 15 '21 at 03:34
  • @kmdreko Mutex holding an `Option` still has some problem: it doesn't allow moving `Option` out of mutex guard, so indeed I can mutate the mutex, but not the data inside (which is updated in application update cycle). – knh190 Apr 15 '21 at 03:47
  • 1
    huh? `Mutex` gives you a mutable reference to the contents, you can either [`.take()`](https://doc.rust-lang.org/std/option/enum.Option.html#method.take) the contents out of the `Option`, or use [`.as_mut()`](https://doc.rust-lang.org/std/option/enum.Option.html#method.as_mut) to modify it in-place. – kmdreko Apr 15 '21 at 03:52

0 Answers0