Daksh Gupta
Daksh Gupta

Reputation: 7804

Different behaviour while passing shared_ptr to weak_ptr in thread functions and normal functions

I'm having a thread function which takes a weak_ptr<> and I pass my shared_ptr<> in the thread function.

Legally weak_ptr<> should not increment the reference count of shared_ptr<>, however, unless I typecast with weak_ptr<> while passing the same to the thread function, it increments the reference count (unexpected)

This behaviour happens only with thread functions and not with normal function calls.

Here is the code for thread function

void thrdfn(weak_ptr<int> wp) {
    cout<<wp.use_count()<<endl;  // Prints 2
}

int main() {
    shared_ptr<int> sp = make_shared<int>();
    thread th { thrdfn, (sp)};
    th.join();
    return 0;
}

However, when I typecast while creating thread, it behaves properly

void thrdfn(weak_ptr<int> wp) {
    cout<<wp.use_count()<<endl;  // Prints 1
}

int main() {
    thread th { thrdfn, weak_ptr<int>(sp)}; // typecast 
}

When I call the function as a normal function call, it works fine without typecasting

void thrdfn(weak_ptr<int> wp) {
    cout<<wp.use_count()<<endl;  // Prints 1
}

int main() {
    shared_ptr<int> sp = make_shared<int>();
    thrdfn(sp);
    return 0;
}

Behaviour is same with multiple compilers

Upvotes: 3

Views: 276

Answers (2)

Barry
Barry

Reputation: 302663

When you write construct a std::thread (and I removed the superfluous parentheses):

thread th{thrdfn, sp};

What happens is:

The new thread of execution starts executing

std::invoke(decay_copy(std::forward<Function>(f)), decay_copy(std::forward<Args>(args))...);

where decay_copy is defined as

template <class T>
std::decay_t<T> decay_copy(T&& v) { return std::forward<T>(v); }

Which is to say, your shared_ptr is copied into the thread and you take a weak_ptr off of that copy. So there are two shared_ptrs: yours and the thread's.

Upvotes: 2

ObliteratedJillo
ObliteratedJillo

Reputation: 5156

Avoid trying auto conversion from shared_ptr to weak_ptr, it may create extra shared_ptr. Below snippet should work fine :

shared_ptr<int> sp = make_shared<int>();
weak_ptr<int> weak = sp;
thread th { thrdfn, (weak)};

Upvotes: 0

Related Questions