Boost logo

Boost :

From: Michael Glassford (glassfordm_at_[hidden])
Date: 2005-04-28 12:38:13


I've been mentioning that I have some ideas about improvements for
Boost.Threads. I intend to bring up these ideas one at a time for
discussion. I'm particularly interested in finding out:

1) Whether people think that the idea would be an improvement.
2) If so, suggestions for improving the idea even more.

The first idea has to do with the long discussion that occured some time
back about the lock class--in particular, its constructors. There were
several ideas about whether lock constructors should make the full range
of lock, try_lock, and timed_lock functionality available and, if so,
how; I don't recall any consensus being reached. I experimented for a
while with a series of template classes that would allow a user to
choose whatever interface they wanted, but another idea has occured to
me since then that I don't remember being mentioned anywhere (if I'm
wrong, my apologies to whoever mentioned it): to eliminate the locking
contructors altogether. In this scheme, a lock object would no longer be
responsible for locking a mutex, only for unlocking it. Instead, a mutex
object would lock itself and transfer ownership of the lock to a lock
object by way of a lock_transfer object.

A sample of what the classes would look like and their usage is given at
the end of this message.

Some advantages I see to this approach:

#1: it simplifies the lock class and allows it to be used to lock any
costructor, no matter what its type (it can own a lock to an exclusive
mutex, an exclusive lock to a shared_mutex, or a shared lock to a
shared_mutex).

#2: instead of the following, which in my mind leaves an ambiguity of
whether the mutex should be unlocked, shared-locked, or exclusive-locked
at the end:

    shared_lock l1(shared_mutex, SHARED_LOCK);
    ...
    {
       exclusive_lock l2 = l1.promote();
       ...
    }

It is possible to write this, which removes the ambiguity:

    lock l = shared_mutex.shared_lock();
    ...
    l = shared_mutex.promote(l.transfer());
    ...

Comments?

Mike

//------------------------------
//Exclusive mutex usage examples
//------------------------------

mutex_type m;

lock_type l;
    //Create lock object that doesn't lock anything
lock_type l = m.lock();
    //Create lock object and lock mutex m
lock_type l = m.try_lock();
    //Create lock object and conditionally lock mutex m
lock_type l = m.timed_lock(xxx);
    //Create lock object and conditionally lock mutex m

l = m.lock();
    //Lock mutex m (first unlocking whatever mutex l was previously
locking, if any)
l = m.try_lock();
    //Conditionally lock mutex m (first unlocking whatever mutex l was
previously locking, if any)
l = m.timed_lock(xxx);
    //Conditionally lock mutex m (first unlocking whatever mutex l was
previously locking, if any)

l = other_lock.transfer();
    //Transfer the lock from one lock object to another

l.unlock();
    //Unlock whatever mutex is locked (throw exception if nothing is locked)
l.is_locked();
    //Is l locking a mutex?
        
//NOT ALLOWED: l.lock(), l.try_lock(), etc.;

//------------------------------
//Shared mutex usage examples
//------------------------------

lock_type l;
    //Create unlocked lock object
lock_type l = m.lock();
    //Create lock object and lock mutex m
lock_type l = m.try_lock();
    //Create lock object and conditionally lock mutex m
lock_type l = m.timed_lock(xxx);
    //Create lock object and conditionally lock mutex m
lock_type l = m.shared_lock();
    //Create lock object and shared-lock mutex m
lock_type l = m.shared_try_lock();
    //Create lock object and conditionally shared-lock mutex m
lock_type l = m.shared_timed_lock(xxx);
    //Create lock object and conditionally shared-lock mutex m

l = m.lock();
    //Lock mutex m (first unlocking whatever mutex l was previously
locking, if any)
l = m.try_lock();
    //Conditionally lock mutex m (first unlocking whatever mutex l was
previously locking, if any)
l = m.timed_lock(xxx);
    //Conditionally lock mutex m (first unlocking whatever mutex l was
previously locking, if any)
l = m.shared_lock();
    //Shared-lock mutex m (first unlocking whatever mutex l was
previously locking, if any)
l = m.try_shared_lock();
    //Conditionally shared-lock mutex m (first unlocking whatever mutex
l was previously locking, if any)
l = m.timed_shared_lock(xxx);
    //Conditionally shared-lock mutex m (first unlocking whatever mutex
l was previously locking, if any)

lock_type l = other_lock.transfer();
l = other_lock.transfer();

l = m.promote(l.transfer());
l = m.try_promote(l.transfer());
l = m.timed_promote(l.transfer(), xxx);
l = m.demote(l.transfer());
l = m.try_demote(l.transfer());
l = m.timed_demote(l.transfer(), xxx);

l.unlock();
    //Unlock whatever mutex is locked (throw exception if nothing is locked)

l.is_locked();
    //Is l locking a mutex?
        
//NOT ALLOWED: l.lock(), l.try_lock(), etc.;

//------------------------------
//Class definitions
//------------------------------

class lock_transfer
{
public:

    //Used to return ownership of a lock from a mutex or
    //to transfer ownership of a lock from one lock object to another

    lock_transfer(...)
    {...}

    ~lock_transfer()
    {
       //unlock the mutex if ownership of the lock
       //hasn't been taken by a lock object
    }

    ...
};

class lock
{
public:

    lock(void)
    {
       //create lock object that doesn't lock any mutex
       ...
    }

    lock(lock_transfer& transfer)
    {
       //copy necessary information out of transfer
       ...
    }

    ~lock()
    {if (is_locked()) unlock();}

    lock_transfer transfer(void)
    {
       ...
    }

    void unlock(void)
    {
       //unlock the mutex
       ...
    }

    bool is_locked(void)
    {
       ...
    }
};

class mutex
{
public:

    mutex(void);
    ~mutex();

    lock_transfer lock(void); //lock the mutex and return a lock_transfer
    lock_transfer try_lock(void);
    lock_transfer timed_lock(...);

    ...
};

class shared_mutex
{
public:

    mutex(void);
    ~mutex();

    lock_transfer lock(void);
    lock_transfer try_lock(void);
    lock_transfer timed_lock(time t);

    lock_transfer shared_lock(void);
    lock_transfer try_shared_lock(void);
    lock_transfer timed_shared_lock(time t);

    lock_transfer demote(lock_transfer& exclusive_lock);
    lock_transfer try_demote(lock_transfer& exclusive_lock);
    lock_transfer timed_demote(lock_transfer& exclusive_lock, time t);

    lock_transfer promote(lock_transfer& shared_lock);
    lock_transfer try_promote(lock_transfer& shared_lock);
    lock_transfer timed_promote(lock_transfer& shared_lock, time t);

    ...
};


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