I want to return a std::vector
. This std::vector
may be accessed from other threads (read and write). How can I unlock my std::mutex
just
This is the sort of question that print statements can really help with. For example:
#include
#include
std::mutex mut;
template
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 lk(mut);
return a;
}
int
main()
{
std::cout << "Start\n";
auto vec = get();
std::cout << "End\n";
}
By making my own version of std::lock_guard
, I can insert print statements to find out when the mutex gets locked and unlocked.
And by making a fake std::vector
(called A
above), I can insert print statements into the special members that I'm interested in. For me this outputs:
A() : 0x10fcfb188
Start
lock
A(const A&) : 0x7fff4ff06b28, 0x10fcfb188
unlock
End
~A() : 0x7fff4ff06b28
~A() : 0x10fcfb188
which clearly shows that the mutex is locked while the A
at 0x10fcfb188 is being copied from.
The test can be altered for assignment with:
int
main()
{
A vec;
std::cout << "Start\n";
vec = get();
std::cout << "End\n";
}
which now outputs:
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
At first it looks like the assignment takes place outside the lock, and thus looks unsafe. However upon closer inspection one sees that the protected A
at 0x10d8a7190 is copied to a temporary A
inside the lock. The mutex is then unlocked and an assignment is made from the temporary to the local. No other thread could possibly reference the temporary. So as long as no other thread references vec
, this is again safe.