Reputation: 35982
Working case:
template<typename T>
class threadsafe_queue
{
private:
mutable std::mutex mut;
std::queue<T> data_queue;
public:
threadsafe_queue()
{}
threadsafe_queue(const threadsafe_queue& other)
{
std::lock_guard<std::mutex> lk(other.mut);
data_queue=other.data_queue;
}
};
Case that should fail: Note no mutable
on std::mutex mut;
template<typename T>
class threadsafe_queue
{
private:
std::mutex mut;
std::queue<T> data_queue;
public:
threadsafe_queue()
{}
threadsafe_queue(const threadsafe_queue& other)
{
std::lock_guard<std::mutex> lk(other.mut);
data_queue=other.data_queue;
}
};
I have tried the both cases listed above and they compile without problems. I assume internally the lock_guard calls mutex::lock function which itself is NOT a const function.
Question> why can we lock the mutex from a const object in the copy constructor?
Upvotes: 1
Views: 2165
Reputation: 131970
The first example compiles because the mutex is qualified to be mutable
. That means that this field can be modified, mutated, without the containing object considered to have been changed. So, in a sense, the mutex' state is not "part of the queue". The compiler allows const
methods to modify mutable
members.
The second example only compiles as long as you don't actually try to instantiate the class and use that method. If you do, it fails. Templates are magic...
Upvotes: 10