Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Win32: WaitOnAddress vs. WaitForSingleObject

1,125 views
Skip to first unread message

Bonita Montero

unread,
Jan 12, 2021, 2:52:26 PM1/12/21
to
I know this isn't a Windows-group.
But as the Win32-groups are dead I ask here.
There's an API called WakeByAddressSingle/ WakeByAddressSingle /
WakeByAddressAll. It is like a binary semaphore (Win32 event),
but it has a superior performance.
Look at this code:

#include <Windows.h>
#include <iostream>
#include <thread>
#include <vector>
#include <chrono>
#include <cstdint>

#pragma warning(disable: 6387)

using namespace std;
using namespace chrono;

int main()
{
using hrc_tp = time_point<high_resolution_clock>;
auto thrAddr = []( uint64_t count, void **waitOnThis, void **notifyThat )
{
void *cmp = nullptr;
for( ; count; --count )
{
while( *waitOnThis == cmp )
WaitOnAddress( waitOnThis, &cmp, sizeof(void *), INFINITE );
*waitOnThis = cmp;
*notifyThat = (void *)-1;
WakeByAddressSingle( notifyThat );
}
};
uint64_t const ROUNDS = 1'000'000;
void *waitA = (void *)-1,
*waitB = nullptr;
hrc_tp start = high_resolution_clock::now();
thread thrA( thrAddr, ROUNDS + 1, &waitA, &waitB ),
thrB( thrAddr, ROUNDS, &waitB, &waitA );
thrA.join();
thrB.join();
int64_t ns = duration_cast<nanoseconds>( high_resolution_clock::now() -
start ).count();
cout << "WaitOnAddress: " << (double)ns / ROUNDS << endl;
auto thrEvent = []( uint64_t count, HANDLE hEvtThis, HANDLE hEvtThat )
{
for( ; count; --count )
WaitForSingleObject( hEvtThis, INFINITE ),
SetEvent( hEvtThat );
};
HANDLE hEvtA = CreateEvent( nullptr, FALSE, TRUE, nullptr ),
hEvtB = CreateEvent( nullptr, FALSE, FALSE, nullptr );
start = high_resolution_clock::now();
thrA = thread( thrEvent, ROUNDS + 1, hEvtA, hEvtB );
thrB = thread( thrEvent, ROUNDS, hEvtB, hEvtA );
thrA.join();
thrB.join();
ns = duration_cast<nanoseconds>( high_resolution_clock::now() - start
).count();
cout << "WaitForSingleObject: " << (double)ns / ROUNDS << endl;
}

This outputs the following on my machine:
WaitOnAddress: 248.879
WaitForSingleObject: 10318.6
20 times the synchronization-performance like a kernel-event (binary
seamphore), this is really amazing. But does anyone know how this
works internally ? The following article is too vague to me:
https://devblogs.microsoft.com/oldnewthing/20160826-00/?p=94185

Bonita Montero

unread,
Jan 12, 2021, 2:53:19 PM1/12/21
to
> This outputs the following on my machine:
> WaitOnAddress: 248.879
> WaitForSingleObject: 10318.6
> 20 times the synchronization-performance ...

No, 40 times.

Bonita Montero

unread,
Jan 12, 2021, 3:30:38 PM1/12/21
to
Better use that, it doesn't require additional linker-settings:

#include <Windows.h>
#include <iostream>
#include <thread>
#include <vector>
#include <chrono>
#include <cstdint>

#pragma warning(disable: 6387)

using namespace std;
using namespace chrono;

int main()
{
using WOA_ADDR = BOOL (WINAPI *)( volatile VOID *, PVOID, SIZE_T, DWORD );
using WBAS_ADDR = void (WINAPI *)( PVOID );
HMODULE hmodSynch = LoadLibraryA( "API-MS-Win-Core-Synch-l1-2-0.dll" );
WOA_ADDR woa = (WOA_ADDR)GetProcAddress( hmodSynch,
"WaitOnAddress" );
WBAS_ADDR wbas = (WBAS_ADDR)GetProcAddress( hmodSynch,
"WakeByAddressSingle" );
using hrc_tp = time_point<high_resolution_clock>;
auto thrAddr = [&]( uint64_t count, void **waitOnThis, void **notifyThat )
{
void *cmp = nullptr;
for( ; count; --count )
{
while( *waitOnThis == cmp )
woa( waitOnThis, &cmp, sizeof(void *), INFINITE );
*waitOnThis = cmp;
*notifyThat = (void *)-1;
wbas( notifyThat );

Chris M. Thomasson

unread,
Jan 12, 2021, 4:02:03 PM1/12/21
to
On 1/12/2021 11:52 AM, Bonita Montero wrote:
> I know this isn't a Windows-group.
> But as the Win32-groups are dead I ask here.
> There's an API called WakeByAddressSingle/ WakeByAddressSingle /
> WakeByAddressAll. It is like a binary semaphore (Win32 event),
> but it has a superior performance.
> Look at this code:
[...]
> This outputs the following on my machine:
> WaitOnAddress: 248.879
> WaitForSingleObject: 10318.6
> 20 times the synchronization-performance like a kernel-event (binary
> seamphore), this is really amazing. But does anyone know how this
> works internally ? The following article is too vague to me:
> https://devblogs.microsoft.com/oldnewthing/20160826-00/?p=94185

Afaict, WaitOnAddress is akin to a futex. Its amazing to me that Windows
has this at all. It can be used to skip kernel calls. WaitOnAddress
should not be a direct kernel call on its fast path. However, when it
needs to wait, a slow path, it will use an underlying kernel object.
Most likely a large array of kernel objects. One way is hashing the
pointer address into a table of said wait objects. I have some older
code that does this. Iirc, called it multimutex.

For instance, a simple case, one can use a futex to add waiting ability
to a spinlock. Keep in mind that it can fail spuriously. So, a futex is
generally integrated into an existing spinlock using a loop.

I am not 100% sure, but WaitOnAddress sure seems like a futex.

Juha Nieminen

unread,
Jan 13, 2021, 3:30:42 AM1/13/21
to
Bonita Montero <Bonita....@gmail.com> wrote:
> using namespace std;

You are making the already-hard-to-read code even harder to read by avoiding
all the clarifying std:: prefixes. And for what? What exactly do you gain
from it? Not clarity, that's for certain.

Bonita Montero

unread,
Jan 13, 2021, 7:56:43 AM1/13/21
to
> You are making the already-hard-to-read code even harder to read by avoiding
> all the clarifying std:: prefixes. ...

That doesn't make the code hard to read.

Juha Nieminen

unread,
Jan 13, 2021, 8:45:17 AM1/13/21
to
It does, because you are mixing names from Windows.h and from the standard
library, and it's not as easy to see which names are from the latter by a
quick visual scan. Likewise names from the standard library get confused
with local variable names because they all look visually very similar and
there's nothing distinguishing them.

When names from the standard library are visually denoted with the "std::"
prefix, they stand out from all the other names, making it easier to make
the distinction, and to more quickly see which standard library utilities
are being used and where.

There is literally zero advantage in *not* using the prefix. There are
arguably disadvantages. Even if you think that those disadvantages are
minuscule, they are still disadvantages, and there's absolutely no reason
to have them, no matter how small you think they may be.

This especially so when you are posting code to a forum where you are
asking other people to examine your code and understand what it's doing.
You should make your code as easy for others to understand as possible.
Clarity of your own code is your responsibility, not the responsibility
of the people you are asking.

Bonita Montero

unread,
Jan 13, 2021, 10:30:31 AM1/13/21
to
>> That doesn't make the code hard to read.

> It does, because you are mixing names from Windows.h and from the standard
> library, and it's not as easy to see which names are from the latter by a
> quick visual scan. ...

Your point is absolutely compulsive.
Someone who programs C++ should know the standard library.

Haven't read the rest of your nonsense.

Nikolaj Lazic

unread,
Jan 13, 2021, 4:30:01 PM1/13/21
to
Dana Wed, 13 Jan 2021 16:30:14 +0100, Bonita Montero <Bonita....@gmail.com> napis'o:
Maybe you should at least try to...

Paavo Helde

unread,
Jan 13, 2021, 5:09:11 PM1/13/21
to
13.01.2021 17:30 Bonita Montero kirjutas:
>>> That doesn't make the code hard to read.
>
>> It does, because you are mixing names from Windows.h and from the
>> standard
>> library, and it's not as easy to see which names are from the latter by a
>> quick visual scan. ...
>
> Your point is absolutely compulsive.
> Someone who programs C++ should know the standard library.

And someone who includes Windows.h should know all the half zillion
names it declares, right?

You are forgetting a tiny point: computer code is not meant as an exam
or test for readers' ability to remember and recognize tons of names
from various large interfaces. The purpose of the source code is to
present a working algorithm in a way that is as easy as possible for
people to understand and modify.

Otherwise, we could just compile our work into machine code and forget
about source code repositories.

Chris M. Thomasson

unread,
Jan 14, 2021, 1:51:51 AM1/14/21
to
On 1/12/2021 11:52 AM, Bonita Montero wrote:
> I know this isn't a Windows-group.
> But as the Win32-groups are dead I ask here.
> There's an API called WakeByAddressSingle/ WakeByAddressSingle /
> WakeByAddressAll. It is like a binary semaphore (Win32 event),
> but it has a superior performance.
> Look at this code:
[...]
> This outputs the following on my machine:
> WaitOnAddress: 248.879
> WaitForSingleObject: 10318.6
> 20 times the synchronization-performance like a kernel-event (binary
> seamphore), this is really amazing. But does anyone know how this
> works internally ? The following article is too vague to me:
> https://devblogs.microsoft.com/oldnewthing/20160826-00/?p=94185

Ivho, a fairer test would be to create a mutex using the "Windows" futex
thing, vs one that uses a normal kernel object for the slow path.

You can use a benaphore or any other mutex you want vs futex as a test
vector.

Chris M. Thomasson

unread,
Jan 14, 2021, 1:58:38 AM1/14/21
to
On 1/12/2021 11:52 AM, Bonita Montero wrote:
> I know this isn't a Windows-group.
> But as the Win32-groups are dead I ask here.
> There's an API called WakeByAddressSingle/ WakeByAddressSingle /
> WakeByAddressAll. It is like a binary semaphore (Win32 event),
> but it has a superior performance.
> Look at this code:
[...]
> This outputs the following on my machine:
> WaitOnAddress: 248.879
> WaitForSingleObject: 10318.6
> 20 times the synchronization-performance like a kernel-event (binary
> seamphore), this is really amazing. But does anyone know how this
> works internally ? The following article is too vague to me:
> https://devblogs.microsoft.com/oldnewthing/20160826-00/?p=94185

Read all:

https://www.kernel.org/doc/ols/2002/ols2002-pages-479-495.pdf

Juha Nieminen

unread,
Jan 14, 2021, 2:38:12 AM1/14/21
to
Bonita Montero <Bonita....@gmail.com> wrote:
>>> That doesn't make the code hard to read.
>
>> It does, because you are mixing names from Windows.h and from the standard
>> library, and it's not as easy to see which names are from the latter by a
>> quick visual scan. ...
>
> Your point is absolutely compulsive.
> Someone who programs C++ should know the standard library.

Which is exactly what I was saying: You are putting expectations on people
here, while trying to ask something from them. Instead of making your code
as easy as possible to read and understand for people here, you are
selfishly putting rather presumptuous and egotistical expectations on
others, while still asking for their help.

When you are asking others for help or opinions, do the work to make their
task as easy as possible.

> Haven't read the rest of your nonsense.

Which is the archetypical response of a petty infantile person who cannot
have a rational conversation and present rational arguments.

I'll take that as "you are right and I'm wrong, but I'm too petulant and
childish and stubborn to admit it, therefore I'll just act smug and in
a hostile manner to compensate for my insecurities."

Ian Collins

unread,
Jan 14, 2021, 4:10:57 AM1/14/21
to
On 14/01/2021 20:37, Juha Nieminen wrote:
> Bonita Montero <Bonita....@gmail.com> wrote:
>>>> That doesn't make the code hard to read.
>>
>>> It does, because you are mixing names from Windows.h and from the standard
>>> library, and it's not as easy to see which names are from the latter by a
>>> quick visual scan. ...
>>
>> Your point is absolutely compulsive.
>> Someone who programs C++ should know the standard library.
>
> Which is exactly what I was saying: You are putting expectations on people
> here, while trying to ask something from them. Instead of making your code
> as easy as possible to read and understand for people here, you are
> selfishly putting rather presumptuous and egotistical expectations on
> others, while still asking for their help.
>
> When you are asking others for help or opinions, do the work to make their
> task as easy as possible.
>
>> Haven't read the rest of your nonsense.
>
> Which is the archetypical response of a petty infantile person who cannot
> have a rational conversation and present rational arguments.

You are expecting rational arguments from someone who can't even work
out how to quote on Usenet?

There are more productive ways to spend your time.

--
Ian.

Bonita Montero

unread,
Jan 14, 2021, 4:36:14 AM1/14/21
to
> And someone who includes Windows.h should know all the half zillion
> names it declares, right?

No, but if you you know the standard libary you can easily
distinguish between standard libary functions and WinAPI
-functions.

Bonita Montero

unread,
Jan 14, 2021, 4:37:02 AM1/14/21
to
>> Your point is absolutely compulsive.
>> Someone who programs C++ should know the standard library.

> Which is exactly what I was saying: You are putting expectations on people
> here, while trying to ask something from them. Instead of making your code
> as easy as possible to read and understand for people here, you are
> selfishly putting rather presumptuous and egotistical expectations on
> others, while still asking for their help.

You're compulsive.

Juha Nieminen

unread,
Jan 14, 2021, 9:22:00 AM1/14/21
to
Well, don't expect me to help you with your questions if you don't put
any effort into it and have such an attitude.

And if you don't care if people answer your questions or not, why are
you even bothering to ask them?

Bonita Montero

unread,
Jan 14, 2021, 10:12:00 AM1/14/21
to
>> You're compulsive.

> Well, don't expect me to help you with your questions if you don't put
> any effort into it and have such an attitude.
> And if you don't care if people answer your questions or not, why are
> you even bothering to ask them?

Your attitude has nothing to do with more readable code but is just
nonsense-compulsiveness. And further you're not able to give an answer
on my question anyway.

Alf P. Steinbach

unread,
Jan 14, 2021, 10:47:44 AM1/14/21
to
On 13.01.2021 14:44, Juha Nieminen wrote:
> Bonita Montero <Bonita....@gmail.com> wrote:
>>> You are making the already-hard-to-read code even harder to read by avoiding
>>> all the clarifying std:: prefixes. ...
>>
>> That doesn't make the code hard to read.
>
> It does, because you are mixing names from Windows.h and from the standard
> library, and it's not as easy to see which names are from the latter by a
> quick visual scan.

Oh that's easy, not a problem, Juha.

The Windows API function names are Pascal camel-case starting with
uppercase letter, like `WaitForSingleObject`.

The standard library function names are lowercase, usually using the
snake case convention with underscores as word separators, like
`duration_cast` and `high_resolution_clock`.


> Likewise names from the standard library get confused
> with local variable names because they all look visually very similar and
> there's nothing distinguishing them.

That's not a problem for me with this code.

It could be a problem in some other code, e.g. code using the name
`high_resolution_clock` as the name of a local variable.

But then it's much easier to just fix the naming than to spray noisy
`std::` prefixes all over that code, and even easier: use an editor with
good syntax coloring, i.e. modern tools.

[snip]
> Clarity of your own code is your responsibility, not the responsibility
> of the people you are asking.

What constitutes clarity is very much arguable.

There's a good chance that your view is in a minority (it could also be
a majority, I don't know). Should Bonity cater to a specific subset of
the readership, and why that particular subset? I think she should just
do what feels right to her.


- Alf

Chris M. Thomasson

unread,
Jan 14, 2021, 6:10:50 PM1/14/21
to
On 1/12/2021 11:52 AM, Bonita Montero wrote:
> I know this isn't a Windows-group.
> But as the Win32-groups are dead I ask here.
> There's an API called WakeByAddressSingle/ WakeByAddressSingle /
> WakeByAddressAll. It is like a binary semaphore (Win32 event),
> but it has a superior performance.
> Look at this code:
[...]

Also, read all of:

https://akkadia.org/drepper/futex.pdf

Chris M. Thomasson

unread,
Jan 14, 2021, 7:15:32 PM1/14/21
to
Can you run this Bonita? Fwiw, it would be my first time using a Windows
Futex! lol:
______________________________________
#include <iostream>
#include <thread>
#include <functional>

#define WIN32_LEAN_AND_MEAN
#include <Windows.h>


#define CT_L2_ALIGNMENT 128
#define CT_THREADS 32
#define CT_ITERS 6666666


struct ct_futex_mutex
{
ULONG alignas(CT_L2_ALIGNMENT) m_state;

ct_futex_mutex() : m_state(0)
{

}

void lock()
{
if (InterlockedExchange(&m_state, 1))
{
while (InterlockedExchange(&m_state, 2))
{
ULONG cmp = 2;
WaitOnAddress(&m_state, &cmp, sizeof(ULONG), INFINITE);
}
}
}

void unlock()
{
if (InterlockedExchange(&m_state, 0) == 2)
{
WakeByAddressSingle(&m_state);
}
}
};


struct ct_shared
{
ct_futex_mutex m_mtx;
unsigned long m_count;

ct_shared() : m_count(0) {}

~ct_shared()
{
if (m_count != 0)
{
std::cout << "counter is totally fubar!\n";
}
}
};


void ct_thread(ct_shared& shared)
{
for (unsigned long i = 0; i < CT_ITERS; ++i)
{
shared.m_mtx.lock();
++shared.m_count;
shared.m_mtx.unlock();

shared.m_mtx.lock();
--shared.m_count;
shared.m_mtx.unlock();
}
}


int main()
{
std::thread threads[CT_THREADS];

std::cout << "Starting up...\n";

{
ct_shared shared;

for (unsigned long i = 0; i < CT_THREADS; ++i)
{
threads[i] = std::thread(ct_thread, std::ref(shared));
}

std::cout << "Running...\n";

for (unsigned long i = 0; i < CT_THREADS; ++i)
{
threads[i].join();
}
}

std::cout << "Completed!\n";

return 0;
}
______________________________________


Afaict, it should work. I have not tested this in Relacy yet.

Bonita Montero

unread,
Jan 15, 2021, 2:57:07 AM1/15/21
to
> Afaict, it should work. I have not tested this in Relacy yet.

It works. And it's not necessary to test such simple code
with Relacy or whatever.

I yesterday wrote a portable semaphore-class:

// fsemaphore.h

#pragma once
#if defined(_MSC_VER)
#include <Windows.h>
#elif defined(__gnu_linux__)
#include <unistd.h>
#include <linux/futex.h>
#include <stdint.h>
#include <sys/time.h>
#include <sys/syscall.h>
#endif
#include <atomic>
#include <cstdint>
#include <system_error>

struct fsemaphore
{
fsemaphore();
~fsemaphore();
fsemaphore( fsemaphore const & ) = delete;
void operator =( fsemaphore const & ) = delete;
bool wait();
bool release();
void forced_wait();
void forced_release();

private:
#if defined(_MSC_VER)
bool m_isCounter;
std::atomic<std::uint32_t> m_semCounter;
HANDLE m_hSemaphore;
using WOA_ADDR = BOOL (WINAPI *)( volatile VOID *Address, PVOID
CompareAddress, SIZE_T AddressSize, DWORD dwMilliseconds );
using WBAS_ADDR = void (WINAPI *)( PVOID Address );
static
WOA_ADDR waitOnAddress;
static
WBAS_ADDR wakeByAddressSingle;
#elif defined(__unix__)
static int futex( uint32_t *uaddr, int futex_op, uint32_t val, timespec
const *timeout, uint32_t *uaddr2, uint32_t val3 );
std::atomic<std::uint32_t> m_semCounter;
#endif
};

inline
void fsemaphore::forced_wait()
{
while( !wait() );
}

inline
void fsemaphore::forced_release()
{
while( !release() );
}

// fsemaphore.cpp

#include "fsemaphore.h"

#if defined(_MSC_VER)
fsemaphore::WOA_ADDR fsemaphore::waitOnAddress = nullptr;
fsemaphore::WBAS_ADDR fsemaphore::wakeByAddressSingle = nullptr;

fsemaphore::fsemaphore()
{
using namespace std;
if( waitOnAddress == (WOA_ADDR)-1 )
goto useSem;
if( !waitOnAddress )
{
HMODULE hmodSynch = LoadLibraryA( "API-MS-Win-Core-Synch-l1-2-0.dll" );
if( hmodSynch == NULL )
goto useSemErr;
waitOnAddress = (WOA_ADDR) GetProcAddress( hmodSynch,
"WaitOnAddress" );
wakeByAddressSingle = (WBAS_ADDR)GetProcAddress( hmodSynch,
"WakeByAddressSingle" );
if( !waitOnAddress || !wakeByAddressSingle )
goto useSemErr;
}
m_isCounter = true;
m_semCounter.store( 0, memory_order_relaxed );
return;
useSemErr:
waitOnAddress = (WOA_ADDR)-1;
useSem:
m_isCounter = false;
if( !(m_hSemaphore = CreateSemaphore( nullptr, 0, 0x7FFFFFFF, nullptr )) )
throw system_error( error_code( (int)GetLastError(), system_category()
), "can't create Win32 semaphore for fsemaphore-object" );
}

fsemaphore::~fsemaphore()
{
if( !m_isCounter )
CloseHandle( m_hSemaphore );
}

bool fsemaphore::wait()
{
using namespace std;
if( m_isCounter )
for( ; ; )
{
uint32_t cmp = m_semCounter;
if( cmp && m_semCounter.compare_exchange_weak( cmp, cmp - 1,
memory_order_acquire, memory_order_relaxed ) )
return true;
cmp = 0;
waitOnAddress( &m_semCounter, &cmp, sizeof m_semCounter, INFINITE );
}
else
return WaitForSingleObject( m_hSemaphore, INFINITE ) == WAIT_OBJECT_0;
}

bool fsemaphore::release()
{
using namespace std;
if( m_isCounter )
{
m_semCounter.fetch_add( 1, memory_order_relaxed );
wakeByAddressSingle( &m_semCounter );
return true;
}
else
return ReleaseSemaphore( m_hSemaphore, 1, nullptr );
}

#elif defined(__gnu_linux__)

fsemaphore::fsemaphore()
{
m_semCounter.store( 0, std::memory_order_relaxed );
}

fsemaphore::~fsemaphore()
{
}

bool fsemaphore::wait()
{
using namespace std;
for( ; ; )
{
uint32_t cmp = m_semCounter;
if( cmp && m_semCounter.compare_exchange_weak( cmp, cmp - 1,
memory_order_acquire, memory_order_relaxed ) )
return true;
cmp = 0;
if( futex( (uint32_t *)&m_semCounter, FUTEX_WAIT, 0, nullptr, 0, 0 )
!= 0 )
return false;
}
}

bool fsemaphore::release()
{
m_semCounter.fetch_add( 1, std::memory_order_relaxed );
return futex( (uint32_t *)&m_semCounter, FUTEX_WAKE, 1, nullptr, 0, 0 )
== 1;
}

int fsemaphore::futex( uint32_t *uaddr, int futex_op, uint32_t val,
timespec const *timeout, uint32_t *uaddr2, uint32_t val3 )
{
return syscall( SYS_futex, uaddr, futex_op, val, timeout, uaddr2, val3 );
}

#endif

Chris M. Thomasson

unread,
Jan 15, 2021, 4:24:10 AM1/15/21
to
On 1/14/2021 11:56 PM, Bonita Montero wrote:
>> Afaict, it should work. I have not tested this in Relacy yet.
>
> It works. And it's not necessary to test such simple code
> with Relacy or whatever.

It does not hurt. Iirc, Relacy has futex simulation. I need to ask the
Author.


> I yesterday wrote a portable semaphore-class:
[...]
> bool fsemaphore::release()
> {
>     m_semCounter.fetch_add( 1, std::memory_order_relaxed );
>     return futex( (uint32_t *)&m_semCounter, FUTEX_WAKE, 1, nullptr, 0,
> 0 ) == 1;
> }

I am wondering why you are calling into the futex (e.g., syscall) every
time you release the semaphore? Usually, we want to avoid calling into
anything to do with the OS. So, we can say that calling futex is when we
actually NEED to wait/signal/broadcast. Not to be called all the time.
For a semaphore implementation, a benaphore is very nice and does not
use a futex. Its a simple layer on top of a os provided semaphore. They
really shine when the os semaphore is "slow".

Iirc, there was a strange semaphore out there that used a futex, and a
wait bit. Around 18 years ago. I cannot remember where I saw it, but I
do remember very vague parts of it.

Bonita Montero

unread,
Jan 15, 2021, 4:52:18 AM1/15/21
to
>> bool fsemaphore::release()
>> {
>>      m_semCounter.fetch_add( 1, std::memory_order_relaxed );
>>      return futex( (uint32_t *)&m_semCounter, FUTEX_WAKE, 1, nullptr,
>> 0, 0 ) == 1;
>> }

> I am wondering why you are calling into the futex (e.g., syscall) every
> time you release the semaphore? Usually, we want to avoid calling into
> anything to do with the OS. So, we can say that calling futex is when we
> actually NEED to wait/signal/broadcast. Not to be called all the time.
> For a semaphore implementation, a benaphore is very nice and does not
> use a futex. Its a simple layer on top of a os provided semaphore. They
> really shine when the os semaphore is "slow".

Ok, when I'm incrementing vom zero to one, it's not necessary.

Bonita Montero

unread,
Jan 15, 2021, 4:54:20 AM1/15/21
to
No, i was right initially; futex has to be called every time since
it's impossible to notice a waiting thread.


Chris M. Thomasson

unread,
Jan 15, 2021, 5:22:45 AM1/15/21
to
Humm... It would be interesting to test the futex semaphore vs one that
uses an actual windows semaphore:
__________________________
// using windows semaphore for slowpath
struct ct_benaphore
{
std::atomic<long> m_state;
HANDLE m_waitset;

ct_benaphore(long state) :
m_state(state),
m_waitset(CreateSemaphore(nullptr, 0, LONG_MAX, nullptr))
{
if (! m_waitset) throw; // oh shit!
}

~ct_benaphore()
{
CloseHandle(m_waitset);
}

void inc()
{
if (m_state.fetch_add(1, std::memory_order_release) < 0)
{
ReleaseSemaphore(m_waitset, 1, nullptr);
}
}

void dec()
{
if (m_state.fetch_sub(1, std::memory_order_acquire) < 1)
{
WaitForSingleObject(m_waitset, INFINITE);
}
}
};
__________________________

Juha Nieminen

unread,
Jan 15, 2021, 5:25:57 AM1/15/21
to
Alf P. Steinbach <alf.p.stein...@gmail.com> wrote:
>> Likewise names from the standard library get confused
>> with local variable names because they all look visually very similar and
>> there's nothing distinguishing them.
>
> That's not a problem for me with this code.

Congratulations.

> It could be a problem in some other code, e.g. code using the name
> `high_resolution_clock` as the name of a local variable.
>
> But then it's much easier to just fix the naming than to spray noisy
> `std::` prefixes all over that code, and even easier: use an editor with
> good syntax coloring, i.e. modern tools.

So instead of making the code easier to read regardless of which editor
or, in this case, usenet news reader is being used, you instead rely on
software to highlight names from the standard library with a different
color from other names, and if someone doesn't use such a "modern tool"
then it's their fault?

Weren't you the one who stubborningly insisted in always having an
#include in your code that you post here that uses some custom header
file of yours for completely unneeded things (especially here)?
I see where your attitude is coming from. You, too, seem to be the kind
of person who expects others to accommodate to your conding quirks
instead of making it as easy as possible for others to read your code
and answer your questions.

If you are writing a program for some personal project, then do whatever
floats your boat. However, when you are asking other people in a
public forum to help you with a problem in your code, you shouldn't
expect them to conform to and understand your personal quirks. You should
put some work into making your question as clear and understandable and
possible, and drop the "if you don't understand this then you are stupid"
attitude, which is incredibly arrogant when asking other people for help.

spudisno...@grumpysods.com

unread,
Jan 15, 2021, 5:37:09 AM1/15/21
to
On Fri, 15 Jan 2021 10:25:41 +0000 (UTC)
Juha Nieminen <nos...@thanks.invalid> wrote:
>I see where your attitude is coming from. You, too, seem to be the kind
>of person who expects others to accommodate to your conding quirks
>instead of making it as easy as possible for others to read your code
>and answer your questions.

You've only just noticed? :)

Bonita Montero

unread,
Jan 15, 2021, 7:29:28 AM1/15/21
to
> I see where your attitude is coming from. You, too, seem to be the kind
> of person who expects others to accommodate to your conding quirks
> ...

You're doing that yourself at the moment.
I think the code is more readable than with the std::-srpaying.

Juha Nieminen

unread,
Jan 15, 2021, 9:21:38 AM1/15/21
to
Bonita Montero <Bonita....@gmail.com> wrote:
> I think the code is more readable than with the std::-srpaying.

Care to present an actual argument of why?

I explained *why* using the prefix make the code more readable.
You have not given a single argument why the opposite would be true.
You have merely presented an assertion.

Ah, but you didn't read my arguments, instead smugly announcing as much,
like a petulant child.

If you are using, let's say, the libpng library, where almost every name
is prefixed with "png_", do you think that the use of this prefix makes
the code more or less readable? Do you whine about having to write it in
front of every name, and go on to create preprocessor macros to create
names without that "png_" prefix?

If not, then what makes "std::" so much different? Why does "png_" not
make the code less readable, while "std::" does? What's the crucial
difference? The two colons instead of one underscore? Is that the problem?
Two colons = less readable, one underscore = more readable?

During the past 20 or so years I have seen dozens and dozens, probably
over a hundred different people whine about the "std::" prefix and how it
allegedly makes the code less readable. To this day I have not seen a
single rational argument presented why, or why that particular prefix
is so different from the myriads of other prefixes used in myriads of
libraries. Likewise I have never seen a good counter-argument to my
arguments for the use of the prefix, other than mere assertions.

spudisno...@grumpysods.com

unread,
Jan 15, 2021, 9:32:12 AM1/15/21
to
On Fri, 15 Jan 2021 14:21:19 +0000 (UTC)
Juha Nieminen <nos...@thanks.invalid> wrote:
>During the past 20 or so years I have seen dozens and dozens, probably
>over a hundred different people whine about the "std::" prefix and how it
>allegedly makes the code less readable. To this day I have not seen a

To some it makes the APIs used clearer, to others its visual noise which is
annoying. There is no right answer, its subjective so your argument is
pointless. You might as well ask why some people prefer rock music instead
of dance - they just do.

Bonita Montero

unread,
Jan 15, 2021, 10:54:41 AM1/15/21
to
>> I think the code is more readable than with the std::-srpaying.

> Care to present an actual argument of why?

Because it's redundant information you need.
And as Alf said it's easy to distinguish between the WinAPI and
between the standard-APIs. And of course no one would implement
a C++-library that uses standard-library names you can almost
always do "using namespace std".

> I explained *why* using the prefix make the code more readable.

No, you don't; that's just your personal compulsive taste and
you want to dictate your taste to others.

Won't read the rest of your nonsense.

Jorgen Grahn

unread,
Jan 15, 2021, 3:59:25 PM1/15/21
to
On Fri, 2021-01-15, Juha Nieminen wrote:
> Bonita Montero <Bonita....@gmail.com> wrote:
>> I think the code is more readable than with the std::-srpaying.
>
> Care to present an actual argument of why?

I suggest to drop the issue.

For what it's worth, me and everyone I've worked with in recent years
do it your way. But I think I've mentioned that before.

/Jorgen

--
// Jorgen Grahn <grahn@ Oo o. . .
\X/ snipabacken.se> O o .

Chris M. Thomasson

unread,
Jan 15, 2021, 8:56:51 PM1/15/21
to
On 1/15/2021 6:21 AM, Juha Nieminen wrote:
> Bonita Montero <Bonita....@gmail.com> wrote:
>> I think the code is more readable than with the std::-srpaying.
>
> Care to present an actual argument of why?
[...]

> Do you whine about having to write it in
> front of every name, and go on to create preprocessor macros to create
> names without that "png_" prefix?

Oh wow. I actually remember, around two decades ago, reading some code
where the author actually did that to pthreads. It made me laugh. Iirc,
it was something like:

#define tcreate pthread_create
#define tjoin pthread_join

ect...


wow.

[...]

Chris M. Thomasson

unread,
Jan 15, 2021, 11:13:43 PM1/15/21
to
Humm... should probably add in a check to make sure that state is > -1:

assert(m_state.load(std::memory_order_relaxed) > -1);

humm... ;^)

Chris M. Thomasson

unread,
Jan 16, 2021, 12:12:20 AM1/16/21
to
On 1/15/2021 1:54 AM, Bonita Montero wrote:
> Am 15.01.2021 um 10:52 schrieb Bonita Montero:
>>>> bool fsemaphore::release()
>>>> {
>>>>      m_semCounter.fetch_add( 1, std::memory_order_relaxed );
>>>>      return futex( (uint32_t *)&m_semCounter, FUTEX_WAKE, 1,
>>>> nullptr, 0, 0 ) == 1;
>>>> }

also, you need to make sure that releasing a semaphore has at least
release memory order semantics. You used relaxed. Now, sometimes a
syscall can act like a "membar", but its not guaranteed.

Incrementing a semaphore needs to have at least release semantics.

Decrementing a semaphore must ensure at least acquire semantics.

This fits into using a binsema as a mutex where locking a mutex needs an
acquire membar, and unlocking needs a release. Where a binsema with an
initial state of 1, used as a mutex has a decrement to acquire, and an
increment to release.

Bonita Montero

unread,
Jan 16, 2021, 1:45:39 AM1/16/21
to
> also, you need to make sure that releasing a semaphore has at least
> release memory order semantics. You used relaxed. Now, sometimes a
> syscall can act like a "membar", but its not guaranteed.

Isn't needed because of the syscall.

Öö Tiib

unread,
Jan 16, 2021, 5:13:02 AM1/16/21
to
On Friday, 15 January 2021 at 22:59:25 UTC+2, Jorgen Grahn wrote:
> On Fri, 2021-01-15, Juha Nieminen wrote:
> > Bonita Montero <Bonita....@gmail.com> wrote:
> >> I think the code is more readable than with the std::-srpaying.
> >
> > Care to present an actual argument of why?
> I suggest to drop the issue.
>
> For what it's worth, me and everyone I've worked with in recent years
> do it your way. But I think I've mentioned that before.

Yes large projects tend to be explicit indeed. How to know if it
is boost::numeric::ublas::vector, boost::container::pmr::vector,
boost::interprocess::vector or some other like that? Just be
explicit. Someone does not want to be explicit saying that if you hover
with mouse in some kind of visual studio over the name then it shows
long form in tooltip? Just don't hire him ... problem solved.
Pointless to argue and to waste time.

Bonita Montero

unread,
Jan 16, 2021, 6:09:07 AM1/16/21
to
> Yes large projects tend to be explicit indeed. How to know if it
> is boost::numeric::ublas::vector, boost::container::pmr::vector,
> boost::interprocess::vector or some other like that? Just be
> explicit. Someone does not want to be explicit saying that if you hover
> with mouse in some kind of visual studio over the name then it shows
> long form in tooltip? Just don't hire him ... problem solved.
> Pointless to argue and to waste time.

That's just a matter of taste.

Öö Tiib

unread,
Jan 16, 2021, 10:56:51 AM1/16/21
to
Yes, and it is pointless to take someone with too different taste
into team. Resulting code base will look inconsistent garbage and
trying to achieve more consistency will waste precious time.

Bonita Montero

unread,
Jan 16, 2021, 12:17:54 PM1/16/21
to
But there's no better style here - but just different tastess.

Chris M. Thomasson

unread,
Jan 16, 2021, 4:35:55 PM1/16/21
to
Bonita Montero wrote:

> bool fsemaphore::release()
> {
> m_semCounter.fetch_add( 1, std::memory_order_relaxed );
> return futex( (uint32_t *)&m_semCounter, FUTEX_WAKE, 1, nullptr,
> 0, 0 ) == 1;
> }

But, either way, it is in the wrong place. A release barrier must be
placed _before_ the atomic logic that actually increments the semaphore.
So for releasing, or basically incrementing a semaphore, the release
membar must be:

using explicit standalone C++11 membars here for clarity. It shows
correct placement for semaphore memory order operations:
__________________________
// using windows semaphore for slowpath
struct ct_benaphore
{
std::atomic<long> m_state;
HANDLE m_waitset;

ct_benaphore(long state) :
m_state(state),
m_waitset(CreateSemaphore(nullptr, 0, LONG_MAX, nullptr))
{
if (! m_waitset) throw; // oh shit!
}

~ct_benaphore()
{
CloseHandle(m_waitset);
}

void inc()
{
std::atomic_thread_fence(std::memory_order_release);

if (m_state.fetch_add(1, std::memory_order_relaxed) < 0)
{
ReleaseSemaphore(m_waitset, 1, nullptr);
}
}

void dec()
{
if (m_state.fetch_sub(1, std::memory_order_relaxed) < 1)
{
WaitForSingleObject(m_waitset, INFINITE);
}

std::atomic_thread_fence(std::memory_order_acquire);
}
};
__________________________


So, your "membar" is in the wrong place, assuming syscall acts like a
barrier at all... Sometimes they can. Now, an acquire barrier needs to
be placed _after_ the atomic logic that decrements a semaphore.

Öö Tiib

unread,
Jan 16, 2021, 5:55:02 PM1/16/21
to
Yes there are no universal better. For you it is better to write ambiguous
code because of 5 characters less to type. For me it is better when such
people are not in my team. Tastes vary.

Keith Thompson

unread,
Jan 16, 2021, 6:36:10 PM1/16/21
to
Öö Tiib <oot...@hot.ee> writes:
[...]
> Yes, and it is pointless to take someone with too different taste
> into team. Resulting code base will look inconsistent garbage and
> trying to achieve more consistency will waste precious time.

At the risk of stating the obvious, it depends on whether someone with
different taste is willing to be flexible. For example, I have strong
opinions about brace placement and indentation (and std::), but in a
work environment I set them aside and conform to coding standards and
existing conventions.

--
Keith Thompson (The_Other_Keith) Keith.S.T...@gmail.com
Working, but not speaking, for Philips Healthcare
void Void(void) { Void(); } /* The recursive call of the void */

Bonita Montero

unread,
Jan 17, 2021, 3:48:23 AM1/17/21
to
> Yes there are no universal better. For you it is better to write ambiguous
> code because of 5 characters less to type. For me it is better when such
> people are not in my team. Tastes vary.

As Alf correctly stated here there aren't any ambiguities here.

Juha Nieminen

unread,
Jan 17, 2021, 4:03:35 AM1/17/21
to
Bonita Montero <Bonita....@gmail.com> wrote:
>>> I think the code is more readable than with the std::-srpaying.
>
>> Care to present an actual argument of why?
>
> Because it's redundant information you need.

The language is *full* of repetition and "redundant" information.
How many semi-colons do you write in your source code? How many
parentheses and curly braces? How many times do you write keywords
like 'int', 'for' or 'return'?

I don't see you complaining about the sheer amount of semicolons
you need to write, and trying to get around that problem.
If you use a library like libpng, do you go your way to try to
avoid having to write all those 'png_' prefixes? If not, why not?

What makes 'std::' so special that you religiously avoid it?

> Won't read the rest of your nonsense.

Of course not. Just goes to show how petulant you are.

I'll take that as a tacit admission of defeat.

Juha Nieminen

unread,
Jan 17, 2021, 4:13:29 AM1/17/21
to
Chris M. Thomasson <chris.m.t...@gmail.com> wrote:
> Oh wow. I actually remember, around two decades ago, reading some code
> where the author actually did that to pthreads. It made me laugh. Iirc,
> it was something like:
>
> #define tcreate pthread_create
> #define tjoin pthread_join

To be fair, this might have more to do with trying to make code as short as
possible, rather that avoiding a particular prefix.

Not that making code as short as possible is any better.

I think it's an interesting psychological phenomenon why so many beginner
programmers, and even not-so-beginner ones, always try to make code,
especially variable and function names, as short as possible.

I see that kind of code quite a lot in my work, where I oftentimes need to
further develop and use code made by others. This seems to be quite
common with a particular kind of C programmers, who will often shorten
names so much that they may become almost indecipherable and make the
code harder to read (especially when many similarly named variables are
being used). Like for example naming something 'evts' instead of 'events',
'err' instead of 'error', and so on.

Although, POSIX (and the unix world in general) is full of this, so it's
perhaps not a great mystery where they have learned this kind of coding.

Juha Nieminen

unread,
Jan 17, 2021, 4:21:36 AM1/17/21
to
?? Tiib <oot...@hot.ee> wrote:
> Yes large projects tend to be explicit indeed. How to know if it
> is boost::numeric::ublas::vector, boost::container::pmr::vector,
> boost::interprocess::vector or some other like that? Just be
> explicit. Someone does not want to be explicit saying that if you hover
> with mouse in some kind of visual studio over the name then it shows
> long form in tooltip? Just don't hire him ... problem solved.
> Pointless to argue and to waste time.

In a particular, relatively popular open source project I was involved with
some years ago, which had started some time in the mid-90's, at some point
in the early 2000's there was this lead developer who was absolutely
obsessed about not using namespaces, and often wrote long rants about how
namespaces are evil, and made (to be frank, rather stupid) arguments about
how it's actually *better* to always use "using namespace" than the
prefixes, how there are actually benefits to it (other than just the
cosmetic "benefits").

The project used quite extensively the Boost library, so rather obviously
all the source files in the project had these at the beginning:

using namespace std;
using namespace boost;

You might already guess where this is going. Yes, indeed, as 2011 was
slowly approaching and more and more compilers started implementing
more and more of the upcoming C++11 standard, people started issuing
bugfix reports that the project wasn't compiling because of clashing
names (the most common issue was the name 'shared_ptr').

This guy's response? "Use a standard-conforming compiler!"

That was his official response that he stubborningly got repeating, no
matter what arguments was presented to him, all the way up to when the
C++11 standard was officially published.

It took a year or two before he kind of "semi-retired" from the position
and the rest of the development team finally refactored the entire
codebase to be C++11 compliant.

Bonita Montero

unread,
Jan 17, 2021, 4:24:53 AM1/17/21
to
> The language is *full* of repetition and "redundant" information.
> How many semi-colons do you write in your source code? How many
> parentheses and curly braces? How many times do you write keywords
> like 'int', 'for' or 'return'?


That has nothing to do with this discussion. We're just talking
about tastes and you're trying to dictate your taste to me.

Öö Tiib

unread,
Jan 17, 2021, 7:10:01 AM1/17/21
to
On Sunday, 17 January 2021 at 01:36:10 UTC+2, Keith Thompson wrote:
> Öö Tiib <oot...@hot.ee> writes:
> [...]
> > Yes, and it is pointless to take someone with too different taste
> > into team. Resulting code base will look inconsistent garbage and
> > trying to achieve more consistency will waste precious time.
> At the risk of stating the obvious, it depends on whether someone with
> different taste is willing to be flexible.

Sure. It is normal that people follow policies that may differ with
their personal views if they want to cooperate. But "Won't read the
rest of your nonsense." is ending any interview. Removing, loosening or
reverting whatever policies because of taste of new member is not possible
so they have to bend or go. They can raise such change request but it will
be most likely rejected as request of worsening.

> For example, I have strong
> opinions about brace placement and indentation (and std::), but in a
> work environment I set them aside and conform to coding standards and
> existing conventions.

About white-space usage we can easily use some kind of formatting software
that keeps eye on style of white space automatically (like unit test of all
code files in continuous integration). We can even vote where is space,
where is indentation and where not with whole team and set it.

But about naming conventions and namespace usage there are no such
good tools I know of. So we can only automatically validate that "using
namespace" has nowhere been uttered.

Bonita Montero

unread,
Jan 17, 2021, 7:53:49 AM1/17/21
to
> Sure. It is normal that people follow policies that may differ with
> their personal views if they want to cooperate. But "Won't read the
> rest of your nonsense." is ending any interview. Removing, loosening
> or reverting whatever policies because of taste of new member is not
> possible so they have to bend or go. They can raise such change request
> but it will be most likely rejected as request of worsening.

We're not a team here so there aren't policies, but just a number of
individual tates.

Nikolaj Lazic

unread,
Jan 17, 2021, 9:27:21 AM1/17/21
to
Dana Sun, 17 Jan 2021 13:54:00 +0100, Bonita Montero <Bonita....@gmail.com> napis'o:
Hm... but when you ask other to read your code... then you are actingr
as a part of the team. This is what everybody is pointing out.

Bonita Montero

unread,
Jan 17, 2021, 10:17:00 AM1/17/21
to
>> We're not a team here so there aren't policies, but just a number of
>> individual tates.

> Hm... but when you ask other to read your code... then you are actingr
> as a part of the team. ...

Everyone here has its own taste. And using std::-spraying isn't common.

daniel...@gmail.com

unread,
Jan 17, 2021, 11:03:19 AM1/17/21
to
On Sunday, January 17, 2021 at 7:53:49 AM UTC-5, Bonita Montero wrote:

> We're not a team here so there aren't policies

Indeed.

On Thursday, January 14, 2021 at 10:47:44 AM UTC-5, Alf P. Steinbach wrote:

> not a problem

> The Windows API function names are Pascal camel-case starting with
> uppercase letter, like `WaitForSingleObject`.
>
> The standard library function names are lowercase, usually using the
> snake case convention with underscores as word separators, like
> `duration_cast` and `high_resolution_clock`.

Just so. And it's common to avoid namespace prefixes in examples and
tutorials when there is no risk of confusion.

Daniel

Nikolaj Lazic

unread,
Jan 17, 2021, 11:04:31 AM1/17/21
to
Dana Sun, 17 Jan 2021 16:17:32 +0100, Bonita Montero <Bonita....@gmail.com> napis'o:
Sure... when you do things for yourself. I use i,j,k for integers and
a,b,c for floats... I guess a bit of Fortran remained. :)
But I do use std::.
And I do use "normal" names for variables when doing something with others.
Or presenting my code. As I would be asking for their time and trying to
waste as little as possible.

Bonita Montero

unread,
Jan 17, 2021, 1:32:04 PM1/17/21
to
>> Everyone here has its own taste. And using std::-spraying isn't common.

> Sure... when you do things for yourself. I use i,j,k for integers and
> a,b,c for floats... I guess a bit of Fortran remained. :)
> But I do use std::.
> And I do use "normal" names for variables when doing something with others.
> Or presenting my code. As I would be asking for their time and trying to
> waste as little as possible.

It's impossible to satisfy or anticipate most peoples tastes.
And I don't complain about such subtle style-differences but
just read the code, even if it doesn't match my favourite style.

Juha Nieminen

unread,
Jan 18, 2021, 2:06:50 AM1/18/21
to
It was you who brought up the "it's redundant" argument, not me.

Now you are saying that it "has nothing to do with this discussion".

Jorgen Grahn

unread,
Jan 23, 2021, 5:26:52 AM1/23/21
to
On Sun, 2021-01-17, Öö Tiib wrote:
> On Sunday, 17 January 2021 at 01:36:10 UTC+2, Keith Thompson wrote:
>> Öö Tiib <oot...@hot.ee> writes:
>> [...]
>> > Yes, and it is pointless to take someone with too different taste
>> > into team. Resulting code base will look inconsistent garbage and
>> > trying to achieve more consistency will waste precious time.
>> At the risk of stating the obvious, it depends on whether someone with
>> different taste is willing to be flexible.
>
> Sure. It is normal that people follow policies that may differ with
> their personal views if they want to cooperate. But "Won't read the
> rest of your nonsense." is ending any interview. Removing, loosening or
> reverting whatever policies because of taste of new member is not possible
> so they have to bend or go. They can raise such change request but it will
> be most likely rejected as request of worsening.

What I notice with myself /and/ others is, we /want/ to cooperate and
we see that it makes sense to adapt to the style of the code base
... but it's never going to stop annoying us, and slowing us down.
And we'll never stop whining about it, when we have a chance.

There's a small minority of programmers who can work with anything
without being distracted. I think that's super-human, and wish I
had that talent.

Often it's about different ways of thinking. E.g., I have a problem
with "getters". "some_polygon.area()" looks right to me, but
"some_polygon.GetArea()" makes me think I'm asking the polygon to go
and fetch the area somewhere else ... which doesn't make sense.
I seem unable to change how I think about this.

And that's just /one/ example. Another is, I have a hard time reading
undocumented code and assuming the programmer intended it to do what
it actually does. Others think it's crazy to document code, because
it does what it does and if you document it, the comment may
contradict the code.

Sometimes I can change something about my style. I've adopted the
space in "if (foo)" in recent years, and I switched to Stroustrup
brace style at one point (decades ago).

Perhaps they shouldn't hire C++ programmers, but C++ programmers of
type A, B, C or D. But I suspect there are many more types.

Manfred

unread,
Jan 23, 2021, 10:45:40 AM1/23/21
to
On 1/23/21 11:26 AM, Jorgen Grahn wrote:
> Often it's about different ways of thinking. E.g., I have a problem
> with "getters". "some_polygon.area()" looks right to me, but
> "some_polygon.GetArea()" makes me think I'm asking the polygon to go
> and fetch the area somewhere else ... which doesn't make sense.
> I seem unable to change how I think about this.

I might even go further with get/set pairs:

class Foo
{
...
public:
Prop prop() const;
void prop(const Prop&);
};

But I admit this may look confusing to some - when working in teams I
follow their coding standards, obviously.

Chris M. Thomasson

unread,
Jan 23, 2021, 4:01:35 PM1/23/21
to
Of course, being able to adapt into a team is an essential quality.
Fwiw, I remember consulting on some code where they had several levels
of get/set type setup. I had to use a "getter" to return a structure of
properties. Then that property structure had more getters/setters. I
figured out how to use it rather quickly.

Think of something along the lines of:

foo.get_props().get_location().get_z_axis()

;^)

Jorgen Grahn

unread,
Jan 23, 2021, 5:45:53 PM1/23/21
to
On Sat, 2021-01-23, Manfred wrote:
> On 1/23/21 11:26 AM, Jorgen Grahn wrote:
>> Often it's about different ways of thinking. E.g., I have a problem
>> with "getters". "some_polygon.area()" looks right to me, but
>> "some_polygon.GetArea()" makes me think I'm asking the polygon to go
>> and fetch the area somewhere else ... which doesn't make sense.
>> I seem unable to change how I think about this.
>
> I might even go further with get/set pairs:

Ok, but note that I wasn't really writing about what's right regarding
getters: it was just an example of where people have preferences they
cannot change.

...
> But I admit this may look confusing to some - when working in teams I
> follow their coding standards, obviously.

I do too, but I cannot force myself to like it, and it's a handicap.

Manfred

unread,
Jan 24, 2021, 12:24:47 PM1/24/21
to
On 1/23/21 11:45 PM, Jorgen Grahn wrote:
> On Sat, 2021-01-23, Manfred wrote:
>> On 1/23/21 11:26 AM, Jorgen Grahn wrote:
>>> Often it's about different ways of thinking. E.g., I have a problem
>>> with "getters". "some_polygon.area()" looks right to me, but
>>> "some_polygon.GetArea()" makes me think I'm asking the polygon to go
>>> and fetch the area somewhere else ... which doesn't make sense.
>>> I seem unable to change how I think about this.
>>
>> I might even go further with get/set pairs:
>
> Ok, but note that I wasn't really writing about what's right regarding
> getters: it was just an example of where people have preferences they
> cannot change.

So was I.

>
> ...
>> But I admit this may look confusing to some - when working in teams I
>> follow their coding standards, obviously.
>
> I do too, but I cannot force myself to like it, and it's a handicap.

To like something of this stuff is strictly related to understanding its
rationale.
So, it helps if the style does make some sense - it has a reasonable
rationale - together with being able to understand someone else's
viewpoint. Which can happen to be an interesting anthropology exercise.

Then there is always the weird case (e.g. "do not use smart pointers"),
where it helps to discuss it with the boss.

>
> /Jorgen
>

Chris M. Thomasson

unread,
Jan 24, 2021, 7:33:10 PM1/24/21
to
One point, smart pointers come in different "flavors" so to speak. Check
this one out:

http://atomic-ptr-plus.sourceforge.net/

Joe Seigh is HYPER smart, and I loved conversing with him over on
comp.programming.threads. He created a very nice smart pointer that has
strong atomic semantics. Here is the patent:

https://patents.google.com/patent/US5295262
(read all...)

It is a beautiful algorihtm that can be directly implemented in pure C++
now, well now with C++11. Well, DWCAS, aka 100% lock-free on a double
word, MUST be lock-free in order for it to "shine", so to speak.

He coined the term, Proxy Garbage Collection. I came up with several
algorithms that do not need DWCAS. Here is one of them:

https://groups.google.com/g/lock-free/c/X3fuuXknQF0/m/u9IPh5fKoFcJ
(read all to see my simulation code in Relacy...)

https://pastebin.com/raw/f71480694
(raw code)

Chris M. Thomasson

unread,
Jan 24, 2021, 8:14:08 PM1/24/21
to
On 1/16/2021 1:35 PM, Chris M. Thomasson wrote:
> On 1/15/2021 10:45 PM, Bonita Montero wrote:
>>> also, you need to make sure that releasing a semaphore has at least
>>> release memory order semantics. You used relaxed. Now, sometimes a
>>> syscall can act like a "membar", but its not guaranteed.
>>
>> Isn't needed because of the syscall.
>
> Bonita Montero wrote:
>
> > bool fsemaphore::release()
> > {
> >      m_semCounter.fetch_add( 1, std::memory_order_relaxed );
> >      return futex( (uint32_t *)&m_semCounter, FUTEX_WAKE, 1, nullptr,
> > 0, 0 ) == 1;
> > }
>
> But, either way, it is in the wrong place. A release barrier must be
> placed _before_ the atomic logic that actually increments the semaphore.
[...]

You need to correct this error!

Bonita Montero

unread,
Jan 25, 2021, 3:58:36 AM1/25/21
to
>> But, either way, it is in the wrong place. A release barrier must be
>> placed _before_ the atomic logic that actually increments the semaphore.
> [...]

> You need to correct this error!

If I'm doing a kernel call in this case I don't need a barrier.

Chris M. Thomasson

unread,
Jan 25, 2021, 3:53:48 PM1/25/21
to
On 1/25/2021 12:58 AM, Bonita Montero wrote:
>>> But, either way, it is in the wrong place. A release barrier must be
>>> placed _before_ the atomic logic that actually increments the semaphore.
>> [...]
>
>> You need to correct this error!

Manually adding in relevant message:
_______________________________________
>
> Bonita Montero wrote:
>
> > bool fsemaphore::release()
> > {
> > m_semCounter.fetch_add( 1, std::memory_order_relaxed );
> > return futex( (uint32_t *)&m_semCounter, FUTEX_WAKE, 1,
nullptr, > 0, 0 ) == 1;
> > }
>
> But, either way, it is in the wrong place. A release barrier must be
placed _before_ the atomic logic that actually increments the semaphore.
[...]
_______________________________________


>
> If I'm doing a kernel call in this case I don't need a barrier.
Huh? Your code is broken. Even if a syscall acts like a barrier. You
snipped relevant parts again. See, your barrier is in the _wrong_ place
for releasing a semaphore. Its simply in the wrong place, period. You
can correct that rather easily. A release member needs to be _before_
the atomic logic that actually increments the semaphore. There is a
simple way to correct your code.

Chris M. Thomasson

unread,
Jan 25, 2021, 3:58:29 PM1/25/21
to
On 1/25/2021 12:53 PM, Chris M. Thomasson wrote:
> On 1/25/2021 12:58 AM, Bonita Montero wrote:
>>>> But, either way, it is in the wrong place. A release barrier must be
>>>> placed _before_ the atomic logic that actually increments the
>>>> semaphore.
>>> [...]
>>
>>> You need to correct this error!
>
> Manually adding in relevant message:

I forgot to add in my name for my comment. See, if you would just sort
of "give in" and add proper quotes, I would not have to do this
manually. Anyway, to reiterate... Even if a syscall is a full barrier,
think #StoreLoad on the SPARC, it is still in the wrong place in your
code. Big time.

> _______________________________________
> >
> > Bonita Montero wrote:
> >
> >  > bool fsemaphore::release()
> >  > {
> >  >      m_semCounter.fetch_add( 1, std::memory_order_relaxed );
> >  >      return futex( (uint32_t *)&m_semCounter, FUTEX_WAKE, 1,
> nullptr,  > 0, 0 ) == 1;
> >  > }
> >

Chris M. Thomasson wrote:

> > But, either way, it is in the wrong place. A release barrier must be
> placed _before_ the atomic logic that actually increments the semaphore.
> [...]

Chris M. Thomasson

unread,
Jan 27, 2021, 12:09:26 AM1/27/21
to
[...]

Btw, iirc, some asshole over at Sun tried to rip off Joe's patent over
at IBM. I wrote about it over on comp.arch. However, I cannot find the
post right now... Need to dig deeper. Iirc, it was this patent:

20060037026 Lightweight reference counting using single-target
synchronization

Joe wrote:
Lock-free reference counting very similar to atomic_ptr or so it would seem.

I basically proved how it violates Joes patent when he worked over at
IBM. Its radically similar in multiple key areas.

Chris M. Thomasson

unread,
Jan 28, 2021, 12:04:50 AM1/28/21
to
I think I finally found it:

https://groups.google.com/g/comp.programming.threads/c/8slBGARhQug/m/CclWCyh69NkJ

The Sun patent totally infringes on prior art. It should have never been
issued.

Chris M. Thomasson

unread,
Feb 1, 2021, 12:27:47 AM2/1/21
to
On 1/17/2021 1:13 AM, Juha Nieminen wrote:
> Chris M. Thomasson <chris.m.t...@gmail.com> wrote:
>> Oh wow. I actually remember, around two decades ago, reading some code
>> where the author actually did that to pthreads. It made me laugh. Iirc,
>> it was something like:
>>
>> #define tcreate pthread_create
>> #define tjoin pthread_join
>
> To be fair, this might have more to do with trying to make code as short as
> possible, rather that avoiding a particular prefix.

;^)

Short in the sense of function names? pthread_mutex_lock, vs pml? ;^)

>
> Not that making code as short as possible is any better.
>
> I think it's an interesting psychological phenomenon why so many beginner
> programmers, and even not-so-beginner ones, always try to make code,
> especially variable and function names, as short as possible.

Indeed.

>
> I see that kind of code quite a lot in my work, where I oftentimes need to
> further develop and use code made by others. This seems to be quite
> common with a particular kind of C programmers, who will often shorten
> names so much that they may become almost indecipherable and make the
> code harder to read (especially when many similarly named variables are
> being used). Like for example naming something 'evts' instead of 'events',
> 'err' instead of 'error', and so on.
>
> Although, POSIX (and the unix world in general) is full of this, so it's
> perhaps not a great mystery where they have learned this kind of coding.
>

;^)

Bonita Montero

unread,
Feb 1, 2021, 3:01:34 AM2/1/21
to
> To be fair, this might have more to do with trying to make code
> as short as possible, rather that avoiding a particular prefix.

My intent was to make less noise in the code.
And for most people this makes my code more readbale.
You're trying to sell compulsiveness as reason.

James Kuyper

unread,
Feb 1, 2021, 9:24:12 AM2/1/21
to
On 1/17/21 4:13 AM, Juha Nieminen wrote:
...
> I think it's an interesting psychological phenomenon why so many beginner
> programmers, and even not-so-beginner ones, always try to make code,
> especially variable and function names, as short as possible.

I actually had a good reason for that during my first class in computer
programming. It was 1976, and an alumnus had donated a long-obsolete IBM
1620 to my high school, which was the only reason we had a programming
class. It used punched cards, and came with a card punch, card sorter,
and card reader.
It's not easy to correct a punched card, and I'm a very poor typist when
I can't backspace to correct my errors. Therefore, every correctly typed
card was precious to me. If I typed a identifier wrong the first time I
wrote it, that became the new "correct" identifier. I got into the habit
of writing my code in such a way as to allow the reuse of cards between
different programs, for instance by using generic identifiers.
I quickly dropped all of those bad habits as soon as I got a chance to
use a computer where programs were stored as editable files.

Juha Nieminen

unread,
Feb 2, 2021, 4:10:50 PM2/2/21
to
If I'm not mistaken some of the first C compilers ever created had
really small limits to things like variable and function name length,
which might have been something as short as 8 characters, and may
explain much of why so many names in POSIX are so short.

Of course this is the 70's we are talking about. Not much reason to
use such short names in the 2020's.

Tim Rentsch

unread,
Feb 20, 2021, 11:43:10 AM2/20/21
to
Jorgen Grahn <grahn...@snipabacken.se> writes:

> On Sun, 2021-01-17, Tiib wrote:
>
>> On Sunday, 17 January 2021 Keith Thompson wrote:
Two points. On the generic issue, I object to the notion that
all choices on "style" questions are purely a matter of taste or
personal preference. In some cases they may be, but in some
others there are objective measures that show one choice is
better than another one. Characterizing /all/ style choices as
merely a question of personal preference is a cop out.

On the specific question of, eg, .area() versus .GetArea(), I
think there are two distinct concerns that bear on the question
(and let me say up front that I agree with your take on which
name is better). One concern is distinguishing between two
modes of thought, namely functional and imperative. It's a
mistake to give every function a name that reflects imperative
thinking: pure functions should have "functional" words or
phrases for names, and "imperative" words or phrases should
be reserved for names of functions that express an imperative
semantics. Obviously area() is better in this regard than
GetArea().

The second concern is what should a function name express? My
answer is that function names should express what the function
does (or returns), and should /not/ express how they do it (or
how the return value is computed). This conclusion follows from
principles of information hiding: what the function does is
important for callers to know, whereas how that is done is
important for callers NOT to know. A good saying in this regard
is, "It's on a need not-to-know basis." Here again area() is
better in this regard that GetArea().

On both of these concerns I consider the choices to be not (only)
a matter of taste/preference but one of programming maturity. I
think most of us learned how to program in assembly language or
an imperative/procedural language such as C or Pascal, and those
early lessons die hard. But make no mistake, those early biases
often reflect less-than-mature judgment as to what constitutes
good programming practice.


> And that's just /one/ example. Another is, I have a hard time
> reading undocumented code and assuming the programmer intended it
> to do what it actually does. Others think it's crazy to document
> code, because it does what it does and if you document it, the
> comment may contradict the code.

I'm interested to hear more about this, not so much why you think
it as how much and what sort of documentation you're talking
about. I don't want to take the other position although probably
my "documenting style" would look like the other side of the
fence from your perspective. Please rest assured I am not
looking for an argument, just more understanding, and hopefully a
shared understanding. Is there more you can say here?
0 new messages