c++ - ¿Por qué no es movible std:: lock_guard?
multithreading c++11 (2)
Tu puedes hacer:
auto&& g = std::lock_guard<std::mutex> { mutex };
Obviamente, esto no es del todo satisfactorio ya que no realiza deducciones. Su intento de una fábrica de deducción casi está ahí, excepto por el hecho de que necesita usar la inicialización de lista para devolver un objeto no móvil:
template<typename Mutex>
std::lock_guard<Mutex> lock_guard(Mutex& mutex)
{
mutex.lock();
return { mutex, std::adopt_lock };
}
que permite auto&& g = lock_guard(mutex);
.
(La incómoda danza con std::adopt_lock
se debe a que el constructor unario es explícito. Por lo tanto, no podemos return { mutex };
ya que es una conversión no permitida, mientras que return std::lock_guard<Mutex> { mutex };
realiza una lista -inicialización de un temporal - que no podemos pasar al valor de retorno.
¿Por qué no es movible std::lock_guard
, haría que el código sea mucho mejor?
auto locked = lock_guard(mutex);
en lugar de
std::lock_guard<std::mutex> locked(mutex);
¿Hay algo malo en crear tu propia versión, como:
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);
}
?
¿Alguna razón fundamental por la que sería una mala idea hacerla móvil?
lock_guard
siempre está ocupado; siempre tiene una referencia a un mutex y siempre lo desbloquea en su destructor. Si fuera móvil, entonces necesitaría mantener un puntero en lugar de una referencia y probar el puntero en su destructor. Esto puede parecer un costo trivial, pero es una filosofía de C ++ que usted no paga por lo que no usa.
Si desea un bloqueo móvil (y liberable) puede usar unique_lock
.
Es posible que esté interesado en la n3602 Deducción de parámetros de plantilla para constructores , que elimina la necesidad de funciones make_
. No estará en C ++ 14 pero podemos esperar para C ++ 17.