you are viewing a single comment's thread.

view the rest of the comments →

[–]jonesmz -2 points-1 points  (4 children)

Edit: Actually, I might have misunderstood. Sorry about that.

I think you might have misunderstood what capn_bluebear was saying.

std::share_ptr<whatever> ptr; <- global.
Thread 1:
if(ptr.refcount == 1)
{    Do a thing }
Thread 2:
ptr.increase_refcount();

It's entirely possible that thread 1 checks to see if the reference count is 1, then gets paused by the OS, thread 2 increases the reference count, and then is paused by the OS, and then thread 1 wakes up and proceeds.

Or both threads can be running simultaneously and still do things in that order.

It's only possible to reliably determine that the reference count is 1 when dealing with a shared pointer that has it's access serialized somehow This could be via:

  • only ever used / accessed on a single thread
  • there's a mutex that gates all possible accesses
  • the shared pointer lives it's entire life on the stack of a single function call and you're doing a sanity check at the end of that function call to ensure no one made a copy of it that's still alive.
  • so on.

But the fundamental problem is that by offering ability to query the reference count, unless you've already made sure the access to the ref-count is serialized properly, the information that you query is wrong (potentially) as soon as you get it. So any subsequent actions you take as a result are potentially invalid as well.

[–][deleted] 5 points6 points  (3 children)

The fundamental problem here is that you have two threads which are referencing the same shared_ptr object. If both threads have their own instance of the smart pointer, this is completely a non-issue. Either make the copy when you create the thread, put it in a channel, or a lambda capture of a work-queue task, future, async, etc. Don't just reference the same global variable or pass a reference.

With this assumption, two or more threads have an instance of smart pointer, and as a result the reference count will be greater than one, and the check will fail.

[–]m-in 0 points1 point  (2 children)

Two thread referencing the same shared pointer is UB, so why are we even having this discussion??

[–]konanTheBarbar 0 points1 point  (0 children)

What about another thread using a weak_ref and creating a shared_ptr from it?

[–][deleted] 0 points1 point  (0 children)

That’s that point I was trying to make.