Search code examples
c++boostlockingboost-threadboost-mutex

How to correctly use boost::timed_mutex and scoped_lock


I am trying to use both timed_mutex with the scoped_lock. I have successfully used the scoped_lock before by following some examples but now I don't seem to find my way around neither I am able to properly understand the boost documentation.

The desired behavior is the following: try to acquire an scoped_lock for x time, if successful return true otherwise return false.

Currently I have:

boost::timed_mutex _mutex;
boost::timed_mutex::scoped_lock scoped_lock(_mutex, boost::get_system_time() + boost::posix_time::miliseconds(10));

However when I try to find (through boost documentation or examples) if this scoped_lock will return a boolean or not I find nothing or find really different ways to do it.

Therefore I ask which is the correct way to do it, how does it exactly works and maybe some indication as to how correctly "read" the documentation of boost.

UPDATE:

So

boost::timed_mutex _mutex;
boost::timed_mutex::scoped_lock scoped_lock(_mutex, boost::get_system_time() + boost::posix_time::miliseconds(10));

if(scoped_lock.owns_lock()) {
    // exclusive code 
}

Will create a mutex which when I try to lock with scoped_lock.owns_lock() will try to acquire the lock during 10 miliseconds (in this case) and return false if the time's up and the lock wasn't acquired?


Solution

  • If you look at the documentation, boost::timed_mutex::scoped_lock is just an alias for boost::unique_lock<timed_mutex>:

    class timed_mutex:
        boost::noncopyable
    {
    public:
        // ...
    
        typedef unique_lock<timed_mutex> scoped_timed_lock;
        typedef unspecified-type scoped_try_lock;
        typedef scoped_timed_lock scoped_lock;
    
        // ...
    };
    

    Now checking out the documentation for boost::unique_lock, it shows that there are two ways to determine if you own the lock:

    template<typename Lockable>
    class unique_lock
    {
    public:
        // ...
    
        explicit operator bool() const noexcept;
        bool owns_lock() const noexcept;
    
        // ...
    };
    

    Therefore, you can do either

    if(scoped_lock) {
        // we have the lock, yay!
    }
    

    or

    if(scoped_lock.owns_lock()) {
        // we have the lock, yay!
    }
    

    Incidentally, unique_lock has a constructor that takes relative time as a chrono::duration, which may or may not be cleaner than using absolute time.

    Edit: Given this code:

    boost::timed_mutex _mutex;
    boost::timed_mutex::scoped_lock scoped_lock(_mutex,
               boost::get_system_time() + boost::posix_time::miliseconds(10)); // <-- attempt to acquire mutex happens here!
    
    if(scoped_lock.owns_lock()) {
        // exclusive code 
    }
    

    The attempt to acquire the mutex happens at the time the lock is constructed, not at the time owns_lock() is called. Yes, the exclusive code will only execute if you successfully acquired the mutex. I'm not sure what you mean by "return false" - this code doesn't return anything. If owns_lock() returns false, then you have failed to acquire the mutex and can't run the exclusive code, and you can communicate this to your caller anyway you want.