std::scoped_lock
Definido en el archivo de encabezado <mutex>
|
||
template< class... MutexTypes > class scoped_lock; |
(desde C++17) | |
La clase scoped_lock
es una envoltura de mutex que proporciona un mecanismo conveniente estilo RAII para poseer uno o más mutexes durante la duración del ámbito de un bloque.
Cuando se crea un objeto scoped_lock
, intenta tomar posesión de los mutexes que se le asignan. Cuando el control abandona el ámbito en el que se creó el objeto scoped_lock
, el scoped_lock
se destruye y los mutexes se liberan, en orden inverso. Si se dan varios mutexes, el algoritmo de evitación de interbloqueo se usa como si lo hiciera std::lock.
La clase scoped_lock
no se puede copiar.
Contenido |
[editar] Parámetros de plantilla
MutexTypes | - | Los tipos de los mutexes a bloquear. Los tipos deben cumplir con los requerimientos de Lockable a menos que sizeof...(MutexTypes)==1, en cuyo caso el tipo único debe cumplir con los requerimientos de BasicLockable |
[editar] Tipos miembro
Tipo miembro | Definición |
mutex_type (if sizeof...(MutexTypes)==1 )
|
Mutex, el único tipo en MutexTypes...
|
[editar] Funciones miembro
Construye un objeto scoped_lock , opcionalmente bloqueando los mutexes dados (función miembro pública) | |
Destruye el objeto scoped_lock object , desbloquea los mutexes subyacentes (función miembro pública) | |
operator= [eliminada] |
No es asignable por copia (función miembro pública) |
[editar] Ejemplo
El siguiente ejemplo utiliza std::scoped_lock
para bloquear pares de mutexes sin bloqueo mutuo y es estilo RAII.
#include <mutex> #include <thread> #include <iostream> #include <vector> #include <functional> #include <chrono> #include <string> struct Employee { Employee(std::string id) : id(id) {} std::string id; std::vector<std::string> lunch_partners; std::mutex m; std::string output() const { std::string ret = "Empleado " + id + " tiene compañeros de almuerzo: "; for( const auto& partner : lunch_partners ) ret += partner + " "; return ret; } }; void send_mail(Employee &, Employee &) { // simular una operación de mensajeo que consume tiempo std::this_thread::sleep_for(std::chrono::seconds(1)); } void assign_lunch_partner(Employee &e1, Employee &e2) { static std::mutex io_mutex; { std::lock_guard<std::mutex> lk(io_mutex); std::cout << e1.id << " y " << e2.id << " a la espera de cerrojos" << std::endl; } { // usar std::scoped_lock para adquirir dos cerrojos sin preocuparse deabout // otras llamadas a assign_lunch_partner interbloquándonos // y también proporciona un mecanismo estilo RAII conveniente std::scoped_lock lock(e1.m, e2.m); // Código equivalente 1 (usando std::lock y std::lock_guard) // std::lock(e1.m, e2.m); // std::lock_guard<std::mutex> lk1(e1.m, std::adopt_lock); // std::lock_guard<std::mutex> lk2(e2.m, std::adopt_lock); // Código equivalente 2 (si se necesirtan unique_locks, p. ej., para variables de condición) // std::unique_lock<std::mutex> lk1(e1.m, std::defer_lock); // std::unique_lock<std::mutex> lk2(e2.m, std::defer_lock); // std::lock(lk1, lk2); { std::lock_guard<std::mutex> lk(io_mutex); std::cout << e1.id << " y " << e2.id << " adquirieron cerrojos" << std::endl; } e1.lunch_partners.push_back(e2.id); e2.lunch_partners.push_back(e1.id); } send_mail(e1, e2); send_mail(e2, e1); } int main() { Employee alice("alice"), bob("bob"), christina("christina"), dave("dave"); // asignar en hilos paralelos porque enviar correo a los usuarios // sobre sus compañeros asignados se lleva mucho tiempo std::vector<std::thread> threads; threads.emplace_back(assign_lunch_partner, std::ref(alice), std::ref(bob)); threads.emplace_back(assign_lunch_partner, std::ref(christina), std::ref(bob)); threads.emplace_back(assign_lunch_partner, std::ref(christina), std::ref(alice)); threads.emplace_back(assign_lunch_partner, std::ref(dave), std::ref(bob)); for (auto &thread : threads) thread.join(); std::cout << alice.output() << '\n' << bob.output() << '\n' << christina.output() << '\n' << dave.output() << '\n'; }
Posible salida:
alice y bob a la espera de cerrojos alice y bob adquirieron cerrojos christina y bob a la espera de cerrojos christina y alice a la espera de cerrojos dave y bob a la espera de cerrojos dave y bob adquirieron cerrojos christina y alice adquirieron cerrojos christina y bob adquirieron cerrojos Empleado alice tiene compañeros de almuerzo: bob christina Empleado bob tiene compañeros de almuerzo: alice dave christina Empleado christina tiene compañeros de almuerzo: alice bob Empleado dave tiene compañeros de almuerzo: bob
[editar] Informes de defectos
Los siguientes informes de defectos de cambio de comportamiento se aplicaron de manera retroactiva a los estándares de C++ publicados anteriormente.
ID | Aplicado a | Comportamiento según lo publicado | Comportamiento correcto |
---|---|---|---|
LWG 2981 | C++17 | Se proporcionó guía de deducción redundante de scoped_lock<MutexTypes...> .
|
Se eliminó. |
[editar] Véase también
(C++11) |
Implementa un envoltorio de propiedad de mutex movible. (plantilla de clase) |
(C++11) |
Implementa un envoltorio de propiedad de mutex estrictamente basado en un ámbito. (plantilla de clase) |