Search code examples
c++multithreadingc++20

Is there a way to wait for a mutex (or similar object) to unlock without locking it afterwards?


In other words, is there a way to have the "reverse" of a condition variable, that will block the waiting thread until the locking thread releases the lock, but not block the waiting thread if the locking thread is not locked?

I have a main thread and a child thread that are both touching the same piece of data. For the most part, I am using std::barriers to keep these two threads in sync and make sure one thread isn't reading the data while the other is writing. There is one spot, though, where the child thread spins up a std::for_each(std::execution::par_unseq) loop that reads the data and does some heavy calculations while the main thread is off doing its own thing, not touching the data except for one spot where it may or may not write some.

I would like to be able to pause all of the reads on the threads when the main thread is writing, but I don't want each of the reads on the threads to block any of the other reads if there is no write going on.

I don't know how many threads the for_each might have spun off, so I cannot use a barrier here, and I wouldn't want to as I don't want to wait if the read isn't happening. It isn't hard to do with a busy loop, but I have been told using a busy loop in multi-threaded code is bad form, and that these std waits pause the threads and send signals on an OS level.


Solution

  • I would like to be able to pause all of the reads on the threads when the main thread is writing but I dont want each of the reads on the threads to block any of the other reads if there is no write going on.

    This is the core of the question, and it's a natural candidate for an std::shared_mutex - a mutex that can be taken in an exclusive mode (writer) or a shared mode (readers). This synchronization tool is known as a RwLock or a read-write lock in other languages and libraries.

    In fact, waiting for an unlock without actually locking is itself risky - using a condition to know that something is safe now doesn't mean it will remain safe unless you either actually hold a suitable lock, or statically ensure that it's the case through other means (e.g. by design, once the notification happens you never have a conflicting write again, and future-you/coworkers/contributors uphold that in perpetuity)