|
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