title: Assignment via copy-and-swap vs two locks
body: <p>Borrowing <a href="http://home.roadrunner.com/~hinnant/mutexes/locking.html#unique_lock_tut" rel="nofollow">Howard Hinnant's example</a> and modifying it to use copy-and-swap, is this op= thread-safe?</p>
  
  <pre><code>struct A {
    A() = default;
    A(A const &amp;x);  // Assume implements correct locking and copying.
  
    A&amp; operator=(A x) {
      std::lock_guard&lt;std::mutex&gt; lock_data (_mut);
      using std::swap;
      swap(_data, x._data);
      return *this;
    }
  
  private:
    mutable std::mutex _mut;
    std::vector&lt;double&gt; _data;
  };
  </code></pre>
  
  <p>I believe this thread-safe (remember op='s parameter is passed by value), and the only problem I can find is the one swept under the rug: the copy ctor.  However, it would be a rare class that allows copy-assignment but not copy-construction, so that problem exists equally in both alternatives.</p>
  
  <p>Given that self-assignment is so rare (at least for this example) that I don't mind an extra copy if it happens, consider the potential optimization of this != &amp;rhs to be either negligible or a pessimization.  Would there be any other reason to prefer or avoid it compared to the original strategy (below)?</p>
  
  <pre><code>A&amp; operator=(A const &amp;rhs) {
    if (this != &amp;rhs) {
      std::unique_lock&lt;std::mutex&gt; lhs_lock(    _mut, std::defer_lock);
      std::unique_lock&lt;std::mutex&gt; rhs_lock(rhs._mut, std::defer_lock);
      std::lock(lhs_lock, rhs_lock);
      _data = rhs._data;
    }
    return *this;
  }
  </code></pre>
  
  <hr>
  
  <p>Incidentally, I think this succinctly handles the copy ctor, at least for this class, even if it is a bit obtuse:</p>
  
  <pre><code>A(A const &amp;x) : _data {(std::lock_guard&lt;std::mutex&gt;(x._mut), x._data)} {}
  </code></pre>