So, iirc, from a long time ago, Alex Terekhov mentioned the need of an acquire barrier when a simple atomic ref count drops to zero. The
acquire _needs_ to be _after_ the atomic rmw and _before_ _any_ user
code wrt delete/resuse/ect...
Basically,
____________
// Release...
std::atomic_thread_fence(std::memory_order_release);
// Dec...
if (m_refcount.fetch_sub(1, std::memory_order_relaxed) == 1)
{
-a-a-a // Acquire...
-a-a-a std::atomic_thread_fence(std::memory_order_acquire);
-a-a-a delete this;
}
____________
I think its right.
On 2/1/26 01:41, Chris M. Thomasson wrote:
So, iirc, from a long time ago, Alex Terekhov mentioned the need of an
acquire barrier when a simple atomic ref count drops to zero. The
acquire _needs_ to be _after_ the atomic rmw and _before_ _any_ user
code wrt delete/resuse/ect...
Basically,
____________
// Release...
std::atomic_thread_fence(std::memory_order_release);
// Dec...
if (m_refcount.fetch_sub(1, std::memory_order_relaxed) == 1)
{
-a-a-a-a // Acquire...
-a-a-a-a std::atomic_thread_fence(std::memory_order_acquire);
-a-a-a-a delete this;
}
____________
I think its right.
Yeah, probably to prevent loads and stores from the delete moving before
the refcount got set to zero. Although I think control dependency would prvent stores from moving before it anyway.
On 2/2/2026 7:25 AM, jseigh wrote:
On 2/1/26 01:41, Chris M. Thomasson wrote:
So, iirc, from a long time ago, Alex Terekhov mentioned the need of an
acquire barrier when a simple atomic ref count drops to zero. The
acquire _needs_ to be _after_ the atomic rmw and _before_ _any_ user
code wrt delete/resuse/ect...
Basically,
____________
// Release...
std::atomic_thread_fence(std::memory_order_release);
// Dec...
if (m_refcount.fetch_sub(1, std::memory_order_relaxed) == 1)
{
-a-a-a-a // Acquire...
-a-a-a-a std::atomic_thread_fence(std::memory_order_acquire);
-a-a-a-a delete this;
}
____________
I think its right.
Yeah, probably to prevent loads and stores from the delete moving
before the refcount got set to zero. Although I think control
dependency would prvent stores from moving before it anyway.
I was thinking about, well let's say _after_ the release membar, another thread incs the refcount does some things and decs the count. Then our
thread hits zero. It needs an acquire... Not sure if control dependency
is enough?
On Sun, 08 Feb 2026 13:44:02 -0800, Chris M. Thomasson wrote:
On 2/2/2026 7:25 AM, jseigh wrote:
On 2/1/26 01:41, Chris M. Thomasson wrote:
So, iirc, from a long time ago, Alex Terekhov mentioned the need of an >>>> acquire barrier when a simple atomic ref count drops to zero. The
acquire _needs_ to be _after_ the atomic rmw and _before_ _any_ user
code wrt delete/resuse/ect...
Basically,
____________
// Release...
std::atomic_thread_fence(std::memory_order_release);
// Dec...
if (m_refcount.fetch_sub(1, std::memory_order_relaxed) == 1)
{
-a-a-a-a // Acquire...
-a-a-a-a std::atomic_thread_fence(std::memory_order_acquire);
-a-a-a-a delete this;
}
____________
I think its right.
Yeah, probably to prevent loads and stores from the delete moving
before the refcount got set to zero. Although I think control
dependency would prvent stores from moving before it anyway.
I was thinking about, well let's say _after_ the release membar, another
thread incs the refcount does some things and decs the count. Then our
thread hits zero. It needs an acquire... Not sure if control dependency
is enough?
If the ref count reaches zero and then another thread increases the ref
count then there is an error in your design.
/Flibble
On Sun, 08 Feb 2026 13:44:02 -0800, Chris M. Thomasson wrote:
On 2/2/2026 7:25 AM, jseigh wrote:
On 2/1/26 01:41, Chris M. Thomasson wrote:
So, iirc, from a long time ago, Alex Terekhov mentioned the need of an >>>> acquire barrier when a simple atomic ref count drops to zero. The
acquire _needs_ to be _after_ the atomic rmw and _before_ _any_ user
code wrt delete/resuse/ect...
Basically,
____________
// Release...
std::atomic_thread_fence(std::memory_order_release);
// Dec...
if (m_refcount.fetch_sub(1, std::memory_order_relaxed) == 1)
{
-a-a-a-a // Acquire...
-a-a-a-a std::atomic_thread_fence(std::memory_order_acquire);
-a-a-a-a delete this;
}
____________
I think its right.
Yeah, probably to prevent loads and stores from the delete moving
before the refcount got set to zero. Although I think control
dependency would prvent stores from moving before it anyway.
I was thinking about, well let's say _after_ the release membar, another
thread incs the refcount does some things and decs the count. Then our
thread hits zero. It needs an acquire... Not sure if control dependency
is enough?
If the ref count reaches zero and then another thread increases the ref
count then there is an error in your design.
On 2/13/2026 5:16 AM, HAL 9000 wrote:
On Sun, 08 Feb 2026 13:44:02 -0800, Chris M. Thomasson wrote:
On 2/2/2026 7:25 AM, jseigh wrote:
On 2/1/26 01:41, Chris M. Thomasson wrote:
So, iirc, from a long time ago, Alex Terekhov mentioned the need of
an acquire barrier when a simple atomic ref count drops to zero. The >>>>> acquire _needs_ to be _after_ the atomic rmw and _before_ _any_ user >>>>> code wrt delete/resuse/ect...
Basically,
____________
// Release...
std::atomic_thread_fence(std::memory_order_release);
// Dec...
if (m_refcount.fetch_sub(1, std::memory_order_relaxed) == 1)
{
-a-a-a-a // Acquire...
-a-a-a-a std::atomic_thread_fence(std::memory_order_acquire);
-a-a-a-a delete this;
}
____________
I think its right.
Yeah, probably to prevent loads and stores from the delete moving
before the refcount got set to zero. Although I think control
dependency would prvent stores from moving before it anyway.
I was thinking about, well let's say _after_ the release membar,
another thread incs the refcount does some things and decs the count.
Then our thread hits zero. It needs an acquire... Not sure if control
dependency is enough?
If the ref count reaches zero and then another thread increases the ref
count then there is an error in your design.
/Flibble
No, this would occur between the membar and the subsequent drop to zero.
____________
// Release...
std::atomic_thread_fence(std::memory_order_release);
// *** Say another thread inc's, uses it, and decs right here!
// Dec...
if (m_refcount.fetch_sub(1, std::memory_order_relaxed) == 1)
{
// Acquire... std::atomic_thread_fence(std::memory_order_acquire);
delete this;
}
____________
On Fri, 13 Feb 2026 11:42:46 -0800, Chris M. Thomasson wrote:
On 2/13/2026 5:16 AM, HAL 9000 wrote:
On Sun, 08 Feb 2026 13:44:02 -0800, Chris M. Thomasson wrote:
On 2/2/2026 7:25 AM, jseigh wrote:
On 2/1/26 01:41, Chris M. Thomasson wrote:
So, iirc, from a long time ago, Alex Terekhov mentioned the need of >>>>>> an acquire barrier when a simple atomic ref count drops to zero. The >>>>>> acquire _needs_ to be _after_ the atomic rmw and _before_ _any_ user >>>>>> code wrt delete/resuse/ect...
Basically,
____________
// Release...
std::atomic_thread_fence(std::memory_order_release);
// Dec...
if (m_refcount.fetch_sub(1, std::memory_order_relaxed) == 1)
{
-a-a-a-a // Acquire...
-a-a-a-a std::atomic_thread_fence(std::memory_order_acquire);
-a-a-a-a delete this;
}
____________
I think its right.
Yeah, probably to prevent loads and stores from the delete moving
before the refcount got set to zero. Although I think control
dependency would prvent stores from moving before it anyway.
I was thinking about, well let's say _after_ the release membar,
another thread incs the refcount does some things and decs the count.
Then our thread hits zero. It needs an acquire... Not sure if control
dependency is enough?
If the ref count reaches zero and then another thread increases the ref
count then there is an error in your design.
/Flibble
No, this would occur between the membar and the subsequent drop to zero.
____________
// Release...
std::atomic_thread_fence(std::memory_order_release);
// *** Say another thread inc's, uses it, and decs right here!
// Dec...
if (m_refcount.fetch_sub(1, std::memory_order_relaxed) == 1)
{
// Acquire... std::atomic_thread_fence(std::memory_order_acquire);
delete this;
}
____________
No, it is an error in your design: if the ref count ever drops to zero
there should no longer be any other owners - no other threads to affect
the ref count.
On 2/13/26 08:16, HAL 9000 wrote:
On Sun, 08 Feb 2026 13:44:02 -0800, Chris M. Thomasson wrote:
On 2/2/2026 7:25 AM, jseigh wrote:
On 2/1/26 01:41, Chris M. Thomasson wrote:
So, iirc, from a long time ago, Alex Terekhov mentioned the need of an >>>>> acquire barrier when a simple atomic ref count drops to zero. The
acquire _needs_ to be _after_ the atomic rmw and _before_ _any_ user >>>>> code wrt delete/resuse/ect...
Basically,
____________
// Release...
std::atomic_thread_fence(std::memory_order_release);
// Dec...
if (m_refcount.fetch_sub(1, std::memory_order_relaxed) == 1)
{
-a-a-a-a-a // Acquire...
-a-a-a-a-a std::atomic_thread_fence(std::memory_order_acquire);
-a-a-a-a-a delete this;
}
____________
I think its right.
Yeah, probably to prevent loads and stores from the delete moving
before the refcount got set to zero. Although I think control
dependency would prvent stores from moving before it anyway.
I was thinking about, well let's say _after_ the release membar, another >>> thread incs the refcount does some things and decs the count. Then our
thread hits zero. It needs an acquire... Not sure if control dependency
is enough?
If the ref count reaches zero and then another thread increases the ref
count then there is an error in your design.
Possibly.-a The increment logic wasn't specified.
The point is if the
shared data was mutable and the dtor needed to see that mutated state,
then you need a release/acquire to handle that correctly.-a It's a
special case but a good refcount implementation should assume that
is a possibility.
On 2/15/2026 5:46 AM, HAL 9000 wrote:
On Fri, 13 Feb 2026 11:42:46 -0800, Chris M. Thomasson wrote:
On 2/13/2026 5:16 AM, HAL 9000 wrote:
On Sun, 08 Feb 2026 13:44:02 -0800, Chris M. Thomasson wrote:
On 2/2/2026 7:25 AM, jseigh wrote:
On 2/1/26 01:41, Chris M. Thomasson wrote:
So, iirc, from a long time ago, Alex Terekhov mentioned the need >>>>>>> of an acquire barrier when a simple atomic ref count drops to
zero. The acquire _needs_ to be _after_ the atomic rmw and
_before_ _any_ user code wrt delete/resuse/ect...
Basically,
____________
// Release...
std::atomic_thread_fence(std::memory_order_release);
// Dec...
if (m_refcount.fetch_sub(1, std::memory_order_relaxed) == 1)
{
-a-a-a-a // Acquire...
-a-a-a-a std::atomic_thread_fence(std::memory_order_acquire);
-a-a-a-a delete this;
}
____________
I think its right.
Yeah, probably to prevent loads and stores from the delete moving
before the refcount got set to zero. Although I think control
dependency would prvent stores from moving before it anyway.
I was thinking about, well let's say _after_ the release membar,
another thread incs the refcount does some things and decs the
count.
Then our thread hits zero. It needs an acquire... Not sure if
control dependency is enough?
If the ref count reaches zero and then another thread increases the
ref count then there is an error in your design.
/Flibble
No, this would occur between the membar and the subsequent drop to
zero.
____________
// Release...
std::atomic_thread_fence(std::memory_order_release);
// *** Say another thread inc's, uses it, and decs right here!
// Dec...
if (m_refcount.fetch_sub(1, std::memory_order_relaxed) == 1)
{
// Acquire...
std::atomic_thread_fence(std::memory_order_acquire);
delete this;
}
____________
No, it is an error in your design: if the ref count ever drops to zero
there should no longer be any other owners - no other threads to affect
the ref count.
I am focusing on when a ref count drops to zero: It needs an acquire
membar. Say thread A has the only reference, count = 1. Right before it
decs it, another thread B incs (count = 2), uses it, and decs (count =
1), then thread A decs count = 0. It needs that acquire. This can happen
with strong atomic reference counting. Joe knows all about it. Are you familiar with differential reference counting? He wrote a really neat
one, atomic_ptr.
On Sun, 15 Feb 2026 11:44:10 -0800, Chris M. Thomasson wrote:
On 2/15/2026 5:46 AM, HAL 9000 wrote:
On Fri, 13 Feb 2026 11:42:46 -0800, Chris M. Thomasson wrote:
On 2/13/2026 5:16 AM, HAL 9000 wrote:
On Sun, 08 Feb 2026 13:44:02 -0800, Chris M. Thomasson wrote:
On 2/2/2026 7:25 AM, jseigh wrote:
On 2/1/26 01:41, Chris M. Thomasson wrote:
So, iirc, from a long time ago, Alex Terekhov mentioned the need >>>>>>>> of an acquire barrier when a simple atomic ref count drops to
zero. The acquire _needs_ to be _after_ the atomic rmw and
_before_ _any_ user code wrt delete/resuse/ect...
Basically,
____________
// Release...
std::atomic_thread_fence(std::memory_order_release);
// Dec...
if (m_refcount.fetch_sub(1, std::memory_order_relaxed) == 1)
{
-a-a-a-a // Acquire...
-a-a-a-a std::atomic_thread_fence(std::memory_order_acquire); >>>>>>>>
-a-a-a-a delete this;
}
____________
I think its right.
Yeah, probably to prevent loads and stores from the delete moving >>>>>>> before the refcount got set to zero. Although I think control
dependency would prvent stores from moving before it anyway.
I was thinking about, well let's say _after_ the release membar,
another thread incs the refcount does some things and decs the
count.
Then our thread hits zero. It needs an acquire... Not sure if
control dependency is enough?
If the ref count reaches zero and then another thread increases the
ref count then there is an error in your design.
/Flibble
No, this would occur between the membar and the subsequent drop to
zero.
____________
// Release...
std::atomic_thread_fence(std::memory_order_release);
// *** Say another thread inc's, uses it, and decs right here!
// Dec...
if (m_refcount.fetch_sub(1, std::memory_order_relaxed) == 1)
{
// Acquire...
std::atomic_thread_fence(std::memory_order_acquire);
delete this;
}
____________
No, it is an error in your design: if the ref count ever drops to zero
there should no longer be any other owners - no other threads to affect
the ref count.
I am focusing on when a ref count drops to zero: It needs an acquire
membar. Say thread A has the only reference, count = 1. Right before it
decs it, another thread B incs (count = 2), uses it, and decs (count =
1), then thread A decs count = 0. It needs that acquire. This can happen
with strong atomic reference counting. Joe knows all about it. Are you
familiar with differential reference counting? He wrote a really neat
one, atomic_ptr.
Isn't this a solved problem? std::shared_ptr is thread-safe.
On Sun, 15 Feb 2026 11:44:10 -0800, Chris M. Thomasson wrote:
On 2/15/2026 5:46 AM, HAL 9000 wrote:
On Fri, 13 Feb 2026 11:42:46 -0800, Chris M. Thomasson wrote:
On 2/13/2026 5:16 AM, HAL 9000 wrote:
On Sun, 08 Feb 2026 13:44:02 -0800, Chris M. Thomasson wrote:
On 2/2/2026 7:25 AM, jseigh wrote:
On 2/1/26 01:41, Chris M. Thomasson wrote:
So, iirc, from a long time ago, Alex Terekhov mentioned the need >>>>>>>> of an acquire barrier when a simple atomic ref count drops to
zero. The acquire _needs_ to be _after_ the atomic rmw and
_before_ _any_ user code wrt delete/resuse/ect...
Basically,
____________
// Release...
std::atomic_thread_fence(std::memory_order_release);
// Dec...
if (m_refcount.fetch_sub(1, std::memory_order_relaxed) == 1)
{
-a-a-a-a // Acquire...
-a-a-a-a std::atomic_thread_fence(std::memory_order_acquire); >>>>>>>>
-a-a-a-a delete this;
}
____________
I think its right.
Yeah, probably to prevent loads and stores from the delete moving >>>>>>> before the refcount got set to zero. Although I think control
dependency would prvent stores from moving before it anyway.
I was thinking about, well let's say _after_ the release membar,
another thread incs the refcount does some things and decs the
count.
Then our thread hits zero. It needs an acquire... Not sure if
control dependency is enough?
If the ref count reaches zero and then another thread increases the
ref count then there is an error in your design.
/Flibble
No, this would occur between the membar and the subsequent drop to
zero.
____________
// Release...
std::atomic_thread_fence(std::memory_order_release);
// *** Say another thread inc's, uses it, and decs right here!
// Dec...
if (m_refcount.fetch_sub(1, std::memory_order_relaxed) == 1)
{
// Acquire...
std::atomic_thread_fence(std::memory_order_acquire);
delete this;
}
____________
No, it is an error in your design: if the ref count ever drops to zero
there should no longer be any other owners - no other threads to affect
the ref count.
I am focusing on when a ref count drops to zero: It needs an acquire
membar. Say thread A has the only reference, count = 1. Right before it
decs it, another thread B incs (count = 2), uses it, and decs (count =
1), then thread A decs count = 0. It needs that acquire. This can happen
with strong atomic reference counting. Joe knows all about it. Are you
familiar with differential reference counting? He wrote a really neat
one, atomic_ptr.
Isn't this a solved problem? std::shared_ptr is thread-safe.
On Sun, 08 Feb 2026 13:44:02 -0800, Chris M. Thomasson wrote:
On 2/2/2026 7:25 AM, jseigh wrote:
On 2/1/26 01:41, Chris M. Thomasson wrote:
So, iirc, from a long time ago, Alex Terekhov mentioned the need of an >>>> acquire barrier when a simple atomic ref count drops to zero. The
acquire _needs_ to be _after_ the atomic rmw and _before_ _any_ user
code wrt delete/resuse/ect...
Basically,
____________
// Release...
std::atomic_thread_fence(std::memory_order_release);
// Dec...
if (m_refcount.fetch_sub(1, std::memory_order_relaxed) == 1)
{
-a-a-a-a // Acquire...
-a-a-a-a std::atomic_thread_fence(std::memory_order_acquire);
-a-a-a-a delete this;
}
____________
I think its right.
Yeah, probably to prevent loads and stores from the delete moving
before the refcount got set to zero. Although I think control
dependency would prvent stores from moving before it anyway.
I was thinking about, well let's say _after_ the release membar, another
thread incs the refcount does some things and decs the count. Then our
thread hits zero. It needs an acquire... Not sure if control dependency
is enough?
If the ref count reaches zero and then another thread increases the ref
count then there is an error in your design.
On 2/15/2026 3:53 PM, HAL 9000 wrote:
On Sun, 15 Feb 2026 11:44:10 -0800, Chris M. Thomasson wrote:
On 2/15/2026 5:46 AM, HAL 9000 wrote:
On Fri, 13 Feb 2026 11:42:46 -0800, Chris M. Thomasson wrote:
On 2/13/2026 5:16 AM, HAL 9000 wrote:
On Sun, 08 Feb 2026 13:44:02 -0800, Chris M. Thomasson wrote:
On 2/2/2026 7:25 AM, jseigh wrote:
On 2/1/26 01:41, Chris M. Thomasson wrote:
So, iirc, from a long time ago, Alex Terekhov mentioned the need >>>>>>>>> of an acquire barrier when a simple atomic ref count drops to >>>>>>>>> zero. The acquire _needs_ to be _after_ the atomic rmw and
_before_ _any_ user code wrt delete/resuse/ect...
Basically,
____________
// Release...
std::atomic_thread_fence(std::memory_order_release);
// Dec...
if (m_refcount.fetch_sub(1, std::memory_order_relaxed) == 1) >>>>>>>>> {
-a-a -a-a-a-a // Acquire...
-a-a -a-a-a-a std::atomic_thread_fence(std::memory_order_acquire); >>>>>>>>>
-a-a -a-a-a-a delete this;
}
____________
I think its right.
Yeah, probably to prevent loads and stores from the delete moving >>>>>>>> before the refcount got set to zero. Although I think control
dependency would prvent stores from moving before it anyway.
I was thinking about, well let's say _after_ the release membar, >>>>>>> another thread incs the refcount does some things and decs the
count.
Then our thread hits zero. It needs an acquire... Not sure if
control dependency is enough?
If the ref count reaches zero and then another thread increases the >>>>>> ref count then there is an error in your design.
/Flibble
No, this would occur between the membar and the subsequent drop to
zero.
____________
// Release...
std::atomic_thread_fence(std::memory_order_release);
// *** Say another thread inc's, uses it, and decs right here!
// Dec...
if (m_refcount.fetch_sub(1, std::memory_order_relaxed) == 1)
{
-a-a-a-a-a-a // Acquire...
-a-a-a-a-a-a std::atomic_thread_fence(std::memory_order_acquire);
-a-a-a-a-a-a delete this;
}
____________
No, it is an error in your design: if the ref count ever drops to zero >>>> there should no longer be any other owners - no other threads to affect >>>> the ref count.
I am focusing on when a ref count drops to zero: It needs an acquire
membar. Say thread A has the only reference, count = 1. Right before it
decs it, another thread B incs (count = 2), uses it, and decs (count =
1), then thread A decs count = 0. It needs that acquire. This can happen >>> with strong atomic reference counting. Joe knows all about it. Are you
familiar with differential reference counting? He wrote a really neat
one, atomic_ptr.
Isn't this a solved problem? std::shared_ptr is thread-safe.
Solved for basic reference counting vs strong atomic?
| Sysop: | Amessyroom |
|---|---|
| Location: | Fayetteville, NC |
| Users: | 59 |
| Nodes: | 6 (0 / 6) |
| Uptime: | 19:25:54 |
| Calls: | 810 |
| Calls today: | 1 |
| Files: | 1,287 |
| D/L today: |
10 files (21,017K bytes) |
| Messages: | 193,989 |