The (bool) cast wrt callable fiasco aside for a moment. This version
has the fences exactly where they need to be. Using C++ CAS with its
membar A for true and membar B for fail is RIPE for bugs anyway, well, imvvho:
#pragma once
#include <concepts>
#include <atomic>
struct xonce_flag
{
-a-a-a xonce_flag() noexcept = default;
private:
-a-a-a friend bool xcall_once( xonce_flag &, std::invocable auto );
-a-a-a using flag_t = std::atomic<signed char>;
-a-a-a flag_t m_flag = 0;
};
bool xcall_once( xonce_flag &xflag, std::invocable auto callable )
{
-a-a-a using namespace std;
-a-a-a xonce_flag::flag_t &flag = xflag.m_flag;
-a-a-a for( signed char ref = flag.load( memory_order_relaxed ); ; ) -a-a-a-a-a-a-a if( ref > 0 ) [[likely]]
-a-a-a-a-a-a-a {
-a-a-a-a-a-a-a-a-a-a-a std::atomic_thread_fence(std::memory_order_acquire);
-a-a-a-a-a-a-a-a-a-a-a return true;
-a-a-a-a-a-a-a }
-a-a-a-a-a-a-a else if( ref < 0 ) [[unlikely]]
-a-a-a-a-a-a-a {
-a-a-a-a-a-a-a-a-a-a-a flag.wait( ref, memory_order_relaxed ); -a-a-a-a-a-a-a-a-a-a-a ref = flag.load( memory_order_relaxed ); -a-a-a-a-a-a-a }
-a-a-a-a-a-a-a else if( flag.compare_exchange_strong( ref, -1, memory_order_relaxed, memory_order_relaxed ) ) [[likely]] -a-a-a-a-a-a-a-a-a-a-a break;
-a-a-a bool succ = true;
-a-a-a std::atomic_thread_fence(std::memory_order_acquire);
-a-a-a try
-a-a-a {
-a-a-a-a-a-a-a if constexpr( requires { (bool)callable(); } ) -a-a-a-a-a-a-a-a-a-a-a succ = (bool)callable();
-a-a-a-a-a-a-a else
-a-a-a-a-a-a-a-a-a-a-a callable();
-a-a-a }
-a-a-a catch( ... )
-a-a-a {
-a-a-a-a-a-a-a std::atomic_thread_fence(std::memory_order_release);
-a-a-a-a-a-a-a flag.store( 0, memory_order_relaxed );
-a-a-a-a-a-a-a flag.notify_one();
-a-a-a-a-a-a-a throw;
-a-a-a }
-a-a-a std::atomic_thread_fence(std::memory_order_release);
-a-a-a flag.store( (char)succ, memory_order_relaxed );
-a-a-a if( succ )
-a-a-a-a-a-a-a flag.notify_all();
-a-a-a else
-a-a-a-a-a-a-a flag.notify_one();
-a-a-a return succ;
}
You're making my code more complicated for nothing.
Am 03.01.2026 um 04:59 schrieb Chris M. Thomasson:
The (bool) cast wrt callable fiasco aside for a moment. This version
has the fences exactly where they need to be. Using C++ CAS with its
membar A for true and membar B for fail is RIPE for bugs anyway, well,
imvvho:
#pragma once
#include <concepts>
#include <atomic>
struct xonce_flag
{
-a-a-a xonce_flag() noexcept = default;
private:
-a-a-a friend bool xcall_once( xonce_flag &, std::invocable auto );
-a-a-a using flag_t = std::atomic<signed char>;
-a-a-a flag_t m_flag = 0;
};
bool xcall_once( xonce_flag &xflag, std::invocable auto callable )
{
-a-a-a using namespace std;
-a-a-a xonce_flag::flag_t &flag = xflag.m_flag;
-a-a-a for( signed char ref = flag.load( memory_order_relaxed ); ; )
-a-a-a-a-a-a-a if( ref > 0 ) [[likely]]
-a-a-a-a-a-a-a {
-a-a-a-a-a-a-a-a-a-a-a std::atomic_thread_fence(std::memory_order_acquire); >>
-a-a-a-a-a-a-a-a-a-a-a return true;
-a-a-a-a-a-a-a }
-a-a-a-a-a-a-a else if( ref < 0 ) [[unlikely]]
-a-a-a-a-a-a-a {
-a-a-a-a-a-a-a-a-a-a-a flag.wait( ref, memory_order_relaxed );
-a-a-a-a-a-a-a-a-a-a-a ref = flag.load( memory_order_relaxed );
-a-a-a-a-a-a-a }
-a-a-a-a-a-a-a else if( flag.compare_exchange_strong( ref, -1,
memory_order_relaxed, memory_order_relaxed ) ) [[likely]]
-a-a-a-a-a-a-a-a-a-a-a break;
-a-a-a bool succ = true;
-a-a-a std::atomic_thread_fence(std::memory_order_acquire);
-a-a-a try
-a-a-a {
-a-a-a-a-a-a-a if constexpr( requires { (bool)callable(); } )
-a-a-a-a-a-a-a-a-a-a-a succ = (bool)callable();
-a-a-a-a-a-a-a else
-a-a-a-a-a-a-a-a-a-a-a callable();
-a-a-a }
-a-a-a catch( ... )
-a-a-a {
-a-a-a-a-a-a-a std::atomic_thread_fence(std::memory_order_release);
-a-a-a-a-a-a-a flag.store( 0, memory_order_relaxed );
-a-a-a-a-a-a-a flag.notify_one();
-a-a-a-a-a-a-a throw;
-a-a-a }
-a-a-a std::atomic_thread_fence(std::memory_order_release);
-a-a-a flag.store( (char)succ, memory_order_relaxed );
-a-a-a if( succ )
-a-a-a-a-a-a-a flag.notify_all();
-a-a-a else
-a-a-a-a-a-a-a flag.notify_one();
-a-a-a return succ;
}
On 1/2/2026 8:02 PM, Bonita Montero wrote:
You're making my code more complicated for nothing.I think it makes it MUCH easier to read, and performs just as well.
The membars are exactly right where they need to be.
Am 03.01.2026 um 05:09 schrieb Chris M. Thomasson:
On 1/2/2026 8:02 PM, Bonita Montero wrote:
You're making my code more complicated for nothing.I think it makes it MUCH easier to read, and performs just as well.
The membars are exactly right where they need to be.
You're crazy.
On 1/2/2026 8:18 PM, Bonita Montero wrote:
Am 03.01.2026 um 05:09 schrieb Chris M. Thomasson:Na. (bool)callable, well, on the other hand... Shit happens.
On 1/2/2026 8:02 PM, Bonita Montero wrote:You're crazy.
You're making my code more complicated for nothing.I think it makes it MUCH easier to read, and performs just as well.
The membars are exactly right where they need to be.
Am 03.01.2026 um 20:43 schrieb Chris M. Thomasson:
On 1/2/2026 8:18 PM, Bonita Montero wrote:
Am 03.01.2026 um 05:09 schrieb Chris M. Thomasson:Na. (bool)callable, well, on the other hand... Shit happens.
On 1/2/2026 8:02 PM, Bonita Montero wrote:You're crazy.
You're making my code more complicated for nothing.I think it makes it MUCH easier to read, and performs just as well.
The membars are exactly right where they need to be.
That's while I intented this new kind of "once_flag"; to make
*that* possible. I can't understand any objections against
that; the interface is rather simple.
The callback is concept'ed with std::invocable auto, i.e it
must be callable without parameters; that makes the inter-
face even easier to understand.
That's while I intented this new kind of "once_flag"; to makeYou need to document it, before anybody needs to read the code to find
*that* possible. I can't understand any objections against
that; the interface is rather simple.
The callback is concept'ed with std::invocable auto, i.e it
must be callable without parameters; that makes the inter-
face even easier to understand.
out.
Am 04.01.2026 um 23:21 schrieb Chris M. Thomasson:
That's while I intented this new kind of "once_flag"; to makeYou need to document it, before anybody needs to read the code to find
*that* possible. I can't understand any objections against
that; the interface is rather simple.
The callback is concept'ed with std::invocable auto, i.e it
must be callable without parameters; that makes the inter-
face even easier to understand.
out.
It's only one line of code to find that out (if constexpr( ... )).
Am 04.01.2026 um 23:21 schrieb Chris M. Thomasson:
That's while I intented this new kind of "once_flag"; to makeYou need to document it, before anybody needs to read the code to find
*that* possible. I can't understand any objections against
that; the interface is rather simple.
The callback is concept'ed with std::invocable auto, i.e it
must be callable without parameters; that makes the inter-
face even easier to understand.
out.
It's only one line of code to find that out (if constexpr( ... )).
Oh no. If somebody wants to use it... I can see it now. The user asks
so what are the rules of callable? You say read the code. That's like
the opengroup saying read the code for a mutex impl to find out how it works. We don't need to document anything, just read the impl code.
Common man!
Am 05.01.2026 um 01:02 schrieb Chris M. Thomasson:
Oh no. If somebody wants to use it... I can see it now. The user asks
so what are the rules of callable? You say read the code. That's like
the opengroup saying read the code for a mutex impl to find out how it
works. We don't need to document anything, just read the impl code.
Common man!
The code is easy to read.
On 1/4/2026 4:04 PM, Bonita Montero wrote:
Am 05.01.2026 um 01:02 schrieb Chris M. Thomasson:
Oh no. If somebody wants to use it... I can see it now. The user
asks so what are the rules of callable? You say read the code.
That's like the opengroup saying read the code for a mutex impl to
find out how it works. We don't need to document anything, just read
the impl code. Common man!
The code is easy to read.
I can read it for sure. Yes I can understand it for sure. But, that (bool)callable() simply needs a clearly documented point. Fair enough?
Am 05.01.2026 um 03:10 schrieb Chris M. Thomasson:
On 1/4/2026 4:04 PM, Bonita Montero wrote:
Am 05.01.2026 um 01:02 schrieb Chris M. Thomasson:
Oh no. If somebody wants to use it... I can see it now. The user
asks so what are the rules of callable? You say read the code.
That's like the opengroup saying read the code for a mutex impl to
find out how it works. We don't need to document anything, just read
the impl code. Common man!
The code is easy to read.
I can read it for sure. Yes I can understand it for sure. But, that
(bool)callable() simply needs a clearly documented point. Fair enough?
Sorry, if you understand the rest this part is rather easy to read
if you can read concept'ed code.
Have you ever created documentation about your code before? I can
imagine you creating a doc on, say, opengroup for a mutex: https://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_mutex_lock.html
You say read the code, instead of providing a detailed explanation.
Am 05.01.2026 um 21:34 schrieb Chris M. Thomasson:
Have you ever created documentation about your code before? I can
imagine you creating a doc on, say, opengroup for a mutex:
https://pubs.opengroup.org/onlinepubs/9699919799/functions/
pthread_mutex_lock.html
You say read the code, instead of providing a detailed explanation.
I use Doxygen sometimes.
But you think you're an expert in parallel programming.
Then you should understand the code easily.
It's only 34 lines of code.
On 1/5/2026 9:07 PM, Bonita Montero wrote:
Am 05.01.2026 um 21:34 schrieb Chris M. Thomasson:
Have you ever created documentation about your code before? I can
imagine you creating a doc on, say, opengroup for a mutex:
https://pubs.opengroup.org/onlinepubs/9699919799/functions/
pthread_mutex_lock.html
You say read the code, instead of providing a detailed explanation.
I use Doxygen sometimes.
But you think you're an expert in parallel programming.
I have had to correct you in the past. Remember?
Then you should understand the code easily.
It's only 34 lines of code.
I do understand it! I even know how to make it use standalone fences.
The (bool)callable raised some red flags. If you doc that clearly,
well... Then, why not use it?
On 1/5/2026 9:07 PM, Bonita Montero wrote:
Am 05.01.2026 um 21:34 schrieb Chris M. Thomasson:
Have you ever created documentation about your code before? I can
imagine you creating a doc on, say, opengroup for a mutex:
https://pubs.opengroup.org/onlinepubs/9699919799/functions/
pthread_mutex_lock.html
You say read the code, instead of providing a detailed explanation.
I use Doxygen sometimes.
But you think you're an expert in parallel programming.
I have had to correct you in the past. Remember?
Then you should understand the code easily.
It's only 34 lines of code.
I do understand it! I even know how to make it use standalone fences.
The (bool)callable raised some red flags. If you doc that clearly,
well... Then, why not use it?
Clearly documented ...; dude that code is 34 only
Am 07.01.2026 um 01:56 schrieb Chris M. Thomasson:
On 1/5/2026 9:07 PM, Bonita Montero wrote:
Am 05.01.2026 um 21:34 schrieb Chris M. Thomasson:
Have you ever created documentation about your code before? I can
imagine you creating a doc on, say, opengroup for a mutex:
https://pubs.opengroup.org/onlinepubs/9699919799/functions/
pthread_mutex_lock.html
You say read the code, instead of providing a detailed explanation.
I use Doxygen sometimes.
But you think you're an expert in parallel programming.
I have had to correct you in the past. Remember?
Then you should understand the code easily.
It's only 34 lines of code.
I do understand it! I even know how to make it use standalone fences.
The (bool)callable raised some red flags. If you doc that clearly,
well... Then, why not use it?
Clearly documented ...; dude that code is 34 only !
I know the code is as is. But, well, what if somebody wants to use it
as a primitive, and wants to read a spec, instead of the code?
Am 07.01.2026 um 07:15 schrieb Chris M. Thomasson:
I know the code is as is. But, well, what if somebody wants to use it
as a primitive, and wants to read a spec, instead of the code?
The code doesn't need to be documented but the interface.
| Sysop: | Amessyroom |
|---|---|
| Location: | Fayetteville, NC |
| Users: | 54 |
| Nodes: | 6 (1 / 5) |
| Uptime: | 20:58:43 |
| Calls: | 742 |
| Files: | 1,218 |
| D/L today: |
6 files (8,794K bytes) |
| Messages: | 185,811 |
| Posted today: | 1 |