Modify

Ticket #1850 (closed Feature Requests: fixed)

Opened 6 years ago

Last modified 2 years ago

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

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

Change History

Changed 6 years ago by bgreen0@…

patch adding unlock_guard to boost/thread/locks.hpp

comment:1 Changed 4 years ago by viboes

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 Changed 3 years ago by viboes

  • Type changed from Patches to Feature Requests
  • Severity changed from Problem to Not Applicable

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 Changed 2 years ago by viboes

  • Owner changed from anthonyw to viboes
  • Status changed from new to assigned

comment:4 follow-up: ↓ 5 Changed 2 years ago by 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();
        }
    };

Changed 2 years ago by viboes

comment:5 in reply to: ↑ 4 Changed 2 years ago by viboes

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 Changed 2 years ago by viboes

  • Milestone changed from Boost 1.36.0 to Boost 1.50.0

Committed in trunk revision 77662.

comment:7 Changed 2 years ago by viboes

  • Status changed from assigned to closed
  • Resolution set to fixed

Committed in release branch at [78543]

View

Add a comment

Modify Ticket

Change Properties
<Author field>
Action
as closed
The resolution will be deleted. Next status will be 'reopened'
Author


E-mail address and user name can be saved in the Preferences.

 
Note: See TracTickets for help on using tickets.