Methods for global static variables

Hi there,

I'm currently playing around with global variables just for fun. (yes I know that global variables are "evil", but I like to explore weird stuff in languages)
I managed to create a global variable, and I understand how and why it should be mutexed. Here is what I came up with: Rust Playground

I do not really like that the functions I need to access the global variable are not methods of the global variable itself. What I would like is to have something like this:

GLOBSTATE.print();
GLOBSTATE.incr();
GLOBSTATE.print();

I tried to write an impl block for Mutex<State> which does not work because it technically counts as an impl for Mutex<T> and that can only be done in the Mutex-crate itself, if I'm not mistaken. Is there any possibility to do what I want, or am I stuck with the standalone functions?

Thanks a lot for your help.

You can use a trait and implement it for Mutex<State>:

use std::sync::{Mutex, MutexGuard};

#[derive(Debug)]
struct State {
    val: u32,
}

impl State {
    const fn new() -> Self {
        State { val: 0 }
    }
}

static GLOBSTATE: Mutex<State> = Mutex::new(State::new());

trait Glob<'a> {
    fn access(&'a self) -> MutexGuard<'a, State>;
    fn print(&'a self);
    fn incr(&'a self);
}

impl<'a> Glob<'a> for Mutex<State> {
    fn access(&'a self) -> MutexGuard<'a, State> {
        self.lock().unwrap()
    }

    fn print(&'a self) {
        let state = self.access();
        println!("{:?}", state);
    }

    fn incr(&'a self) {
        let mut state = self.access();
        state.val += 1;
    }
}

fn main() {
    GLOBSTATE.print();
    GLOBSTATE.incr();
    GLOBSTATE.print();
}

Playground.

3 Likes

Thank you so much for this extremely quick reply. This looks pretty much like what I was looking for.
I have to say that I really appreciate the community. Everyone is nice and helpful.

1 Like

Note that I updated the snippet above to make the trait much more idiomatic :slightly_smiling_face:

1 Like

You can also keep the static variable private, and provide access through associated functions:

impl State {
    fn access() -> MutexGuard<'static, State> {
        static GLOBSTATE: Mutex<State> = Mutex::new(State { val:0 });
        GLOBSTATE.lock().unwrap()
    }

    pub fn print() {
        let state = Self::access();
        println!("{:?}", state);
    }

    pub fn incr() {
        let mut state = Self::access();
        state.val += 1;
    }
}

fn main() {
    State::print();
    State::incr();
    State::print();
}
3 Likes

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.