|
Boost : |
From: Alexander Terekhov (terekhov_at_[hidden])
Date: 2004-07-19 10:23:04
Alexander Terekhov wrote:
[...]
> http://groups.google.com/groups?selm=4087a6d3%40usenet01.boi.hp.com
> (Subject: Re: pthread_mutex_delete on almost-used mutex?)
>
> ----
> [...] beware that this is a tricky area of implementation, and you are
> not entirely unlikely to run into some implementation that's done it wrong
> by referencing the mutex (e.g., to record performance or debugging
> information) "on the way out" of the lock operation.
^
|
un-------------------------------------+
With respect to swap_based_mutex_for_windows thing (without
pimpl-and-never-destroyed-impl), the problem is that it can go boom
in unlock().
void lock() throw() {
if (m_lock_status.swap(1, msync::acq))
while (m_lock_status.swap(-1, msync::acq))
m_retry_event.wait();
}
void unlock() throw() {
if (m_lock_status.swap(0, msync::rel) < 0)
m_retry_event.set();
}
Scenario...
Given: mutex protected refcounting. Two threads, A and B.
t0: thread A locks the mutex and decrements refcount to 2;
t1: thread B does m_lock_status.swap(1, msync::acq) on the
fast path and sees 1;
t2: thread A unlocks the mutex (doesn't enter slow path);
t3: thread B does mutex m_lock_status.swap(-1, msync::acq),
locks the mutex, decrements refcount to 1, does
m_lock_status.swap(0, msync::rel) and enters slow path
in unlock();
t4: thread A locks the mutex, decrements refcount to 0,
unlocks the mutex, and destroys it (including event);
t5: thread B goes BOOM.
See also:
http://lists.boost.org/MailArchives/boost/msg67104.php
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.
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk