why is std::lock_guard not movable?

valoh picture valoh · Mar 19, 2014 · Viewed 7.1k times · Source

Why is std::lock_guard not movable, it would make code so much nicer:

auto locked = lock_guard(mutex);

instead of

std::lock_guard<std::mutex> locked(mutex);

Is there something wrong with creating your own version, like:

template <typename T> class lock_guard_
{
  T* Mutex_;
  lock_guard_(const lock_guard_&) = delete;
  lock_guard_& operator=(const lock_guard_&) = delete;
public:
  lock_guard_(T& mutex) : Mutex_(&mutex)
  {
    Mutex_->lock();
  }
  ~lock_guard_()
  {
    if(Mutex_!=nullptr)
      Mutex_->unlock();
  }
  lock_guard_(lock_guard_&& guard)
  {
    Mutex_ = guard.Mutex_;
    guard.Mutex_ = nullptr;
  }
};

template <typename T> lock_guard_<T> lock_guard(T& mutex)
{
  return lock_guard_<T>(mutex);
}

?

Any fundamental reason it would be a bad idea to make it movable?

Answer

ecatmur picture ecatmur · Mar 19, 2014

lock_guard is always engaged; it always holds a reference to a mutex and always unlocks it in its destructor. If it was movable then it would need to hold a pointer instead of a reference, and test the pointer in its destructor. This might seem a trivial cost, but it is C++ philosophy that you don't pay for what you don't use.

If you want a movable (and releaseable) lock you can use unique_lock.

You might be interested in n3602 Template parameter deduction for constructors, which removes the need for make_ functions. It won't be in C++14 but we can hope for C++17.