-3

I am trying to create a mutable static variable in Rust.

Note that this question is different to this:

In this case I am attempting to solve the problem without the use of other libraries, such as lazy static.

I succeeded in doing such a thing, but the compiler complained at the final step because what I had written was not thread-safe.

Since I am only working with a single thread, this is ok, but requires the use of unsafe Rust.

Rather than give in and use unsafe I wanted to resolve this properly with a Mutex.

However I have not attempted any multithread Rust code before, and so unsurprisingly my attempt did not work.

My attempt does not work because I am attempting to return a reference to some local variable, which does not exist after the function returns.

I am also not that familiar with lifetime parameters, having not had to use them before, either.

But I don't know how to proceed from here.

Here's what I have so far.

struct Object {
    
    field: i64
}

struct GlobalStruct {
    
}

impl GlobalStruct {
    
    fn get() -> &'static mut Object {
        
        static object_mutex: std::sync::Mutex<Option<Object>> = std::sync::Mutex::new(None);
        
        let maybe_locked_mutex = object_mutex.lock();
        
        match maybe_locked_mutex {
            
            Ok(mut locked_mutex) => {
                
                let &mut object = locked_mutex.as_mut().unwrap();
                &mut object
            }
            
            Err(exception) => {
                panic!("help");
            }
        }
        
    }
}

fn main() {
    
    let object = GlobalStruct::get();
}
FreelanceConsultant
  • 13,167
  • 27
  • 115
  • 225
  • @cafce25 None of the answers provide a solution using Mutex. Why is this important? Those coming from a C++ background would likely write code very similar to the above. It is broadly speaking, a standard way of doing it - although clearly my Rust syntax is not quite right. – FreelanceConsultant Aug 04 '23 at 19:02
  • @cafce25 Sure, in which case that's part of a legitimate question. This doesn't seem to be working in this case - what should I do about it? – FreelanceConsultant Aug 04 '23 at 19:07
  • @cafce25 There is no relevant solution there. – FreelanceConsultant Aug 04 '23 at 19:07
  • 1
    I did read your question. The first answer on the duplicate does use `Mutex`, in multiple ways. You added the requirement that you can't use the lazy_static crate after I closed the question. While I generally think this kind of requirement changes the question to a programming puzzle rather than a practical problem, it's easy to avoid lazy_static in this case. I'll eddit the answer on the duplicate. – Sven Marnach Aug 04 '23 at 19:17
  • 2
    On a side note, I'd ask you to refrain from antagonistic comments like your first one. It's just a lot more fun to help if people are nice. – Sven Marnach Aug 04 '23 at 19:18
  • 1
    I just realized that there is no need to edit the answers on the duplicate. The [second answer](https://stackoverflow.com/a/73014979) is already exactly what I was going to say, and it's an answer to your question. – Sven Marnach Aug 04 '23 at 19:22
  • I agree with the last comment of @SvenMarnach. This answer is exactly what you should do, with a Mutex and everything. Please actually read and try to understand the proposed duplicates before complaining. The `fn get() -> &'static mut Object` syntax is sadly impossible - it would allow users to get multiple mutable references simultaneously, bypassing the Mutex entirely. This is called [aliasing](https://doc.rust-lang.org/beta/nomicon/aliasing.html) and will always be prevented by the compiler. – Finomnis Aug 05 '23 at 09:04
  • Although the closest thing to your existing code would be `fn get() -> &'static Mutex`, as described in the proposed duplicate, using a [`OnceLock`](https://doc.rust-lang.org/stable/std/sync/struct.OnceLock.html) instead of a local static variable. – Finomnis Aug 05 '23 at 09:12
  • In case you are having trouble understanding the duplicate, here is how your code would look like with `OnceLock` and no external library: https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=121c998e5f47b00496fa63e7e39fd4bc – Finomnis Aug 05 '23 at 09:21
  • @FreelanceConsultant Maybe even closer to your original code would be `fn get() -> MutexGuard<'static, Object>`: https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=8630740e7dbb7199e25c010e2f5ae01a – Finomnis Aug 05 '23 at 09:55
  • Although in your case, one doesn't even need a `OnceLock` for that: https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=1cba5b9cd5a8747df3930b09c6ee2e5f – Finomnis Aug 05 '23 at 10:05
  • @SvenMarnach It was not antagonistic. The question was closed literally within a few seconds of being posted. It was quite clear you did not read it, assumed it was a duplicate and closed it without further consideration. It was totally inconsiderate for you to have done this. I should have perhaps added that question as a link explicitly, because I also happened to have read it since it comes up as the first result from fairly obvious searches. – FreelanceConsultant Aug 06 '23 at 09:37
  • @SvenMarnach Onto your point about the second answer on that question. I tried to implement that - as evidenced above - and failed. I do not understand why I failed. This is the whole point of asking a question. – FreelanceConsultant Aug 06 '23 at 09:39
  • 1
    @FreelanceConsultant I closed the question [more than ten minutes after you askd it](https://stackoverflow.com/posts/76838440/timeline), and I did read it carefully before that. I always do. I sometimes get it wrong anyway, but I'm trying to help. – Sven Marnach Aug 06 '23 at 10:22
  • @SvenMarnach In that case I misunderstood. There was a close vote almost immediatly after it was posted – FreelanceConsultant Aug 06 '23 at 13:19

0 Answers0