Questo è il tipo di domanda con cui le dichiarazioni di stampa possono davvero essere d'aiuto. Per esempio:
#include <mutex>
#include <iostream>
std::mutex mut;
template <class Mutex>
class Lock
{
Mutex& mut_;
public:
~Lock()
{
std::cout << "unlock\n";
mut_.unlock();
}
Lock(const Lock&) = delete;
Lock& operator=(const Lock&) = delete;
Lock(Mutex& mut)
: mut_(mut)
{
mut_.lock();
std::cout << "lock\n";
}
};
struct A
{
~A()
{
std::cout << "~A() : " << this << "\n";
}
A()
{
std::cout << "A() : " << this << "\n";
}
A(const A& a)
{
std::cout << "A(const A&) : " << this << ", " << &a << "\n";
}
A& operator=(const A& a)
{
std::cout << "A& operator=(const A&) : " << this << ", " << &a << "\n";
return *this;
}
};
A a;
A
get()
{
Lock<std::mutex> lk(mut);
return a;
}
int
main()
{
std::cout << "Start\n";
auto vec = get();
std::cout << "End\n";
}
Rendendo la mia versione di std::lock_guard
, posso inserire istruzioni di stampa per sapere quando il mutex viene bloccato e sbloccato. .
e facendo un falso std::vector
(chiamato A
sopra), posso inserire le dichiarazioni di stampa nel membri speciali che mi interessano per me questo uscite:
A() : 0x10fcfb188
Start
lock
A(const A&) : 0x7fff4ff06b28, 0x10fcfb188
unlock
End
~A() : 0x7fff4ff06b28
~A() : 0x10fcfb188
che dimostra chiaramente che il mutex è bloccato mentre viene copiato il A
a 0x10fcfb188.
Il test può essere modificato per l'assegnazione con:
int
main()
{
A vec;
std::cout << "Start\n";
vec = get();
std::cout << "End\n";
}
che ora uscite:
A() : 0x10d8a7190
A() : 0x7fff5235ab28
Start
lock
A(const A&) : 0x7fff5235ab18, 0x10d8a7190
unlock
A& operator=(const A&) : 0x7fff5235ab28, 0x7fff5235ab18
~A() : 0x7fff5235ab18
End
~A() : 0x7fff5235ab28
~A() : 0x10d8a7190
Dapprima sembra che l'assegnazione avviene al di fuori del blocco, e quindi sembra pericoloso. Tuttavia, a seguito di un'ispezione più ravvicinata, si vede che lo A
protetto a 0x10d8a7190 viene copiato in uno spazio temporaneo A
all'interno del blocco. Il mutex viene quindi sbloccato e viene assegnato un incarico dal temporaneo al locale. Nessun altro thread potrebbe fare riferimento al temporaneo. Quindi, fino a quando nessun altro thread fa riferimento a vec
, questo è di nuovo sicuro.
fonte
2014-12-09 19:41:22
La costruzione della copia di 'vec' avviene al di fuori del blocco. Se altri thread potrebbero modificare il vettore di riferimento, hai una corsa di dati. – Casey
Questo non funzionerà, si sta restituendo uno stato interno ('m_value') per riferimento. –
@ DieterLücking: infatti, ho notato questo mentre aggiungo effettivamente il codice ^^ 'Anche se m_value è un membro (quindi dovrebbe funzionare effettivamente), restituendo per valore corregge il mio problema (anche se devo ancora usare lock_guard). Quello che ho aggiunto è in realtà un problema non realizzato. Grazie. –
Korchkidu