q0987
q0987

Reputation: 35982

why can we lock a mutex defined inside a const object?

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

Answers (1)

einpoklum
einpoklum

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

Related Questions