Sunday, September 26, 2021

Digest for comp.lang.c++@googlegroups.com - 16 updates in 4 topics

Jorgen Grahn <grahn+nntp@snipabacken.se>: Sep 26 06:58AM


>> Nothing inherently wrong with that, but in C, it would be more
>> traditional to use NULL.
 
> It would be more traditional in C++, as well.
 
Opinions varied. Before nullptr, I always used NULL in C and 0 in
C++. IIRC using 0 was a common recommendation here, too, for whatever
reason.
 
/Jorgen
 
--
// Jorgen Grahn <grahn@ Oo o. . .
\X/ snipabacken.se> O o .
Branimir Maksimovic <branimir.maksimovic@gmail.com>: Sep 26 07:47AM


> Opinions varied. Before nullptr, I always used NULL in C and 0 in
> C++. IIRC using 0 was a common recommendation here, too, for whatever
> reason.
 
#define NULL (void*)0
simple, problem is that in C++, one have to cast from void
and that does not works, and this is BuG in C++.
 
 
--
 
7-77-777
Evil Sinner!
Keith Thompson <Keith.S.Thompson+u@gmail.com>: Sep 26 02:15AM -0700


> #define NULL (void*)0
> simple, problem is that in C++, one have to cast from void
> and that does not works, and this is BuG in C++.
 
That's not a valid definition of NULL in either C or C++.
 
In C or C++, the definition has to be parenthesized to avoid parsing
errors in some contexts;
 
#define NULL ((void*0)
 
I'm not sure what you mean by "this is BuG in C++". A C++
implementation that defined NULL that way would be non-conforming.
 
--
Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
Working, but not speaking, for Philips
void Void(void) { Void(); } /* The recursive call of the void */
Keith Thompson <Keith.S.Thompson+u@gmail.com>: Sep 26 02:17AM -0700


> Opinions varied. Before nullptr, I always used NULL in C and 0 in
> C++. IIRC using 0 was a common recommendation here, too, for whatever
> reason.
 
As I recall, Stroustrup's books used 0 when a null pointer constant was
required, and that was probably the origin of the (pre-nullptr)
convention to use 0 in C++ while NULL is more widely recommended in C.
 
--
Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
Working, but not speaking, for Philips
void Void(void) { Void(); } /* The recursive call of the void */
Branimir Maksimovic <branimir.maksimovic@gmail.com>: Sep 26 09:38AM


> #define NULL ((void*0)
 
> I'm not sure what you mean by "this is BuG in C++". A C++
> implementation that defined NULL that way would be non-conforming.
 
Exactly, that is why it is Bug.
Thanks for correction, BTW.
 
--
 
7-77-777
Evil Sinner!
Bo Persson <bo@bo-persson.se>: Sep 26 01:54PM +0200

On 2021-09-26 at 09:47, Branimir Maksimovic wrote:
 
> #define NULL (void*)0
> simple, problem is that in C++, one have to cast from void
> and that does not works, and this is BuG in C++.
 
It is not a bug when it is done very much on purpose.
 
Stroustrup says:
 
"A pointer to any type of object can be assigned to a variable of type
void*, a void* can be assigned to another void*, void* can be compared
for equality and inequality, and a void* can be explicitly converted to
another type. Other operations would be unsafe because the compiler
cannot know what kind of object is really pointed to. Consequently,
other operations result in compile-time errors."
HorseyWorsey@the_stables.com: Sep 26 02:20PM

On 26 Sep 2021 06:58:15 GMT
 
>Opinions varied. Before nullptr, I always used NULL in C and 0 in
>C++. IIRC using 0 was a common recommendation here, too, for whatever
>reason.
 
It still use NULL instead of nullptr because its a lot more obvious when
speed reading code.
Keith Thompson <Keith.S.Thompson+u@gmail.com>: Sep 26 03:03PM -0700

>> implementation that defined NULL that way would be non-conforming.
 
> Exactly, that is why it is Bug.
> Thanks for correction, BTW.
 
To be clear, you're saying that if any C++ implementation actually
defined NULL that way, it would be a bug in that implementation.
That's true, but I'm not aware of any implementation that actually
has that hypothetical bug. It can require some trivial extra work
for an implementation that shares headers between C and C++, but
implementers are well aware of the issue.
 
--
Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
Working, but not speaking, for Philips
void Void(void) { Void(); } /* The recursive call of the void */
Keith Thompson <Keith.S.Thompson+u@gmail.com>: Sep 26 03:17PM -0700

> to another type. Other operations would be unsafe because the compiler
> cannot know what kind of object is really pointed to. Consequently,
> other operations result in compile-time errors."
 
"The C++ Programming Language", 4th edition, section 7.2.1.
 
As Stroustrup says, converting from void* to another pointer type
requires an explicit conversion, but converting NULL to any pointer
type does not. (void*)0 is a null pointer constant in C, but not in C++.
 
This:
int *p;
p = (void*)0;
is invalid in C++, but this:
int *p;
p = NULL;
is valid. Because of that, a C++ implementation that defines NULL as
either (void*)0 or ((void*)0) is non-conforming. (It's unlikely that
any actual C++ implementations make that mistake.)
 
--
Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
Working, but not speaking, for Philips
void Void(void) { Void(); } /* The recursive call of the void */
"Alf P. Steinbach" <alf.p.steinbach@gmail.com>: Sep 26 01:50AM +0200

On 25 Sep 2021 23:07, Manfred wrote:
>> general.
 
> I'm no expert in coroutines, but AFAIU their main advantage is to enable
> multitasking without the overhead of multithreading.
 
What you write is an advantage of continuations compared to general
coroutines. I consider that a very marginal advantage. Correctness is
far, far more important than some micro-efficiency.
 
The advantage of general coroutines is that they enable multi-tasking
(namely cooperative multi-tasking) without the severe synchronization
problems of general threads or processes.
 
Coroutines don't automagically deal with all kinds of multi-tasking
problems, in particular deadlocks are still possible, but you don't have
two or more threads possibly accessing the same thing at a time, since
only one coroutine executes at a time.
 
 
> In order to achieve this, language support is needed that was just not
> available prior to C++20 (and even with C++20 such support is limited,
> so that only the subset of continuations is actually available, as you say)
 
True, but I fail to see any reason, and I haven't yet seen anybody able
to cough up a reason, to have continuations in C++.
 
 
> The point being, if you try to do that using threads kind of defeats the
> purpose, doesn't it?
 
No (you misunderstood the purpose).
 
Doing this could open the world of safe multi-tasking to C++ programmers
in general.
 
Oh, I already wrote that, sorry.
 
 
> (even if you build this with full synchronization inside, you'll still
> pay the price of performance and resource usage, which can be relevant
> for this kind of thing)
 
Yes, it must be built with synchronization inside, and like threads each
general coroutine needs its own stack, which is another cost: firing up
a general coroutine generally involves a dynamic allocation (though I
guess with language support it's technically possible to use statically
allocated stack areas when the number of coroutines has a reasonably low
upper bound, but such support would be needed for that because standard
threads don't provide any means to influence the per-thread stacks).
 
 
>> Another such enabler: an implementation of Ada-like rendezvous.
 
>> And, and, ... Occam-like channels, maybe. :)
 
I forgot to mention Linda.
 
Oh well.
 
 
- Alf
HorseyWorsey@the_stables.com: Sep 26 02:15PM

On Sat, 25 Sep 2021 18:44:55 +0200
>> compiler generated object too. So simple compared to state variables!
 
>You can be assured that in the near future most C++-capable debuggers
>will support that.
 
In the real world as opposed to your toy home dev enviroment, compilers
and debuggers do not get updated very often because they have to be
thoroughly tested to make sure they don't break the code or cause some other
issue. Keeping a business running is more important than having the latest
bleeding edge language features.
Manfred <noname@add.invalid>: Sep 26 07:12PM +0200

On 9/26/2021 1:50 AM, Alf P. Steinbach wrote:
 
> What you write is an advantage of continuations compared to general
> coroutines. I consider that a very marginal advantage. Correctness is
> far, far more important than some micro-efficiency.
 
Correctness is the precondition, obviously, but this is not about
micro-efficiency (see below)
 
 
> The advantage of general coroutines is that they enable multi-tasking
> (namely cooperative multi-tasking) without the severe synchronization
> problems of general threads or processes.
 
Yes, what you call "severe synchronization problems" is part of what I
called "overhead". (I tend to write in a very concise way - that is
meant both as "coding overhead" and "resource usage overhead")
 
> problems, in particular deadlocks are still possible, but you don't have
> two or more threads possibly accessing the same thing at a time, since
> only one coroutine executes at a time.
 
Yes, that was clear.
 
>> say)
 
> True, but I fail to see any reason, and I haven't yet seen anybody able
> to cough up a reason, to have continuations in C++.
 
Aren't continuations in C++20? Do you mean general coroutines?
If that is the case, the fact that POSIX has (had) support for them
would suggest that it should be possible, then the fact that they
dropped it may also suggest that there are counter indications of some
sort, but I agree that still the question for explanation stands.
 
 
>> The point being, if you try to do that using threads kind of defeats
>> the purpose, doesn't it?
 
> No (you misunderstood the purpose).
Not entirely (see above)
 
 
> Doing this could open the world of safe multi-tasking to C++ programmers
> in general.
 
> Oh, I already wrote that, sorry.
So, you mean make life easier for C++ programmers that are not
comfortable with multithreaded programming, fair enough. ("open the
world" sounded to me like there would be something more involved).
 
> allocated stack areas when the number of coroutines has a reasonably low
> upper bound, but such support would be needed for that because standard
> threads don't provide any means to influence the per-thread stacks).
 
Referring to the first "see below" above: there are multiple performance
costs involved with firing up multiple threads - whether these costs
fall into the category of "micro-efficiency" depends on the context.
 
AFAIU coroutines are especially used (or at least advocated for) in
areas like high-throughput server processes, real time systems, and
architectures with strict resource constraints. This is why I wrote
performance might be relevant for this kind of thing.
 
As to how it works, with POSIX I found "man makecontext" interesting (on
any decent Linux box or the appropriate POSIX documentation).
But then, support for this has been removed in POSIX.1-2008, so probably
it's not that pressing of a need.
 
Bonita Montero <Bonita.Montero@gmail.com>: Sep 26 07:26AM +0200

So as the timings of the PAUSE-instructions are so different I
decided to write a singleton containing the fastest timing of
the PAUSE-instruction on the machine. This is the code:
 
cpu_pause.h:
 
#pragma once
#if defined(_MSC_VER) && (defined(_M_X64) || defined(_M_IX86))
#include <intrin.h>
#elif defined(__GNUC__) && (defined(__x86_64__) || defined(__i386__))
#include <immintrin.h>
#else
#error "need platform-specific pause-instruction"

No comments: