Opened 15 years ago

Closed 10 years ago

#1850 closed Feature Requests (fixed)

request for unlock_guard (and/or unique_unlock) to compliment lock_guard/unique_lock

Reported by: bgreen0@… Owned by: viboes
Milestone: Boost 1.50.0 Component: thread
Version: Boost 1.35.0 Severity: Not Applicable
Keywords: unlock_guard release_guard Cc: bryan.d.green@…

Description

I'd like to request an unlock_guard class template to complement lock_guard. I wonder if it is any more involved than the attached patch. A unique_unlock class template may be nice as well, but an unlock_guard seems sufficient.

Is there a known reason it was left out of the proposal for the C++0x thread library, or is it a simple oversight? I don't see any reference to it in the documents.

Attachments (2)

lock.patch (697 bytes ) - added by bgreen0@… 15 years ago.
patch adding unlock_guard to boost/thread/locks.hpp
1850.patch (12.2 KB ) - added by viboes 11 years ago.

Download all attachments as: .zip

Change History (9)

by bgreen0@…, 15 years ago

Attachment: lock.patch added

patch adding unlock_guard to boost/thread/locks.hpp

comment:1 by viboes, 13 years ago

The following prototype seems not clear to me

70	        unlock_guard(Mutex& m_,adopt_lock_t): 
71	            m(m_) 
72	        {} 

For lock and unique lock adopt_lock_t parameter means adoption of the mutex was lock. For unlock_guard, adopt_lock_t will mean adoption of the mutex was unlock?

I would prefer a new structure

struct adopt_unlock_t {}
const adopt_unlock_t adopt_unlock={};
unlock_guard(Mutex& m_,adopt_unlock_t): 
 	m(m_) 
 	{} 

Maybe is just an english language question I don't master.

comment:2 by viboes, 12 years ago

Severity: ProblemNot Applicable
Type: PatchesFeature Requests

As this patch doesn't provides test and documentation I think we can downgrade it to Feature Request. Please could you provide them?

comment:3 by viboes, 11 years ago

Owner: changed from Anthony Williams to viboes
Status: newassigned

comment:4 by viboes, 11 years ago

I'm wondering if this features is not dangerous combined with other lock guards. E.g. The user of lock_guard expects his lock to be locked during his lifetime, so nesting a unlock_guard will break the user expectations. I think that as far as we unlock we are transferring ownership, so the safe way to nest the unlock guard is to use move semantics from a lock owning the mutex. What do you think of a reverse_lock

    template<typename Lock>
    class reverse_lock
    {
    private:
        Lock& m;

    public:
        reverse_lock(reverse_lock const&) = delete;
        reverse_lock& operator=(reverse_lock const&) = delete;

        typedef typename Lock::mutex_type mutex_type;
        explicit reverse_lock(Lock& m_):
            m(m_)
        {
            BOOST_ASSERT(m.owns_lock());
            m.unlock();
        }
        reverse_lock(Lock& m_,adopt_unlock_t):
            m(m_)
        {
            BOOST_ASSERT(!m.owns_lock());
        }
        ~reverse_lock()
        {
            if(!m.owns_lock())
                m.lock();
        }
        explicit operator bool() const BOOST_NOEXCEPT
        {
            return m.owns_lock(); // always false
        }
        bool owns_lock() const BOOST_NOEXCEPT
        {
            return m.owns_lock(); // always false
        }

        mutex_type* mutex() const BOOST_NOEXCEPT
        {
            return m.mutex();
        }

        mutex_type* release() BOOST_NOEXCEPT
        {
          return m.release();
        }
    };

by viboes, 11 years ago

Attachment: 1850.patch added

in reply to:  4 comment:5 by viboes, 11 years ago

Replying to viboes:

I'm wondering if this features is not dangerous combined with other lock guards. E.g. The user of lock_guard expects his lock to be locked during his lifetime, so nesting a unlock_guard will break the user expectations. I think that as far as we unlock we are transferring ownership, so the safe way to nest the unlock guard is to use move semantics from a lock owning the mutex. What do you think of a reverse_lock

    template<typename Lock>
    class reverse_lock
    {
    private:
        Lock& m;

    public:
        reverse_lock(reverse_lock const&) = delete;
        reverse_lock& operator=(reverse_lock const&) = delete;

        typedef typename Lock::mutex_type mutex_type;
        explicit reverse_lock(Lock& m_):
            m(m_)
        {
            BOOST_ASSERT(m.owns_lock());
            m.unlock();
        }
        reverse_lock(Lock& m_,adopt_unlock_t):
            m(m_)
        {
            BOOST_ASSERT(!m.owns_lock());
        }
        ~reverse_lock()
        {
            if(!m.owns_lock())
                m.lock();
        }
        explicit operator bool() const BOOST_NOEXCEPT
        {
            return m.owns_lock(); // always false
        }
        bool owns_lock() const BOOST_NOEXCEPT
        {
            return m.owns_lock(); // always false
        }

        mutex_type* mutex() const BOOST_NOEXCEPT
        {
            return m.mutex();
        }

        mutex_type* release() BOOST_NOEXCEPT
        {
          return m.release();
        }
    };

I have removed all the member operations as the goal is to ensure that the mutex is lock after destructor.

comment:6 by viboes, 11 years ago

Milestone: Boost 1.36.0Boost 1.50.0

Committed in trunk revision 77662.

comment:7 by viboes, 10 years ago

Resolution: fixed
Status: assignedclosed

Committed in release branch at [78543]

Note: See TracTickets for help on using tickets.