<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>