Boost logo

Boost :

From: Howard Hinnant (hinnant_at_[hidden])
Date: 2006-11-02 09:28:41


On Nov 2, 2006, at 3:23 AM, Anthony Williams wrote:

>> Agreed.
>> So we would end up with mutex and recursive_mutex, yes?
>
> Yes, though I like Howard's idea of recursive_mutex being an
> adaptor, with
> specializations for optimization.

Btw, recursive_mutex adaptor, if it is a good idea in the first
place, is a good example of an application needing to lock a mutex in
a non-scoped manner.

Ion pointed out to me that recursive_mutex shouldn't hold a mutex&,
but rather a mutex. It can then be constructed in place with
perfectly forwarding variadic templates:

template <class Mutex>
class recursive_mutex
{
private:
     Mutex mut_;
     unsigned count_;
     thread_util::id id_;
public:
     template <class ...T>
     explicit recursive_mutex(T&& t...)
         : mut_(std::forward<T>(t)...), count_(0), id_
(thread_self::not_any_thread()) {}

I probably messed up the variadic template syntax. But this way you
don't have to have an external mutex sitting out somewhere, but if
you want that you can use recurisive_mutex<mutex&> (which could also
be specialized as a straight drop through if need be). This is of
course somewhat emulate-able in C++03 (like bind does).

I should also stress: recursive_mutex is an experiment, not a
proposed solution. I'm just thinking out loud, and would like more
help in the thinking department. :-)

> I was thinking about mutex,
> try_mutex and timed_mutex, which I think can really be one and the
> same
> class.

I've also been experimenting with a timed_mutex adaptor:

<experimental>

struct event
{
     mutex mut_;
     condition<mutex> cond_;
};

template <class Mutex>
class timed_mutex
{
private:
     Mutex mut_;
     event sig_;
     timespec abs_time_;

     timed_mutex(const timed_mutex&);
     timed_mutex& operator=(const timed_mutex&);
public:
     template <class ...T>
     timed_mutex(T&& t..., const timespec& abs_time)
         : mut_(std::forward<T>(t)...), abs_time_(abs_time)) {}

      void lock()
     {
         mut_.lock();
     }

     bool try_lock()
     {
         exclusive_lock<mutex> lk(sig_.mut_);
         bool timed_out;
         bool owns;
         do
         {
             owns = mut_.try_lock();
             if (owns)
                 break;
             timed_out = !sig_.cond_.timed_wait(sig_.mut_, abs_time_);
         } while (!timed_out);
         return owns;
     }

     void unlock()
     {
         mut_.unlock();
         sig_.cond_.notify_all();
     }
};

</experimental>

This is even less mature than the recursive_mutex. But hopefully
people can see where I'm trying to go: Instead of having recursive
and timed flavors of every kind of mutex (exclusive, sharable,
upgradable), one might instead have adaptors that one could apply to
these, and perhaps to user-defined mutexes as well (more motivation
for mutex concepts: here's more generic mutex code people could plug
into).

-Howard


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