Date: Wed, 18 Feb 2026 18:29:56 +0100
We are talking "efficient" here, but are we talking worst-case or average?
Querying for "is_always_lockfree()" can be useful as a (somewhat crude)
check that the worst case scenario is bounded.
If the implementation is "good but with the wrong trade-offs for my problem
domain", then it is not a QoI.
// Robin
On Mon, Feb 16, 2026, 19:09 Jonathan Wakely via Std-Proposals <
std-proposals_at_[hidden]> wrote:
>
>
> On Mon, 16 Feb 2026 at 13:30, Vittorio Romeo via Std-Proposals <
> std-proposals_at_[hidden]> wrote:
>
>> Consider the following pattern:
>>
>> std::atomic_flag flag = ATOMIC_FLAG_INIT;
>>
>> // Thread A
>> flag.test_and_set(std::memory_order_release);
>> flag.notify_all();
>>
>> // Thread B
>> flag.wait(false, std::memory_order_acquire);
>>
>> It can nicely be simplified with a latch:
>>
>> std::latch latch{ 1 };
>>
>> // Thread A
>> latch.count_down();
>>
>> // Thread B
>> latch.wait();
>>
>> This seems a direct improvement, but unfortunately it really isn't:
>> 1. There's no guarantee that `std::latch` uses atomics under the hood
>> 2. There's no guarantee that `std::latch` is "lock-free"
>>
>
> There's no guarantee that std::atomic_flag::wait and
> std::atomic_flag::notify_all are lock-free either.
>
>
>
>> 3. All functions in the first pattern were `noexcept`, while none of the
>> `latch`'s functions are
>>
>> I would like to be able to use the higher-level pattern using
>> `std::latch` without sacrificing performance nor exception safety.
>>
>
> Does it matter whether it uses atomics? Surely what matters is that it's
> efficient, not whether that efficiency is achieved using atomics or using
> magic. If it's not as efficient as it could be using atomics, isn't that
> just a bad implementation?
>
>
>
>>
>> It would be nice if there was a way to detect at compile-time if
>> `std::latch` uses atomic operations under the hood and is guaranteed to not
>> throw.
>> Something like `std::atomic<T>::is_always_lock_free`, but for latches.
>>
>> Ideas:
>> - std::latch::is_always_lock_free
>>
>
> What would this mean? Since wait and notify can use locks, none of latch's
> members can really be lock-free.
>
>
>> - std::latch::uses_atomic_operations
>>
>
> Is this really useful? A uses_atomic_operations constant wouldn't
> guarantee that it's efficient. It could use atomics and be inefficient, or
> it could be efficient without using atomics.
>
>
>
>> - std::latch::is_atomic
>>
>
> What would this mean? std::latch already guarantees not to introduce data
> races, and the counter decrement in count_down is already guaranteed to be
> atomic.
>
>
>>
>> Additionally, it would be nice if the Standard mentioned that while
>> `std::latch`'s functions cannot be generally be marked `noexcept`, they
>> are guaranteed to never throw if the above trait is true.
>>
>
> Could this be solved by just having implementations use conditional
> noexcept on std::latch member functions?
>
> I think what you're asking for latch to be efficient, which is QoI, and to
> be able to tell if latch is nothrow, which you want to use some new traits
> for, but just testing noexcept(declval<latch>().count_down()) &&
> noexcept(declval<latch>().wait()) seems sufficient for that.
>
>
>> What do you think?
>> Worth writing a paper?
>>
>> Cheers,
>>
>> Vittorio Romeo
>> https://vittorioromeo.com
>> --
>> Std-Proposals mailing list
>> Std-Proposals_at_[hidden]
>> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
>>
> --
> Std-Proposals mailing list
> Std-Proposals_at_[hidden]
> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
>
Querying for "is_always_lockfree()" can be useful as a (somewhat crude)
check that the worst case scenario is bounded.
If the implementation is "good but with the wrong trade-offs for my problem
domain", then it is not a QoI.
// Robin
On Mon, Feb 16, 2026, 19:09 Jonathan Wakely via Std-Proposals <
std-proposals_at_[hidden]> wrote:
>
>
> On Mon, 16 Feb 2026 at 13:30, Vittorio Romeo via Std-Proposals <
> std-proposals_at_[hidden]> wrote:
>
>> Consider the following pattern:
>>
>> std::atomic_flag flag = ATOMIC_FLAG_INIT;
>>
>> // Thread A
>> flag.test_and_set(std::memory_order_release);
>> flag.notify_all();
>>
>> // Thread B
>> flag.wait(false, std::memory_order_acquire);
>>
>> It can nicely be simplified with a latch:
>>
>> std::latch latch{ 1 };
>>
>> // Thread A
>> latch.count_down();
>>
>> // Thread B
>> latch.wait();
>>
>> This seems a direct improvement, but unfortunately it really isn't:
>> 1. There's no guarantee that `std::latch` uses atomics under the hood
>> 2. There's no guarantee that `std::latch` is "lock-free"
>>
>
> There's no guarantee that std::atomic_flag::wait and
> std::atomic_flag::notify_all are lock-free either.
>
>
>
>> 3. All functions in the first pattern were `noexcept`, while none of the
>> `latch`'s functions are
>>
>> I would like to be able to use the higher-level pattern using
>> `std::latch` without sacrificing performance nor exception safety.
>>
>
> Does it matter whether it uses atomics? Surely what matters is that it's
> efficient, not whether that efficiency is achieved using atomics or using
> magic. If it's not as efficient as it could be using atomics, isn't that
> just a bad implementation?
>
>
>
>>
>> It would be nice if there was a way to detect at compile-time if
>> `std::latch` uses atomic operations under the hood and is guaranteed to not
>> throw.
>> Something like `std::atomic<T>::is_always_lock_free`, but for latches.
>>
>> Ideas:
>> - std::latch::is_always_lock_free
>>
>
> What would this mean? Since wait and notify can use locks, none of latch's
> members can really be lock-free.
>
>
>> - std::latch::uses_atomic_operations
>>
>
> Is this really useful? A uses_atomic_operations constant wouldn't
> guarantee that it's efficient. It could use atomics and be inefficient, or
> it could be efficient without using atomics.
>
>
>
>> - std::latch::is_atomic
>>
>
> What would this mean? std::latch already guarantees not to introduce data
> races, and the counter decrement in count_down is already guaranteed to be
> atomic.
>
>
>>
>> Additionally, it would be nice if the Standard mentioned that while
>> `std::latch`'s functions cannot be generally be marked `noexcept`, they
>> are guaranteed to never throw if the above trait is true.
>>
>
> Could this be solved by just having implementations use conditional
> noexcept on std::latch member functions?
>
> I think what you're asking for latch to be efficient, which is QoI, and to
> be able to tell if latch is nothrow, which you want to use some new traits
> for, but just testing noexcept(declval<latch>().count_down()) &&
> noexcept(declval<latch>().wait()) seems sufficient for that.
>
>
>> What do you think?
>> Worth writing a paper?
>>
>> Cheers,
>>
>> Vittorio Romeo
>> https://vittorioromeo.com
>> --
>> Std-Proposals mailing list
>> Std-Proposals_at_[hidden]
>> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
>>
> --
> Std-Proposals mailing list
> Std-Proposals_at_[hidden]
> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
>
Received on 2026-02-18 17:30:14
