Boost logo

Boost :

From: Michael Glassford (glassfordm_at_[hidden])
Date: 2004-07-08 09:33:32


Peter Dimov wrote:

> Eric Niebler wrote:
>
>>How about:
>>
>>if( ScopedLock l = try_lock( m ) )
>>{
>>}
>
>
> You know that I very much favor declarations in conditions, but this is a
> whole new design, one that uses moveable locks. Something like:
>
> class Mutex
> {
> public:
>
> AutoLock lock();
> AutoLock try_lock();
> AutoLock timed_lock( xtime );
> };
>
> One might argue that a lock is naturally moveable...

This does need to be addressed someday, but...

> but I think that we
> should constrain ourselves to (fixing) the current noncopyable scoped_lock
> idiom.

I agree that movable locks should wait. However, what about something
like this, which doesn't require movable locks (concept only--there are
probably errors):

    //----- locker classes -----/

    template <typename Mutex>
    class unlocked
    {
    public:

       unlocked(Mutex& m)
       : m_(m) {}

       template <typename Lock>
       operator () (Lock& l) const
       {}
    };

    template <typename Mutex>
    class locked
    {
    public:

       locked(Mutex& m)
       : m_(m) {}

       template <typename Lock>
       operator () (Lock& l) const
       {l.lock();}
    };

    template <typename Mutex>
    class try_locked
    {
    public:

       try_locked(Mutex& m)
       : m_m(m) {}

       template <typename Lock>
       operator () (Lock& l) const
       {l.try_lock();}

       Mutex m_;

    private:

       bool locked_;
    };

    template <typename Mutex>
    class timed_locked
    {
    public:

       timed_locked(Mutex& m, const xtime& t)
       : m_m(m), t_(t) {}

       template <typename Lock>
       operator () (Lock& l) const
       {l.timed_lock(t);}

       Mutex m_;

    private:

       bool t_;
    };

    //----- lock classes -----/

    class lock
    {
    public:

       template <class Locker>
       try_lock(const Locker& locker)
       : m_(locker.m_)
       {locker(*this);}
    }

    class try_lock
    {
    public:

       template <class Locker>
       try_lock(const Locker& locker)
       : m_(locker.m_)
       {locker(*this);}
    }

    class timed_lock
    {
    public:

       template <class Locker>
       try_lock(const Locker& locker)
       : m_(locker.m_)
       {locker(*this);}
    }

    //----- example -----/

    mutex m;

    lock l1 = unlocked(m);
    lock l2 = locked(m);

    try_lock l3 = unlocked(m);
    try_lock l4 = locked(m);
    if (try_lock l5 = try_locked(m)) {/*...*/}

    timed_lock l6 = unlocked(m);
    timed_lock l7 = locked(m);
    if (timed_lock l8 = try_locked(m)) {/*...*/}
    if (timed_lock l9 = timed_locked(m, get_xtime()) {/*...*/}

To select whether a lock should be locked or not at runtime, you could
add constructors to the locker classes that take a bool or enum and
redefine their operator() to lock if the constructor parameter indicated
that it should.

Mike


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk