Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

C++ shared_ptr and mutex

I’m new to C++ and I have to following scenario:

main.cpp

#include "Foo.h"
#include "Bar.h"

int main() {
    Bar bar{};
    auto bar_ptr = std::make_shared<Bar>(bar);

    for (int i = 0; i < 10; i++) {
        Foo foo{bar_ptr};
    }

    return 0;
}

I want 10 Instances of Class Foo to share 1 Instance of Class Bar. Each Instance of Class Foo will run in a separate Thread. I want the shared Instance of Class Bar only to be accessed by one Instance of Foo at a time. That’s why I wanted to add a std::mutex to Foo. This seems to conflict with std::mutex not being copyable/moveable. What is the correct way to use a mutex with a shared_ptr?

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

Foo.h

#include <memory>
#include <utility>
#include "Bar.h"

class Foo {
    std::shared_ptr<Bar> bar_ptr;

public:
    explicit Foo(std::shared_ptr<Bar> bar_ptr){
        this->bar_ptr = std::move(bar_ptr);
    }
};

Bar.h

#include <mutex>

class Bar {
    std::mutex mutex{};

};

>Solution :

std::mutex is a move-only type, so you can’t copy it.

In your main function you are creating a Bar, and then trying to create a std::shared_ptr by copying that instance of Bar.

Instead, just use std::make_shared<Bar>() to create a shared_ptr to a bar with the default constructor.

#include "Foo.h"
#include "Bar.h"

int main() {
    auto bar_ptr = std::make_shared<Bar>();

    for (int i = 0; i < 10; i++) {
        Foo foo{bar_ptr};
    }

    return 0;
}

To clarify, the arguments passed to make_shared are forwarded to the constructor of the class. If you pass a Bar& it will try to use the copy constructor.

If you pass nothing it will use the default constructor.

If Bars constructor takes arguments in your real use-case, pass the arguments to make_shared.

#include <memory>
#include <utility>
#include <mutex>

class Bar {
    public:
    Bar(int i) : value(i) {}
    private:
    std::mutex mutex{};
    int value;
};

class Foo {
    std::shared_ptr<Bar> bar_ptr;

public:
    // Use the initializer list when possible
    // Otherwise we first default-construct then assign
    explicit Foo(std::shared_ptr<Bar> ptr) : bar_ptr(std::move(ptr)) {}
};

int main() {
    auto bar_ptr = std::make_shared<Bar>(5);

    for (int i = 0; i < 10; i++) {
        Foo foo{bar_ptr};
    }

    return 0;
}
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading