1

I'm writing a function that needs to use mutable static variables to work (a weird implementation of a message loop). In order to allow only one writer to access those variables at any given time, I need to make the access to this function exclusive (to the first thread that accesses it).

Using AtomicBool

My first guess was to use an AtomicBool:

use std::sync::atomic::{Ordering, AtomicBool};

static FLAG: AtomicBool = AtomicBool::new(false);

fn my_exclusive_function() {
    if FLAG.load(Ordering::SeqCst) {
        panic!("Haha, too late!")
    }
    
    FLAG.store(true, Ordering::SeqCst);

    /* Do stuff */
}

This code has an obvious flaw: if two threads happen to read FLAG at the same time, they would both think that this is ok for them to continue.

Using Mutex<()>

Then I thought about using a Mutex<()> for its lock.

use std::sync::Mutex;

static FLAG: Mutex<()> = Mutex::new(());

fn my_exclusive_function() {
    let _lock = FLAG.try_lock() {
        Ok(lock) => lock,
        Err(_) => panic!("Haha, too late!"),
    };

    /* Do stuff */

    // `_lock` gets dropped here, another thread can now access the function
}

There are two problems here:

  1. Mutex::new is not a const function which makes me unable to initialize the Mutex. I could use a library like lazy_static here but if I can avoid an additional dependency, it would be great.
  2. Even if I use lazy_static, a user-defined function (the handler inside of the message loop actually) could panic and poison the mutex. Here again, I could use a thread-party library like parking_lot but that would be yet anther additional dependency.

I'm willing to use those if there is no alternatives but if I can avoid it, that is better.

What would the right way to do this look like? Is it just a matter of Ordering?

Related question that did not help me

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
Gymore
  • 585
  • 2
  • 10
  • [`compare_exchange`](https://doc.rust-lang.org/std/sync/atomic/struct.AtomicBool.html#method.compare_exchange) / [`compare_and_swap`](https://doc.rust-lang.org/std/sync/atomic/struct.AtomicBool.html#method.compare_and_swap) – Shepmaster Jan 06 '21 at 16:15
  • @Shepmaster Seems like magic to me x) What about the ordering? Is `Ordering::Relaxed` sufficient for this case? I'm fairly new to async programming. – Gymore Jan 06 '21 at 16:20
  • (a) That's not async programming. (b) understanding the ordering has always eluded me. I use `SeqCst` so I don't have to think. The bookmark I have is [Atomic operations, std::atomic<> and ordering of writes](https://stackoverflow.com/q/32384901/155423) – Shepmaster Jan 06 '21 at 16:21

0 Answers0