Clayton Rabenda
Clayton Rabenda

Reputation: 5219

Is it possible to create a global that is assigned once at the beginning of runtime and then borrowed across threads?

lazy_static doesn't work because I need to assign to this variable at runtime after some user interaction. thread_local doesn't work because I need to read this variable across threads.

From a system perspective, I think what I'm trying to do should be simple. At the beginning of execution I'm single threaded, I initialize some things, and then I tokio::spawn some tasks which only need to read those things.

I can get past the problem by using a mutex, but I don't really see why I should need to use a mutex when I can guarantee that no tasks will ever try to get mutable access other than at the very beginning of runtime when I'm still in a single thread. Is there a better way that using a mutex?

This is what I have so far, in case anyone is curious:

lazy_static! {
    pub static ref KEYPAIRSTORE_GLOBAL: Mutex<KeypairStore> = Mutex::new(KeypairStore::new());
}

// ...
// at top of main:
let mut keypairstore = KEYPAIRSTORE_GLOBAL.lock().unwrap();
*keypairstore = KeypairStore::new_from_password();

// somewhere later in a tokio::spawn:
let keypair_store = KEYPAIRSTORE_GLOBAL.lock().unwrap();
let keypair = keypair_store.get_keypair();
println!("{}", keypair.address());

I don't see why I need to use this mutex... I'd be happy to use unsafe during assignment, but I'd rather not have to use it every time I want to read.

Upvotes: 0

Views: 234

Answers (1)

Peter Hall
Peter Hall

Reputation: 58835

As written, you need the Mutex because you are mutating it after it is initialised. Instead, do the mutation during the initialisation:

lazy_static! {
    pub static ref KEYPAIRSTORE_GLOBAL: KeypairStore = {
        let mut keystore = KeypairStore::new_from_password();
        // ... more initialisation here...
        keystore
    }
}

// somewhere later in a tokio::spawn:
let keypair = KEYPAIRSTORE_GLOBAL.get_keypair();
println!("{}", keypair.address());

This is assuming that the signature of get_keypair is:

pub fn get_keypair(&self) -> Keypair;

Upvotes: 3

Related Questions