c++boostshared-memoryinterprocess

Using boost::interprocess condition variable on an already locked mutex


I want to use boost::interprocess condition variable on an already locked mutex. I have locked the mutex already using mutex->lock(); function and because of this scoped_lock is not really appropriate for me. Is there any API available in boost::interprocess to wait on a condition variable without using scoped_lock? I am looking for an API that looks similar to below:

condition_variable.wait(mutex)

In the above code block, the mutex is already locked so there is no need for the scoped_lock. However, the above code block doesn't work because boost expects a lock instead of mutex as the first argument to `wait. I could do the same in the pthread using the function call below:

pthread_cond_wait(condition_variable, mutex)

Solution

  • You need a BasicLockable. Indeed scoped_lock (or lock_guard) are not that. unique_lock and similar are:

    The class unique_lock meets the BasicLockable requirements. If Mutex meets the Lockable requirements, unique_lock also meets the Lockable requirements (ex.: can be used in std::lock); if Mutex meets the TimedLockable requirements, unique_lock also meets the TimedLockable requirements.

    Here's a small demo assuming some types for your interprocess mutex and condition:

    Coliru

    #include <boost/date_time/posix_time/posix_time.hpp>
    #include <boost/interprocess/managed_mapped_file.hpp>
    #include <boost/interprocess/sync/interprocess_condition.hpp>
    #include <boost/interprocess/sync/interprocess_mutex.hpp>
    #include <mutex>
    #include <thread>
    namespace bip = boost::interprocess;
    using namespace std::literals;
    
    using boost::posix_time::milliseconds;
    auto now = boost::posix_time::microsec_clock::universal_time;
    
    int main() {
        bip::managed_mapped_file mmf(bip::open_or_create, "mapped.dat", 32<<10);
    
        auto& mutex = *mmf.find_or_construct<bip::interprocess_mutex>("mutex")();
        auto& cond  = *mmf.find_or_construct<bip::interprocess_condition>("cond")();
        auto& data  = *mmf.find_or_construct<int>("data")(0);
    
        auto is_ready = [&data] { return data != 42; };
    
        std::unique_lock lk(mutex);
    
        /*void*/ cond.wait(lk);
    
        /*void*/ cond.wait(lk, is_ready);
    
        // check return values for these:
        cond.timed_wait(lk, now() + milliseconds(120));
        cond.timed_wait(lk, now() + milliseconds(120), is_ready);
    }
    

    (Of course that would just block forever because nothing ever notifies the condition).

    Added a running demo with a very quick-and-dirty signaller thread: http://coliru.stacked-crooked.com/a/a1eb29653f1bbcee

    Without Standard Library

    You can use the equivalent Boost types: https://www.boost.org/doc/libs/1_76_0/doc/html/thread/synchronization.html#thread.synchronization.locks