[cpp-threads] Re: Thread API interface tweaks

Alexander Terekhov alexander.terekhov at gmail.com
Wed Aug 30 13:15:58 BST 2006


On 8/30/06, Howard Hinnant <hinnant at twcny.rr.com> wrote:
[...]
> template <class Mutex>
> class recursive_mutex
> {
> private:
>      Mutex& mut_;
>      unsigned count_;
>      thread_id id_;
> public:
>      explicit recursive_mutex(Mutex& mut)
>          : mut_(mut), count_(0) {}  // thread_id default constructed
> to "not a thread"
>
>      void lock()
>      {
>          thread_id self = thread_id::current();
>          if (count_ > 0 && id_ == self)

Um, you've got a data race here.

>              ++count_;
>          else
>          {
>              mut_.lock();
>              id_ = self;
>              store_release(&count_, 1);
>          }
>      }
>      ...
> };
>
> I.e. recursive_mutex<Mutex> takes any exclusive Mutex and turns it
> into a recursive mutex.  To implement this I needed the notion of
> thread id.

Not really.

key - tsd flag key
lock - mutex (non-recursive lock)
count - unsigned

init {
  tsd::init(&key);
  lock::init(&lock);
  count = 0;
}

destroy {
  lock::destroy(&lock);
  tsd::destroy(&key);
}

lock {
  if (!tsd::get(&key)) {
    tsd::set(&key, true);
    lock.acquire();  // assume throw()-nothing
    count = 1;
  }
  else {
    ++count;
  }
}

unlock {
  if (!--count ) {
    lock.release(); // throw()-nothing
    tsd::set(&key, false);
  }
}

Note that if you need "posix safety" with respect to unlock/destroy of
this lock, "tsd::set(&key, false);" shall be done before
"lock.release();" (and of course the underlying nonrecursive lock
itself shall be safe with respect to unlock/destroy).

regards,
alexander.



More information about the cpp-threads mailing list