<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On Sat, Aug 30, 2014 at 9:53 PM, Ed Schouten <span dir="ltr"><<a href="mailto:ed@80386.nl" target="_blank">ed@80386.nl</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
Hi DeLesley,<br>
<br>
First of all, thanks for your work on the thread annotations for<br>
Clang! Impressed by how well they work, I decided to patch up<br>
FreeBSD's pthread library to use these annotations by default.<br>
<br>
<a href="http://lists.freebsd.org/pipermail/freebsd-toolchain/2014-August/001183.html" target="_blank">http://lists.freebsd.org/pipermail/freebsd-toolchain/2014-August/001183.html</a><br>
<br>
While experimenting with using these annotations in a C++ codebase, I<br>
discovered that it's currently not possible to use these for<br>
interlocking, as scoped_lockable does not support acquiring multiple<br>
mutexes. Example:<br>
<br>
class SCOPED_LOCKABLE DoubleGuard {<br>
DoubleGuard(Mutex* m1, Mutex* m2) EXCLUSIVE_LOCK_FUNCTION(m1, m2) {<br>
if (m1 == m2) {<br>
m1_ = m1;<br>
m2_ = nullptr;<br>
m1_->Lock();<br>
} else {<br>
if (m1 < m2) {<br>
m1_ = m1;<br>
m2_ = m2;<br>
} else {<br>
m1_ = m2;<br>
m2_ = m1;<br>
}<br>
m1_->Lock();<br>
m2_->Lock();<br>
}<br>
}<br>
<br>
~DoubleGuard() UNLOCK_FUNCTION() {<br>
m1_->Unlock();<br>
if (m2_ != nullptr)<br>
m2_->Unlock();<br>
}<br>
<br>
private:<br>
Mutex* m1_;<br>
Mutex* m2_;<br>
};<br>
<br>
This class cannot be used, as it will cause a warning that the guard<br>
object itself is locked twice. Attached is a patch to fix this. It<br>
changes the lock path to always create exactly one FactEntry for<br>
scoped lockables. Instead of having a single UnderlyingMutex, it now<br>
uses a CapExprSet.<br>
<br>
What are your thoughts on this change? Is it all right for me to commit this?</blockquote><div><br></div><div>Does this handle the variadic template case:</div><div><br></div><div>class SCOPED_LOCKABLE MultiGuard {</div>
<div>public:</div><div> template<typename ...T> MultiGuard(T *...mutexes) EXCLUSIVE_LOCK_FUNCTION(mutexes...)</div><div> : m{mutexes...} {</div><div> std::sort(m.begin(), m.end());</div><div> for (Mutex *mut : m) mut->Lock();</div>
<div> }</div><div> ~MutexGuard() UNLOCK_FUNCTION() {</div><div> std::reverse(m.begin(), m.end());</div><div> for (Mutex *mut : m) : mut->Unlock();</div><div> }</div><div>private:</div><div> std::vector<Mutex*> m;</div>
<div>};</div></div></div></div>