a static can only be initialized in const context, so your MyString::new() must be a const function.
if your constructor cannot be const, then you simply cannot put it in a static variable with Mutex alone, try LazyLock instead, which initialize the variable at runtime lazily when it is first accessed.
btw, unless you are on embedded targets and uses something like critical_section::Mutext, you don't need RefCell inside a std::Mutex, since Mutex already has interior mutability functionality, so just Mutex<String> is enough.
I currently have thread local data that cashes some information for re-use.
This data can be quite large, so would be better if all the threads could share this information, when it is not being modified; i.e., if I did not need a separate copy for each thread.
I would also like to be able to go back and forth between adding to the global data and using it.
How does one normally go about this in rust ?
Is this something like a configuration that is occasionally updated? Does only one thread write the data? Can you afford the memory to have two copies exist at once when it is being re-written? If so, arc-swap might be a good solution.
But if your problem does not have those characteristics, then RwLock would likely be a reasonable choice — it is like Mutex but allows multiple simultaneous readers.
Whichever type you use for mutability, as @nerditation already wrote, you can use LazyLock to initialize static data that can't be const initialized. Or for some applications, a static RwLock<Option<MyString>> might be the right choice — you can initialize it with None.
It almost worked for my application, but I need it to be static and I need it to have a HashMap in it. The following program does not compile when you include the HashMap:
use std::sync::RwLock;
use std::collections::HashMap;
//
// static RW : RwLock< HashMap<String,usize > > = RwLock::new( HashMap::new() );
// If I uncomment the line above, I get the following error: cannot call
// non-const associated function `HashMap::<String, usize>::new` in statics
//
#[derive(Debug)]
struct MyStruct {
key : Vec<String> ,
value : Vec<usize> ,
}
impl MyStruct {
pub const fn new() -> Self {
Self {
key : Vec::new(),
value : Vec::new(),
}
}
}
static RWLOCK : RwLock< MyStruct > = RwLock::new( MyStruct::new() );
//
//
fn add_to_rwlock(key : String, value : usize)
{
// try_write
let try_write = RWLOCK.try_write();
println!( "try_write = {:?}", try_write );
if try_write.is_err() {
panic!( "attempt to write while a read or write was active" )
}
//
// try_write_unwrap
let my_struct = &mut try_write.unwrap();
my_struct.key.push(key);
my_struct.value.push(value);
}
//
fn main() {
println!( "RWLOCK = {:?}", RWLOCK );
add_to_rwlock("one".to_string(), 1);
println!( "RWLOCK = {:?}", RWLOCK );
add_to_rwlock("two".to_string(), 2);
println!( "RWLOCK = {:?}", RWLOCK );
}