Wednesday, May 23, 2018

Digest for comp.lang.c++@googlegroups.com - 22 updates in 5 topics

David Brown <david.brown@hesbynett.no>: May 23 08:38AM +0200

On 23/05/18 00:03, Melzzzzz wrote:
 
> You either use threads or processes. There is no point in using both
> threads and fork, except as you noted when exec-ing from multi-thread
> process.
 
That's not /quite/ true. Large server programs can sometimes see
advantages in having multiple processes, each of which has multiple
threads. There may be no exec's involved - the parent process forks of
multiple copy processes as needed. But child processes that spawn
threads to do the actual work do not then fork - a given processes
spawns either fork processes, or threads, but not both. (Except, as you
say, for fork-exec for running independent programs.)
boltar@cylonHQ.com: May 23 09:45AM

On Tue, 22 May 2018 09:22:53 -0700
 
>> If I have to explain why its an ugly hack there's little point discussing it.
 
>Nope. You're the one making an assertion without providing evidence.
>Therefore you are the one who has to back up the assertion.
 
Because starting up an entirely new process to pass a command line parameter
that has to be parsed first then do an explicit jump or call to a particular
function or location is utterly prehistoric compared to doing a switch() on
the return value of fork(). Its aesthetically ugly and inefficient from a
processor POV too.
boltar@cylonHQ.com: May 23 09:54AM

On Tue, 22 May 2018 21:42:40 +0200
 
>>What do you think fork() does?
 
>It creates a copy of the current process, which in most use cases is
>immediately disposed afterwards by calling one of the exec() variants.
 
In most use cases? The shell, sure. Most other programs that use fork use it
to undertake multi process processing.
 
>Creating that unwanted copy may be expensive in the first place,
>depending on the OS and MMU architecture. And it has ugly side-effects
>for programs dealing with a lot of open handles, especially socket handles.
 
Not at all. The open handles are a necessity for a lot of things and there
is the SOCK_CLOEXEC option to automatically close sockets on an exec anyway.
 
>running an arbitrary exe, passing over only explicitly specified
>information through command line parameters, pipes, or environment
>variables.
 
Windows approach is a poor hack presumably because starting a new process
from scratch is a lot simpler than effectively splitting one in 2 and
having to manage everything that goes with that.
Paavo Helde <myfirstname@osa.pri.ee>: May 23 02:22PM +0300


> Windows approach is a poor hack presumably because starting a new process
> from scratch is a lot simpler than effectively splitting one in 2 and
> having to manage everything that goes with that.
 
And since when is a simpler way to do something called a "poor hack"?
 
With fork+exec one needs to make sure that all the irrelevant open
files, sockets and pipes (including the ones created by any third party
libraries) have the proper FD_CLOEXEC flags attached. Yes, this is
complicated and there are ugly hacks used to forcible close them. At
least in Windows one needs to create inheritable handles explicitly and
CreateProcess() function has the bInheritHandles parameter which gives
another simple way to control it. But I guess this is too simple for
your taste.
Paavo Helde <myfirstname@osa.pri.ee>: May 23 02:38PM +0300

> function or location is utterly prehistoric compared to doing a switch() on
> the return value of fork(). Its aesthetically ugly and inefficient from a
> processor POV too.
 
Unfortunately the trend appears to go toward multithreaded programs
nowadays, and fork without exec cannot be used in multithreaded
programs. At the same time, fork+exec involves the same "ugly" command
line parameter parsing, plus other complications.
 
So what you call "prehistoric" appears to be "trendy" now. Go figure.
scott@slp53.sl.home (Scott Lurndal): May 23 01:26PM


>Unfortunately the trend appears to go toward multithreaded programs
>nowadays, and fork without exec cannot be used in multithreaded
>programs.
 
Sure it can. With care. Unixware even has a 'forkall()' system call
that clones all the parent threads.
Chris Vine <chris@cvine--nospam--.freeserve.co.uk>: May 23 04:46PM +0100

On Wed, 23 May 2018 13:26:46 GMT
> Paavo Helde <myfirstname@osa.pri.ee> writes:
[anip]
> >programs.
 
> Sure it can. With care. Unixware even has a 'forkall()' system call
> that clones all the parent threads.
 
I thought it was SunOS/Solaris which had forkall(). Are you sure about
unixware?
 
However, forkall() doesn't solve the issue. Before forkall()ing, the
forking thread has the same problem of needing to synchronise with other
threads. In the case of forkall() this is so that the other threads are
in a state which allows them to be duplicated; in the face of fork()
this is so that they are in a state which allows them not to be
duplicated. Forkall() cannot be performed willy nilly without other
threads' knowledge or consent, in particular with respect to side
effects. Forkall()ing a process where a thread happens to be doing
some IO is an obvious example of a disaster waiting to happen.
forkall() just redistributes the problem.
 
There is some discussion by Butenhof of this here in the context of the
uselessness of pthread_atfork() (that was before our dear spammer drove
the newsgroup concerned out of use):
https://groups.google.com/d/msg/comp.programming.threads/ThHE32-vRsg/3j-YICgSQzoJ
red floyd <dont.bother@its.invalid>: May 23 09:51AM -0700

On 5/23/2018 8:46 AM, Chris Vine wrote:
>> that clones all the parent threads.
 
> I thought it was SunOS/Solaris which had forkall(). Are you sure about
> unixware?
 
UnixWare was SVR4.x, which was also the basis for Solaris. Wouldn't be
surprised if it had it.
Paavo Helde <myfirstname@osa.pri.ee>: May 23 08:14PM +0300

On 23.05.2018 16:26, Scott Lurndal wrote:
>> programs.
 
> Sure it can. With care. Unixware even has a 'forkall()' system call
> that clones all the parent threads.
 
forkall() I can understand. But what do you mean by "with care"? Using
pthread_atfork()? Seems pretty complicated.
scott@slp53.sl.home (Scott Lurndal): May 23 05:25PM

>> that clones all the parent threads.
 
>forkall() I can understand. But what do you mean by "with care"? Using
>pthread_atfork()? Seems pretty complicated.
 
No, the threads within the application are coded to allow for the fact
that at some point in time (controlled by the application itself) they
will be forked. Controller/main thread tells other threads to prepare
for fork, waits for them to check in, then forks.
 
In the rare case that a third-party library which uses threads is linked
into the application, then the third-party library would need to offer
an api to quiesce its thread. Third party libraries that use
threads are fairly rare.
 
It's not like the fork()/forkall() calls are unexpected by the application.
 
That said, I've been using threads since the late 80's, and have never
encounted a use-case for forking a multithreaded app and not immediately calling exec(2).
Jorgen Grahn <grahn+nntp@snipabacken.se>: May 23 07:10AM

On Mon, 2018-05-21, Christiano wrote:
> std-discussion and I want to suggest to isocpp.org to add comp-lang-cpp
> here:
> https://isocpp.org/std/forums
 
Hasn't comp.lang.c++ always been unrelated to the commitee?
Do you perhaps mean comp.std.c++?
 
> This is being discussed here:
> https://groups.google.com/a/isocpp.org/forum/#!topic/std-discussion/pAL2dOe9MIk
 
> I would like to know your opinion.
 
Not interested, personally.
 
(Also, it annoys me when people call C++ "cpp", since cpp is also the
C preprocessor.)
 
/Jorgen
 
--
// Jorgen Grahn <grahn@ Oo o. . .
\X/ snipabacken.se> O o .
legalize+jeeves@mail.xmission.com (Richard): May 23 02:53PM

[Please do not mail me a copy of your followup]
 
Jorgen Grahn <grahn+nntp@snipabacken.se> spake the secret code
 
>(Also, it annoys me when people call C++ "cpp", since cpp is also the
>C preprocessor.)
 
Web thingies notoriously confuse + with ' ' because of URL encodings.
--
"The Direct3D Graphics Pipeline" free book <http://tinyurl.com/d3d-pipeline>
The Terminals Wiki <http://terminals-wiki.org>
The Computer Graphics Museum <http://computergraphicsmuseum.org>
Legalize Adulthood! (my blog) <http://legalizeadulthood.wordpress.com>
woodbrian77@gmail.com: May 23 10:11AM -0700

On Wednesday, May 23, 2018 at 2:10:13 AM UTC-5, Jorgen Grahn wrote:
> > here:
> > https://isocpp.org/std/forums
 
> Hasn't comp.lang.c++ always been unrelated to the commitee?
 
Others and I have made some informal proposals here. I hope
that will continue. Comp.lang.c++.moderated was OK, but
nothing to write home about.
 
 
Brian
Ebenezer Enterprises
https://github.com/Ebenezer-group/onwards
Pvr Pasupuleti <pvr.ram34@gmail.com>: May 23 09:08AM -0700

https://unacademy.com/lesson/abstract-classes/HCNAUQHC
Juha Nieminen <nospam@thanks.invalid>: May 23 06:24AM

Why doesn't the last line compile?
 
//------------------------------------------------------------
struct Test1 {};
struct Test2 { constexpr Test2() {} };
 
struct Container
{
struct Test3 {};
struct Test4 { constexpr Test4() {} };
 
static constexpr Test1 object1; // Compiles
static constexpr Test2 object2; // Compiles
static constexpr Test3 object3; // Compiles
static constexpr Test4 object4; // Does not compile
};
//------------------------------------------------------------
Ian Collins <ian-news@hotmail.com>: May 23 07:27PM +1200

On 23/05/18 18:24, Juha Nieminen wrote:
> static constexpr Test4 object4; // Does not compile
> };
> //------------------------------------------------------------
 
Compilers are trying to tell us something:
 
$ clang++ -std=c++17 /tmp/tt.cc
/tmp/tt.cc:13:28: error: constexpr variable 'object4' must be
initialized by a constant expression
static constexpr Test4 object4; // Does not compile
^~~~~~~
/tmp/tt.cc:13:28: note: undefined constructor 'Test4' cannot be used in
a constant expression
/tmp/tt.cc:8:30: note: declared here
struct Test4 { constexpr Test4() {} };
^
1 error generated.
$ g++ -std=c++17 /tmp/tt.cc
/tmp/tt.cc:10:28: error: constexpr static data member 'object1' must
have an initializer
static constexpr Test1 object1; // Compiles
^~~~~~~
/tmp/tt.cc:11:28: error: constexpr static data member 'object2' must
have an initializer
static constexpr Test2 object2; // Compiles
^~~~~~~
/tmp/tt.cc:12:28: error: constexpr static data member 'object3' must
have an initializer
static constexpr Test3 object3; // Compiles
^~~~~~~
/tmp/tt.cc:13:28: error: constexpr static data member 'object4' must
have an initializer
static constexpr Test4 object4; // Does not compile
^~~~~~~
 
Change the objects to object[1234]():
 
$ clang++ -std=c++17 -c /tmp/tt.cc
$ g++ -std=c++17 -c /tmp/tt.cc
 
--
Ian.
Paavo Helde <myfirstname@osa.pri.ee>: May 23 12:07PM +0300

On 23.05.2018 10:27, Ian Collins wrote:
> static constexpr Test4 object4; // Does not compile
> ^~~~~~~
 
> Change the objects to object[1234]():
 
This will just declare a bunch of functions, which is probably not what
OP had in mind. One ought to use object[1234]{}, but this doesn't
compile for Test4 either:
 
>g++ main.cpp
main.cpp:15:33: error: 'constexpr Container::Test4::Test4()' called in a
constant expression before its definition is complete
static constexpr Test4 object4{}; // Does not compile
^
Ian Collins <ian-news@hotmail.com>: May 23 10:08PM +1200

On 23/05/18 21:07, Paavo Helde wrote:
>>> static constexpr Test4 object4; // Does not compile
>>> };
>>> //------------------------------------------------------------
 
<snip>
 
 
> This will just declare a bunch of functions, which is probably not what
> OP had in mind. One ought to use object[1234]{}, but this doesn't
> compile for Test4 either:
 
That was what I meant to type...
 
> constant expression before its definition is complete
> static constexpr Test4 object4{}; // Does not compile
> ^
 
I wonder if it is to do with where inline member function definitions
are parsed? The nested class is within the scope of Container, so where
is a local class constructor complete?
 
--
Ian.
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: May 23 12:54PM +0200

On 23.05.2018 08:24, Juha Nieminen wrote:
> static constexpr Test4 object4; // Does not compile
> };
> //------------------------------------------------------------
 
It's clearly a bug, but the question is whether it's in the compilers or
in the standard.
 
I'd guess that the compilers somehow incorrectly regard `Test4` as
incomplete because the containing class `Container` is incomplete.
 
As a workaround it "should" work to just provide the explicit
initialization that the error messages quoted else-thread, refer to.
 
 
Cheers!,
 
- Alf
Sam <sam@email-scan.com>: May 23 08:30AM -0400

Juha Nieminen writes:
 
> static constexpr Test3 object3; // Compiles
> static constexpr Test4 object4; // Does not compile
> };
 
The definition of the "Container" class is not complete until its closing
brace.
 
A constexpr object must refer to a complete class, amongst all the other
requirements. "Test4" refers to a member of an incomplete class, at the time
it's used.
 
You just can't have a `constexpr` class member instance of the class itself,
or of any inner classes.
Ben Bacarisse <ben.usenet@bsb.me.uk>: May 23 02:54PM +0100

I'm piggy-backing as much as replying...
 
>> static constexpr Test3 object3; // Compiles
>> static constexpr Test4 object4; // Does not compile
>> };
 
A data point... gcc (Ubuntu 7.3.0-16ubuntu3) 7.3.0 complains about all
four lines with "constexpr static data member 'object1' must have an
initializer". Adding = {} to each makes it complain only about the last
one with 'constexpr Container::Test4::Test4()' called in a constant
expression before its definition is complete".
 
 
> A constexpr object must refer to a complete class, amongst all the
> other requirements. "Test4" refers to a member of an incomplete class,
> at the time it's used.
 
That's the bit that confuses me. Container is not complete, but Test4
looks complete. Adding
 
struct Test5 { int i; };
...
static constexpr Test5 object5 = {};
 
provokes no complaint (for gcc or clang) and Test5 looks just as
complete or incomplete as Test4. The issue must be specific to classes
with constructors and I confess to not have read what C++ says about a
class being complete.
 
> You just can't have a `constexpr` class member instance of the class
> itself, or of any inner classes.
 
gcc and clang both permit such a thing in the case of Test5, so is that
a compiler bug?
 
--
Ben.
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: May 23 02:56PM +0200

The notation is still ugly, but I got an insight: that one may need to
remove/cancel an option from a base class. Then for expressing an
options set "+" and "-" work better than "|". The notation is still ugly
though, involving verbose "using" statements to avoid even worse verbosity:
 
Main_window()
: Top_level_window{ L"The new main window" }
{
using Ed = winapi::gui::Edit_control;
using Opt = Ed::Options;
using Ft = name::Features;
using cppx::options_shortname::_;
const ptr_<Ed> edit = make_new<Ed>( *this, Opt{} + _<Ft>(
Ed::multiline ) );
MoveWindow( *edit, 10, 10, 640, 400, false );
}
 
Here the "name::Features" (a pointer type in a namespace) is the way to
express a name for a value, so that one can have, say, various integer
values that denote different things.
 
A less verbose alternative could perhaps be to require a separate type,
maybe a boxing type, for each rôle of type's values?
 
Ideas?
 
 
Cheers!,
 
- Alf
You received this digest because you're subscribed to updates for this group. You can change your settings on the group membership page.
To unsubscribe from this group and stop receiving emails from it send an email to comp.lang.c+++unsubscribe@googlegroups.com.

No comments: