On 10/3/2018 5:57 AM, David Brown wrote:
> On 03/10/18 14:15, James Kuyper wrote:
>> On 10/03/2018 03:30 AM, David Brown wrote:
>>> On 02/10/18 22:11, Chris M. Thomasson wrote:
>>>> On 10/2/2018 4:01 AM, David Brown wrote:
>> ...
>>>>> However, race conditions are always undefined behaviour. And relying on
>>>>> the behaviour of undefined behaviour is never a good idea.
>>>>
>>>> I am artificially creating the race condition using 100% legitimate
>>>> operations;
>>>
>>> And your result is as undefined as if you wrote "int xs[10]; return
>>> x[100];".
>>
>> Could you point to a single, specific, and preferably simple example of
>> code that he wrote which has undefined behavior, and the specific clause
>> from the standard that says that this code has undefined behavior?
>
> After reading Chris Vine's posts and having another quick look, it
> appears that his code does not in fact have race conditions, even though
> that is how Chris Thomasson described his own code.
My code just shows what happens when one has a broken implementation of
the fetch-and-add function. It boils down to:
______________________________
static std::atomic<unsigned int> g_racer(0);
void racer(unsigned int n)
{
for (unsigned int i = 0; i < n; ++i)
{
// Race infested fetch-and-add op
unsigned int r = g_racer.load(std::memory_order_relaxed);
r = r + 1;
g_racer.store(r, std::memory_order_relaxed);
}
}
______________________________
Wrt the standard, this is free of race conditions and/or undefined
behavior. However, wrt the actual logic of the implementation of said
fetch-and-add operation: it is busted. This creates a seemingly endless
stream of data. Just for fun, I was thinking about seeing what happens
if it were to emit bits. Actually, when the system is under load the
"quality" of the "random numbers" seem to get better.
It seems like the bit stream can be used to infer some information from
the system. If it is under heavy load, the quality of the "random" bits
should be "better" than ones derived from a system state that is
basically doing nothing.
> If it /does/ have
> data races that I missed, these are undefined behaviour (5.1.2.4p25 in
> C11, and 1.10p21 in C++14 I think). But these define data races as
> mixing atomic and non-atomic accesses, whereas the code uses only atomic
> accesses.
Right. Everything is working off a global std::atomic<unsigned int>
called g_racer.
> (It may be that there is other undefined behaviour in the code - I
> haven't looked in detail. My argument was based on the OP's statement
> "my code uses race conditions to give random numbers", rather than a
> good look at the code.)
>> Preferably with an explanation of how that clause applies. I'm not
>> disagreeing with you, but multi-threaded code is not something I have a
>> lot of experience with, and I haven't had time to fully digest the
>> descriptions of the newly added features of C that support such code. He
>> is disagreeing with you, and I'd like to have enough information to
>> decide which of you I agree with.
>>
>>> Race conditions are undefined behaviour.
There are two different types of race conditions. Wrt the _standard_, my
code has no race conditions. Wrt the busted fetch-and-add
implementation, well, it just shows what can happen if a sync primitive
is not implemented correctly. My little program that shows this is okay
wrt the standard.
I inappropriately used the term race-condition to refer to the actual
busted fetch-and-add implementation used to generate "random" numbers.
Sorry about that.
> The compiler (and library)
>>> don't guarantee anything here - the don't even guarantee that the
>>> operations are atomic.
>>
>> True, per 5.1.2.4p25; but I gather that the point of disagreement here
>> is whether the conditions have been met for that clause to apply -
>> specifically, the requirement that "... at least one of which is not
>> atomic, ...". Could you explain what's wrong with the reasons that have
>> been given for believing that it doesn't apply?
>>
>
> As I say, it looks like the code does not contain data races after all.
I totally agree with you. Thank you for taking the time to have a
"closer" look. :^)