When I step through the following code in MSVC 2012 I place a breakpoint on line 3. and line 8.
First break comes on line 8.
The lock_guard is called just fine and then we break on line 3. This time, since a lock is already obtained, an exception is thrown when I step over.
I would really like it to just move on since it's still the same thread calling (we just came from line 11.)
Is there another locking mechanism better suited for this scenario?
I have a background in native win32 programming so I'm used to WaitForSingleObject which would just let me through here without fuss, but lock_guard doesn't.
Am I supposed to handle the exception? None of the examples I've seen have any kind of exception handler for lock_guard...
Is there a better way to make sure the map isnt accessed by more than one thread at a time? I need both write and read lock on it, and lock_guard seemed like a smooth alternative since I dont have to ReleaseMutex...
//Cars.h
mutable std::mutex carsMutex;
class Cars
{
private:
std::map<std::string,Cars> _cars;
public:
virtual ~Cars() {}
Cars() {}
Cars & operator[](const std::string &key);
Cars & operator[](const DWORD &key);
std::string color;
};
//Cars.cpp
#include "Cars.h"
1. Cars & Cars::operator[](const std::string &key)
2. {
3. std::lock_guard<std::mutex> lock_a(carsMutex);
4. return _cars[key];
5. }
6. Cars & Cars::operator[](const DWORD &key)
7. {
8. std::lock_guard<std::mutex> lock_a(carsMutex);
9. std::stringstream ss;
10. ss << key;
11. return operator[](ss.str());
12. }
14. void main()
15. {
16. //ok i have multiple threads like this one writing and reading from the map
17. Cars cars;
18. cars[(DWORD)2012]["volvo"].color = "blue";
19. }
UPDATE: Here is my edit of the code above. I have taken the answer into account and this is my new attempt to correctly use std::lock_guard Please comment if its not correct.
//Cars.h
mutable std::recursive_mutex carsMutex;
class Cars
{
private:
std::string _color;
std::map<std::string,Cars> _cars;
public:
virtual ~Cars() {}
Cars() {}
Cars & operator[](const std::string &key);
Cars & operator[](const DWORD &key);
void color(const std::string &color);
std::string color();
};
//Cars.cpp
#include "Cars.h"
1. Cars & Cars::operator[](const std::string &key)
2. {
3. std::lock_guard<std::recursive_mutex> lock(carsMutex);
4. return _cars[key];
5. }
6. Cars & Cars::operator[](const DWORD &key)
7. {
8. std::lock_guard<std::recursive_mutex> lock(carsMutex);
9. std::stringstream ss;
10. ss << key;
11. return operator[](ss.str());
12. }
13. void color(const std::string &color)
14. {
15. std::lock_guard<std::recursive_mutex> lock(carsMutex);
16. _color = color;
17. }
18. std::string color()
19. {
20. std::lock_guard<std::recursive_mutex> lock(carsMutex);
21. return _color;
22. }
23.
24. Cars cars;//this is global...
25. void main()
26. {
27. //ok i have multiple threads like this one writing and reading from the map
28. cars[(DWORD)2012]["volvo"].color("blue");
29. }