Boost logo

Boost :

From: Yuval Ronen (ronen_yuval_at_[hidden])
Date: 2007-03-22 15:20:43


Howard Hinnant wrote:
> On Mar 22, 2007, at 1:14 PM, Yuval Ronen wrote:
>
>>> The usual
>>> idiom is to have the mutex at namespace scope, or as a class data
>>> member, and have the lock referring to that mutex "on the stack". So
>>> for the usual idioms, non-copyable, non-movable mutexes do not seem
>>> overly problematic.
>> I'm not sure it's not problematic. If the mutex is class data member
>> (a
>> very common scenario - perhaps the most common one), then it makes
>> that
>> class non-movable. Non-copyable - I understand, but non-movable -
>> that's
>> a major limitation, IMO.
>
> I think we're ok here, both for copying and moving. Here's a
> prototype class A which owns an int on the heap. And because I think
> this is a cool use of the read/write locks from N2094 I'm going to use
> them to implement the copy assignment. :-)
>
> I'm typing this code in untested, so please forgive me any careless
> mistakes.
>
> class A
> {
> int* the_data_;
> std::sharable_mutex mut_;
>
> typedef std::sharable_lock<std::sharable_mutex> read_lock;
> typedef std::exclusive_lock<std::sharable_mutex> write_lock;
> public:
> explicit A(int data) : the_data_(new int(data)) {}
> ~A() {delete the_data_;}
>
> // copy semantics
> A(const A& a) : the_data_(0)
> {
> read_lock lk(a.mut_);
> if (a.the_data_ != 0)
> the_data_ = new int(*a.the_data_);
> }
> A& operator=(const A& a)
> {
> if (this != &a)
> {
> read_lock lock_a(a.mut_, std::defer_lock);
> write_lock lock_this(mut_, std::defer_lock);
> std::lock(lock_this, lock_a); // prevents deadlock
> int* new_data = a.the_data_ ? new int(*a.the_data_) :
> (int*)0;
> delete the_data_;
> the_data_ = new_data;
> }
> return *this;
> }
>
> // move semantics
> A(A&& a) : the_data_(a.the_data_)
> {
> a.the_data_ = 0; // no locking required, a is an rvalue! :-)
> }
> A& operator=(A&& a)
> {
> write_lock lock_this(mut_);
> delete the_data_;
> the_data_ = a.the_data_;
> a.the_data_ = 0;
> return *this;
> }
> };
>
> I.e. you just move or copy the protected data and not the mutex.

The main thing I was thinking about is the move constructor. Instead of
stealing the mutex from the rvalue, you construct a new mutex, and let
the old one be destructed. This might be not optimal. But on the other
hand, it might not be that bad after all, I don't know...


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