1
template<typename T>
class TSQueue {
public:
    TSQueue() {}
    TSQueue(const TSQueue& rhs) {
        lock_guard<mutex> lg1(rhs._mutex);
        _data = rhs._data;
    }

private:
    queue<shared_ptr<T> > _data;
    mutex _mutex;

};

I have seen in textbooks that only source (rhs) is locked in copy constructor. I am not sure how exclusive access of destination (this) is ensured by only locking rhs. I think both source and destination should be locked. What is the ideal way to write thread safe copy constructor?

Arghya Pal
  • 133
  • 1
  • 9
  • Possible duplicate of https://stackoverflow.com/questions/49500419/how-to-use-a-mutex-as-a-member-variable-without-copy-constructor-of-simple-enc – Galik Apr 09 '22 at 16:46

2 Answers2

6

When the constructor runs it's creating a new object; there is no possibility of that object being accessed from another thread, because there is no code that can pass that (currently non-existent) object to another thread. So there's no need to protect the object that's being constructed.

Pete Becker
  • 74,985
  • 8
  • 76
  • 165
  • I think maybe placement new can do it. Not sure technically it exist or not. but it can be somewhat accessed. – apple apple Apr 09 '22 at 16:28
  • @appleapple -- well, maybe. If you explicitly destroy an object that another thread accesses, then use placement new to construct a new object in place of the old one, the other thread could do something with the newly constructed object. But the object it knew about no longer exists, so you're deep into undefined behavior. That's so perverse that you shouldn't even be thinking of it, much less protecting against it. – Pete Becker Apr 09 '22 at 18:13
0

Let's step out of the C++ world for a bit. The objective is to copy something say a blueprint of a house at a given time. When the copy happens we do not want the architect to be modifying the blueprint. So we go ahead and lock the blueprint. Once we know it's safely locked away from any modification we copy the blueprint.

Now maybe not just you but several others also want a copy of the blueprint. So we ensure that the architect does not modify the blueprint whenever a copy is done.

Do we really care if you or the others modify their own copy while they are creating it. No we don't. All that matters is the source not the destination.

You as the owner of your copy are still in the process of creating it and so no one else would even be able to access it when you are still creating your copy.

Try translating this to the copy constructor code you have written and you will see why protecting the destination is not necessary

pcodex
  • 1,812
  • 15
  • 16
  • This doesn't address the fundamental issue of having a data race. If two threads access the same object without synchronization and at least one of them modifies it, that's a data race, and the behavior of the program is undefined. So, no, we don't care about modifying a blueprint while it's being created. But an object is not a blueprint. – Pete Becker Apr 09 '22 at 18:15
  • The OP's question is in no way trying to bring up the "fundamental issue of having a data race". It's more around ensuring exclusive access to the destination which is moot and that's what I'm trying to explain. – pcodex Apr 09 '22 at 20:00
  • The reason for enforcing exclusive access is to prevent data races. If you can’t guarantee exclusive access you have a data race and, as a result, undefined behavior. That’s a paraphrase of the more formal language in the C++ standard. So, yes, the fundamental issue here is managing data races. – Pete Becker Apr 09 '22 at 23:38
  • So now you assume I don't know the reason for exclusive access just as you have assumed that the OP's question is around data races. Read the question again – pcodex Apr 10 '22 at 04:07