Sunday, February 7, 2021

Digest for comp.lang.c++@googlegroups.com - 7 updates in 3 topics

"Chris M. Thomasson" <chris.m.thomasson.1@gmail.com>: Feb 07 01:57PM -0800

Take a look at the code here:
 
https://pastebin.com/raw/p1E9WN5i
 
Well there is something stupid I did. The code still works for me, but
its still pissing me off. It involves negating an unsigned int.
 
Take a look at the following function:
_____________________
void prv_quiesce_begin()
{
// Try to begin the quiescence process.
if (! m_quiesce.exchange(true, std::memory_order_acquire))
{
// advance the current collector and grab the old one.
unsigned int old = m_current.load(std::memory_order_relaxed) &
0xFU;
old = m_current.exchange((old + 1) & 1, std::memory_order_acq_rel);
collector& c = m_collectors[old & 0xFU];
 
// decode reference count.
//unsigned int refs = old & 0xFFFFFFF0U; HOLY SHIT!!!
long refs = old & 0xFFFFFFF0U;
 
// verify reference count and previous collector index.
// RL_ASSERT(!(refs & 0x10U) && (old & 0xFU) == (&c -
m_collectors));
 
// increment and generate an odd reference count.
if (c.m_count.fetch_add(refs + 0x10U,
std::memory_order_release) == (unsigned int)-refs)
{
// odd reference count and drop-to-zero condition detected!
prv_quiesce_complete(c);
}
}
}
_____________________
 
Now, this makes me feel bad. I should have just wrote it the following
way to begin with... Adding UINT_MAX + 1 should negate the reference
count without any casts:
 
_____________________
void prv_quiesce_begin()
{
// Try to begin the quiescence process.
if (! m_quiesce.exchange(true, std::memory_order_acquire))
{
// advance the current collector and grab the old one.
unsigned int old = m_current.load(std::memory_order_relaxed) &
0xFU;
old = m_current.exchange((old + 1) & 1, std::memory_order_acq_rel);
collector& c = m_collectors[old & 0xFU];
 
// decode reference count.
unsigned int refs = old & 0xFFFFFFF0U;
 
// verify reference count and previous collector index.
// RL_ASSERT(!(refs & 0x10U) && (old & 0xFU) == (&c -
m_collectors));
 
// increment and generate an odd reference count.
if (c.m_count.fetch_add(refs + 0x10U,
std::memory_order_release) == refs + UINT_MAX + 1)
{
// odd reference count and drop-to-zero condition detected!
prv_quiesce_complete(c);
}
}
}
_____________________
 
 
Much better!
 
 
refs + UINT_MAX + 1 should equal -refs... ;^)
"Chris M. Thomasson" <chris.m.thomasson.1@gmail.com>: Feb 07 02:02PM -0800

On 2/7/2021 1:57 PM, Chris M. Thomasson wrote:
> Take a look at the code here:
 
> https://pastebin.com/raw/p1E9WN5i
[...]
> Much better!
 
> refs + UINT_MAX + 1 should equal -refs... ;^)
 
Also, I need to ensure that I am using actual 32-bit types here.
unsigned int can be less than 32-bits. My Bad!! I am correcting these
things before I finish creating my "Poor Mans RCU..." example in C++17.
 
The examples work for me, even negating an unsigned int. However, its
not portable.
Richard Damon <Richard@Damon-Family.org>: Feb 07 05:48PM -0500

On 2/7/21 4:57 PM, Chris M. Thomasson wrote:
 
> refs + UINT_MAX + 1 should equal -refs... ;^)
 
UINT_MAX+1 as a unsigned int (which it should be) will be 0, remember
unsigned math is mod *_MAX+1
 
thus refs + UINT_MAX + 1 will be refs.
 
You don't need casts to deal with -refs, as an unsigned it just has the
value of UINT_MAX + 1 - refs
 
You only need the cast if you want -refs to be < 0, but I don't see any
comparisons in the code that would be affected by that.
James Kuyper <jameskuyper@alumni.caltech.edu>: Feb 07 01:43PM -0500

On 2/7/21 1:22 PM, Anton Shepelev wrote:
> configuration of the several build systems supported by the
> project in parallel. What problems, drawbacks, or dangers do
> you see to this approach?
 
The answer to your question involves C++ issues, so I've added
comp.lang.c++.
 
Note (unrelated to your question): the way I normally do things,
"ppscale.c" would already #include "ppscale.h", helping ensure that the
declarations in the header file are consistent with the definitions in
the .c file. That would render it unnecessary for the C++ file to do so
itself. Do you do the same?
 
If you take arbitrary C code, and process it as C++ code, there's a lot
of minor issues that could cause problems. See Annex C of the C++
standard for a list of differences that is fairly complete and fairly
comprehensive. Most of the differences are likely to prevent
compilation, or at least trigger a mandatory diagnostic.
 
Therefore, if he got your code to compile as C++ code with a high
warning level and no diagnostics, and in particular, if he thinks he got
it to work, then there's a decent chance that none of those problems
actually came up. However, there are silent differences - C code that
would compile without diagnostics as C++ code, but has subtly different
semantics, and if he didn't give the code a thorough test, he might have
missed those differences. It would be far safer to compile it as C code,
and then use extern "C" declarations to link to it from C++ code.
There's far fewer tricky issues to worry about (though there's still a few).
Anton Shepelev <anton.txt@gmail.com>: Feb 07 09:57PM +0300

James Kuyper:
 
> The answer to your question involves C++ issues, so I've
> added comp.lang.c++.
 
Yes, C++ programmers are welcome.
 
> are consistent with the definitions in the .c file. That
> would render it unnecessary for the C++ file to do so
> itself. Do you do the same?
 
No:
 
https://launchpad.net/ppscale
 
but I will, which will make including ppscale.h redundant.
I don't know why I didn't do it, probably just forgot. I
kept thinking of .c and .h files as the interface and
implentation parts of a Modula module, which they are not.
Thanks for the suggestion.
 
> that is fairly complete and fairly comprehensive. Most of
> the differences are likely to prevent compilation, or at
> least trigger a mandatory diagnostic.
 
That is a good reason to compile the C code with a C
compliler into a separate object file or static library.
 
> use extern "C" declarations to link to it from C++ code.
> There's far fewer tricky issues to worry about (though
> there's still a few).
 
Thank you very much for the advice. I will forward it to the
maintainer.
 
--
() ascii ribbon campaign -- against html e-mail
/\ http://preview.tinyurl.com/qcy6mjc [archived]
Manfred <noname@invalid.add>: Feb 07 09:04PM +0100

On 2/7/21 7:57 PM, Anton Shepelev wrote:
> kept thinking of .c and .h files as the interface and
> implentation parts of a Modula module, which they are not.
> Thanks for the suggestion.
 
While you're at it, you may want to bracket the C declarations in the
header file with
 
#ifdef __cplusplus
extern "C" {

No comments: