• when a ref count drops to zero...

    From Chris M. Thomasson@chris.m.thomasson.1@gmail.com to comp.lang.c++ on Sat Jan 31 22:41:42 2026
    From Newsgroup: comp.lang.c++

    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)
    {

    // Acquire...
    std::atomic_thread_fence(std::memory_order_acquire);

    delete this;
    }
    ____________

    I think its right.
    --- Synchronet 3.21b-Linux NewsLink 1.2
  • From jseigh@jseigh_es00@xemaps.com to comp.lang.c++ on Mon Feb 2 10:25:51 2026
    From Newsgroup: comp.lang.c++

    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 // Acquire...
    -a-a-a std::atomic_thread_fence(std::memory_order_acquire);

    -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.
    --- Synchronet 3.21b-Linux NewsLink 1.2
  • From Chris M. Thomasson@chris.m.thomasson.1@gmail.com to comp.lang.c++ on Sun Feb 8 13:44:02 2026
    From Newsgroup: comp.lang.c++

    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?
    --- Synchronet 3.21b-Linux NewsLink 1.2
  • From HAL 9000@hal@discovery.nasa to comp.lang.c++ on Fri Feb 13 13:16:10 2026
    From Newsgroup: comp.lang.c++

    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
    --- Synchronet 3.21b-Linux NewsLink 1.2
  • From Chris M. Thomasson@chris.m.thomasson.1@gmail.com to comp.lang.c++ on Fri Feb 13 11:42:46 2026
    From Newsgroup: comp.lang.c++

    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;
    }
    ____________


    --- Synchronet 3.21b-Linux NewsLink 1.2
  • From jseigh@jseigh_es00@xemaps.com to comp.lang.c++ on Sat Feb 14 18:22:28 2026
    From Newsgroup: comp.lang.c++

    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 // 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.


    Possibly. 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. It's a
    special case but a good refcount implementation should assume that
    is a possibility.
    --- Synchronet 3.21b-Linux NewsLink 1.2
  • From HAL 9000@hal@discovery.nasa to comp.lang.c++ on Sun Feb 15 13:46:43 2026
    From Newsgroup: comp.lang.c++

    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.

    /Flibble
    --- Synchronet 3.21b-Linux NewsLink 1.2
  • From Chris M. Thomasson@chris.m.thomasson.1@gmail.com to comp.lang.c++ on Sun Feb 15 11:44:10 2026
    From Newsgroup: comp.lang.c++

    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.
    --- Synchronet 3.21b-Linux NewsLink 1.2
  • From Chris M. Thomasson@chris.m.thomasson.1@gmail.com to comp.lang.c++ on Sun Feb 15 11:47:14 2026
    From Newsgroup: comp.lang.c++

    On 2/14/2026 3:22 PM, jseigh wrote:
    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.

    Right. shit. Well, I should have pointed out that there are two kinds of reference counting. Basic and "strong atomic", just like your excellent atomic_ptr that uses DWCAS.


    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.

    Exactly! :^)

    --- Synchronet 3.21b-Linux NewsLink 1.2
  • From HAL 9000@hal@discovery.nasa to comp.lang.c++ on Sun Feb 15 23:53:14 2026
    From Newsgroup: comp.lang.c++

    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.

    /Flibble
    --- Synchronet 3.21b-Linux NewsLink 1.2
  • From Chris M. Thomasson@chris.m.thomasson.1@gmail.com to comp.lang.c++ on Sun Feb 15 16:16:24 2026
    From Newsgroup: comp.lang.c++

    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 // 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.

    Sure. Well, I would think so! I was just digging into the nitty gritty
    of it. ;^)
    --- Synchronet 3.21b-Linux NewsLink 1.2
  • From Chris M. Thomasson@chris.m.thomasson.1@gmail.com to comp.lang.c++ on Sun Feb 15 19:44:50 2026
    From Newsgroup: comp.lang.c++

    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 // 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.

    Solved for basic reference counting vs strong atomic?
    --- Synchronet 3.21b-Linux NewsLink 1.2
  • From Chris M. Thomasson@chris.m.thomasson.1@gmail.com to comp.lang.c++ on Mon Feb 16 21:22:43 2026
    From Newsgroup: comp.lang.c++

    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.

    Even is basic refcounting. Say thread A creates an object with a
    refcount of 2. Passes it to another thread B. Thread B mutates the
    object and finally decs, refcount 1. Thread A drops its count, refcount
    0, Thread A still needs an acquire in that case.
    --- Synchronet 3.21b-Linux NewsLink 1.2
  • From Chris M. Thomasson@chris.m.thomasson.1@gmail.com to comp.lang.c++ on Tue Feb 17 12:50:27 2026
    From Newsgroup: comp.lang.c++

    On 2/15/2026 7:44 PM, Chris M. Thomasson wrote:
    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?

    Iirc, c++'s way for strong atomic ref counters? I saw std::atomic<std::shared_ptr<T>>, have not dug into any impls, but Joe
    already has that solved way back.


    --- Synchronet 3.21b-Linux NewsLink 1.2