Interview with Mr Stroustrup

J

Joshua Maurice

What's wrong with relying on standards for threads, such as pthreads?  
There is no reason to push something into a particular standard when that
very same feature is already defined by another standard.

Several reasons.

First, I think we'd all like an implemented and portable threading
interface so we don't have to roll our own abstraction layer. There's
a lot of subtle nuance in the several threading libraries which make
it non-trivial to wrap.

Second, threading really ought to be part of the programming language
standard as it directly affects and constrains the code generation of
the compiler. A library like a GUI doesn't impose any particular
noteworthy restrictions on the compiler, but threading is inextricably
tied to compilation, optimization, and code generation.

Third, from my knowledge of win32 threads, pthreads, and the barriers
of the linux kernel, I personally very much welcome this new standard
as it's much more formalized. There is such a lack of knowledge in the
community as to how threading actually works. I meet people every day
who think that volatile is still a portably useful threading
primitive. Trying to reason about how the compiler operate when
throwing inline assembly at it with pthreads is also quite difficult.
The new standard is much more complete, sane, and useful.

I've seen people using gcc inline assembly to do a read and write
barriers, and argue whether the "memory" clobber is used or not, and
whether volatile will make it work in the absence of the "memory"
clobber. With this new standard, you might even get better
optimization as opposed to gcc's current interface as the compiler
will be able to do something more fine grain than the correct "memory"
clobber, and it will still have the correct behavior unlike the case
of no "memory" clobber.

AFAIK, it has been standardized to be implementable on all hardware
such that "you don't pay for what you don't use". Specifically, if you
write your data dependent loads correctly in the C source, your code
will work on the DEC-alpha, and you won't suffer any performance
penalties where it's not needed such as the x86.
 
A

Alan Curry

Just as we don't want C to be left behind. The C++ standard has adapted
to modern hardware by incorporating threading into the core language and
the C1x drafts do likewise.

If anything like pthreads gets added, and fork() doesn't, it'll be a tragedy.

One of the great benefits of modern hardware is protected memory. fork
gives you multiple threads of execution without throwing away that benefit.
To give up protected memory in the name of "adapting to modern hardware" is
ridiculous.
 
J

Joshua Maurice

If anything like pthreads gets added, and fork() doesn't, it'll be a tragedy.

One of the great benefits of modern hardware is protected memory. fork
gives you multiple threads of execution without throwing away that benefit.
To give up protected memory in the name of "adapting to modern hardware" is
ridiculous.

Well, I think that's more to do with that not all operating systems
natively support a Posix-like fork - eg: win32, whereas all current
threading models are sufficiency similar to allow standardization.

If we're talking about a much more generic process spawn equivalent,
then I agree that would be nice to have. It would be nice for the
reasons you state, and it would be nice even if I was programming only
on unix-like systems to avoid the bugs in Posix fork.

Finally, see my other posts else-thread for other reasons which apply
to threads but don't apply to processes. Threading is inextricably
tied to code generation, so it really ought to be in the same standard
document that constrains the rest of the code generation of the
compiler, whereas the existence of and the use of processes don't
really constrain the code generation of a compiler.
 
B

Ben Pfaff

If anything like pthreads gets added, and fork() doesn't, it'll be a tragedy.

Threads affect the language a lot more than fork() does. It's a
lot easier to add fork() as an afterthought than it is to add
threads.
 
T

Thomas Richter

Alan said:
If anything like pthreads gets added, and fork() doesn't, it'll be a tragedy.

One of the great benefits of modern hardware is protected memory.

C as well as C++ also operates on hardware that *does not have*
protected memory, though offers threads. The fork() primitive requires a
lot of support from the operating system, and support some (if not even
the majority of the operating systems I know) do not offer.

Greetings,
Thomas
 
T

Tobias Blass

Threads affect the language a lot more than fork() does. It's a
lot easier to add fork() as an afterthought than it is to add
threads.
Of course it is easy to add fork() on some platforms, but I think including
threads to the standard but fork() not would make fork() look like some 2nd
class threading, so people would always use threading instead of several
processes. Of course there are some scenarios were threads are actually better
than processes ( e.g. scientific calculations), but in most of the cases
processes with separated address spaces lead to programs much easier to debug and to maintain. Wouldn't it be possible to add a clone(2)-like library function where you can specify how much you want to share with your child process. You had to find a way how to support separated data on platforms without separated process memory, but couldn't you just handle per process data like a variable with prefix? (So if the programmer says "I want to have 2 processes, one containing var1 and one containig var2" you could simulate it by dividing your programs memory and only refer to the memory used by the simulated process you're in)
I have no experience with writing compilers or operating systems, so the
approach may be quite naive, but I would be glad to hear some feedback where I'm
wrong
 
I

Ian Collins

Of course it is easy to add fork() on some platforms, but I think including
threads to the standard but fork() not would make fork() look like some 2nd
class threading, so people would always use threading instead of several
processes.

It's not a matter of 1st and 2nd class threading, it's a more matter of
code generation and optimisation, see Joshua Maurice's posts to this thread.

There's more to thread support than just creating threads.
 
A

Alan Curry

Threads affect the language a lot more than fork() does. It's a
lot easier to add fork() as an afterthought than it is to add
threads.

In other words, threads with protected memory (i.e. fork) get along well
with the language, and threads without protected memory (i.e. pthread)
completely screw it up and force the programmer and the compiler to do
much more complicated things to compensate for the anything-goes shared
address space.

And this is an argument *for* non-protected-memory threads?
 
I

Ian Collins

In other words, threads with protected memory (i.e. fork) get along well
with the language, and threads without protected memory (i.e. pthread)
completely screw it up and force the programmer and the compiler to do
much more complicated things to compensate for the anything-goes shared
address space.

And this is an argument *for* non-protected-memory threads?

Threads exist, get over it.

Some applications suit threads, some suit processes. Because process
don't required core language support they can be added purely as a
library extension.

Isn't it better to have the compiler do the complicated things rather
than force every programmer to do them?
 
T

tm

AFAIK Apple has a version of gcc that does this, but it's not in gcc
itself.

Ok. BTW, the proposed C++ support for closures looks
also interesting.


Greetings Thomas Mertes

--
Seed7 Homepage: http://seed7.sourceforge.net
Seed7 - The extensible programming language: User defined statements
and operators, abstract data types, templates without special
syntax, OO with interfaces and multiple dispatch, statically typed,
interpreted or compiled, portable, runs under linux/unix/windows.
 
J

James Kuyper

On 01/12/2011 04:52 PM, sandeep wrote:
....
In my opinion, compatibility with C++ is one of C's greatest assets. I
recommend the ISO C body to move towards these two goals viz-a-viz C++:

1. any program that is syntactically valid both in C and C++, should have
the same semantics in both languages

This program contains two modules and one shared header. It's very
carefully designed to make many different points in a program that is as
small as possible. I make no claim that this represents good programming
practice:

shared.h:
=========
#ifndef SHARED_H
#define SHARED_H

extern char tag;
extern int enumer[2];

typedef void voidvoid(void);

int Cnmtyp(void);
int Cfunc(voidvoid*);

#endif

First module:
=============
#ifdef __cplusplus
extern "C" {
#endif

#include "shared.h"

char tag = 0;

static int hidden(voidvoid *pfunc)
{
(*pfunc)();
tag = sizeof 'C' == sizeof(int);
return Cnmtyp() && enumer[0] && enumer[1];
}

int Cfunc(voidvoid* pfunc)
{
struct tag
{
enum { enumer, other } in;
int integer;
} out;

out.integer = sizeof(tag) == 1 && sizeof(enumer) == sizeof out.in;

return hidden(pfunc) && out.integer;
}

#ifdef __cplusplus
}
#endif

Second module:
==============
#ifdef __cplusplus
extern "C" {
#endif

#include "shared.h"

int enumer[2] = {0, 1};

static void Cppname_Cpptype(void)
{
enumer[0] = sizeof 'C' == 1;
return;
}

#ifdef __cplusplus
}
#endif

int Cnmtyp(void)
{
struct tag
{
enum { enumer, other } in;
int integer;
} out;

out.integer = sizeof(enumer) == 2 * sizeof(int);

return out.integer && sizeof(tag) == sizeof out;
}

static voidvoid Cppname_Ctype;

static void Cppname_Ctype(void) {
Cppname_Cpptype();
}

int main(void) {
return Cfunc(&Cppname_Ctype) && tag;
}

Both modules contain syntactically valid code: according to C99, C++98,
and C++03, together they constitute strictly conforming C code, and
well-formed C++ code. The behavior of code containing __cplusplus is
technically undefined under C90, but for most (all?) fully conforming
C90 compilers, the behavior is exactly as if it were not a reserved
identifier, and not a pre-#defined macro. For any such C90 compiler, the
only code that would otherwise constitute a syntax error will be dropped
by the #if's.

You can compile both modules in C, or both in C++; the resulting
executables are guaranteed by the relevant standards to exit with a
failure status, for quite different reasons in each case. If you compile
the first module in C, and the second in C++, and the two compilers are
compatible, then the modules can be linked together; in that case, the
executable will exit with success status. Unfortunately, if you do it
the other way around, they cannot be linked.

Why does it matter which language is used for each module? Because three
of the comparison operators are guaranteed to have a different value,
depending upon whether the module is compiled as C or C++. The other two
comparisons will have the same value in both languages only in the
unlikely event that sizeof(int)==1. I'll leave it as an exercise for the
reader to figure out why these statements are true.

Please note that, while this code is VERY contrived, it depends upon
very deep principles of the two languages. For every single comparison
operator in the above code, guaranteeing that it would be true in both
languages would break a lot of code in one of the two languages.

So, if you want the semantics of this program to be the same in both
languages, what should they be?
 
R

Rui Maciel

Joshua said:
Several reasons.

First, I think we'd all like an implemented and portable threading
interface so we don't have to roll our own abstraction layer.

That's what a standard is for. The POSIX threads standard is pretty clear
on it's purpose: to implement a standard API to handle threads. If some
people keep ignoring a standard for over 15 years then what good will it
do if yet another standard is defined to deal with this very same issue?

There's
a lot of subtle nuance in the several threading libraries which make
it non-trivial to wrap.

That's why we have for over a decade a standard for an API designed to
handle threads.


Second, threading really ought to be part of the programming language
standard as it directly affects and constrains the code generation of
the compiler. A library like a GUI doesn't impose any particular
noteworthy restrictions on the compiler, but threading is inextricably
tied to compilation, optimization, and code generation.

I don't believe this to be any relevant. There is a standard that defines
an API to handle threads. I don't see any reason why the people dedicated
in developing a programming language would be forced to ignore an API when
they try to add support for a particular feature.

Third, from my knowledge of win32 threads, pthreads, and the barriers
of the linux kernel, I personally very much welcome this new standard
as it's much more formalized.

What's wrong with pthreads? And what do you mean by "more formalized"?

There is such a lack of knowledge in the
community as to how threading actually works. I meet people every day
who think that volatile is still a portably useful threading
primitive. Trying to reason about how the compiler operate when
throwing inline assembly at it with pthreads is also quite difficult.
The new standard is much more complete, sane, and useful.

That's irrelevant. It has nothing to do with any API and everything to do
with the people in your anectodal example. A standard doesn't force any
knowledge on anyone remotely related to a subject, which means that
adopting a current standard or inventing a new one will have absolutely no
impact on this issue.

I've seen people using gcc inline assembly to do a read and write
barriers, and argue whether the "memory" clobber is used or not, and
whether volatile will make it work in the absence of the "memory"
clobber. With this new standard, you might even get better
optimization as opposed to gcc's current interface as the compiler
will be able to do something more fine grain than the correct "memory"
clobber, and it will still have the correct behavior unlike the case
of no "memory" clobber.

AFAIK, it has been standardized to be implementable on all hardware
such that "you don't pay for what you don't use". Specifically, if you
write your data dependent loads correctly in the C source, your code
will work on the DEC-alpha, and you won't suffer any performance
penalties where it's not needed such as the x86.

That's irrelevant. The pthreads standard defines an API. The
implementaton details are left to the programming language and underlying
platforms. If there is a need to define any behavior of a given
programming language then this issue should be dealt by the people who
dedicate their time to manage that programming language. Yet, defining
behavior which has been previously left undefined does not force anyone to
design a new standard API from scratch while ignoring an established
standard designed for this very purpose.


Rui Maciel
 
R

Rui Maciel

Ian said:
Library support and core language support are two different beasts.
While they both support portability, some desirable features require
language support.

It's quite possible to work on the definition of a programming language in
order to better support some features desired by some developers,
including those involved in developing libraries, without being forced to
bloat the standard by incorporating any definition on how exactly those
libraries should behave.

Do you object to the threading support in the C1x draft?

The question which must be asked regarding pushing a definition of a
particular library into the C standard is "why?" and not "why not?". Any
addition to a programming language must be thoroughly justified, which has
not been the case.

The C++ community has certainly embraced the support for threads in
C++0x as a long overdue feature for a modern programming language. I'm
really surprised people object to the additions to C.

Apples and oranges. There was no international standard that defined an
API to handle threads in C++. Adding to that, although it was possible to
handle threads with the pthreads library in a C++ program, there were
always a few issues plaguing it's use, which forced the programmer to jump
through a hand full of proverbial hoops just to make things work.

So, unequivocally the C++ programming language needed a dedicated standard
that defined a native C++ API for threads. Unfortunately the C++ people
failed to follow time-proven best practices on how to implement libraries
and simply made the mistake of bolting this new C++ threads standard onto
the definition of the C++ programming language.


Rui Maciel
 
R

Rui Maciel

Joshua said:
Well, I think that's more to do with that not all operating systems
natively support a Posix-like fork - eg: win32, whereas all current
threading models are sufficiency similar to allow standardization.

If I'm not mistaken, the reason behind Microsoft's failure to adopt
standard interfaces for basic features such as threading isn't due to any
technical issue that they failed to overcome.

Considering this, I don't believe that pushing a standard definition of a
particular API into the C standard will force Microsoft (and any other
company that shares their motivations) to offer a decent, standard API for
that particular feature.


Finally, see my other posts else-thread for other reasons which apply
to threads but don't apply to processes. Threading is inextricably
tied to code generation, so it really ought to be in the same standard
document that constrains the rest of the code generation of the
compiler, whereas the existence of and the use of processes don't
really constrain the code generation of a compiler.

If the C programming language needs any behavior to be defined in order to
be able to implement a particular library or a feature which is provided
by an underlying platform then it is clear that it is a good idea to
define whatever behavior needs to be defined. Yet, that doesn't force
anyone to push an entire definition of an API into the standard definition
of that particular programming language. Moreover, if we consider that
this API is designed to handle a feature which already benefits from an
API defined through a international standard for the past 15 years or so,
things become a bit more unjustifiable.


Rui Maciel
 
J

Joshua Maurice

That's what a standard is for.  The POSIX threads standard is pretty clear
on it's purpose: to implement a standard API to handle threads.  If some
people keep ignoring a standard for over 15 years then what good will it
do if yet another standard is defined to deal with this very same issue?  


That's why we have for over a decade a standard for an API designed to
handle threads.


I don't believe this to be any relevant.  There is a standard that defines
an API to handle threads.  I don't see any reason why the people dedicated
in developing a programming language would be forced to ignore an API when
they try to add support for a particular feature.


What's wrong with pthreads?  And what do you mean by "more formalized"?


That's irrelevant.  It has nothing to do with any API and everything to do
with the people in your anectodal example.  A standard doesn't force any
knowledge on anyone remotely related to a subject, which means that
adopting a current standard or inventing a new one will have absolutely no
impact on this issue.



That's irrelevant.  The pthreads standard defines an API.  The
implementaton details are left to the programming language and underlying
platforms.  If there is a need to define any behavior of a given
programming language then this issue should be dealt by the people who
dedicate their time to manage that programming language. Yet, defining
behavior which has been previously left undefined does not force anyone to
design a new standard API from scratch while ignoring an established
standard designed for this very purpose.

As opposed to a piecemeal reply, let me make it short.

First, pthreads threads is a highly informal standard compared to the
proposed C++ semantics. There are several dark corners in pthreads
where the behavior is less than clear. It's badly specified. The new
proposed C++0x standard goes a lot better in clarifying corner cases
of what does and does not work. Please see:
http://www.hpl.hp.com/techreports/2008/HPL-2008-56.pdf
for a comprehensive review of the new threading standard. There's a
couple of places in the doc which describe the ambiguity of the
current pthreads standard, and at least one point where nearly all
POSIX pthreads implementations are glaringly not conforming to the
pthreads standard (see: "3. Making Trylock Efficient" in the above
link).

Second, it's not complete. It doesn't specify Linux kernel calls read,
write, and data dependent barriers, what C++0x calls
memory_order_consume,
memory_order_acquire,
memory_order_release,
memory_order_acq_rel,
It also lacks a way to say "No, I really know what I'm doing, and this
race condition is harmless" which C++0x calls
memory_order_relaxed,
And to make everyone's life easier, you can specify that the memory
operation participates in the global ordering, aka that it's
"sequentially consistent"
memory_order_seq_cst
Posix pthreads doesn't support any of that except memory_order_acq_rel
(or is it memory_order_seq_cst?), which sometimes results in people
going to the assembly for what the Linux kernel calls read, write, and
data dependency barriers. This leads to fun conversations between
experts on what exactly is going on, such as:
http://groups.google.com/group/comp...read/thread/fcef57c539a42ef5/be98b8ef87ff64a4
Does the volatile do anything? Obviously not portably, but will it
make your compiler + implementation on your hardware produce the
correct results? Do you need gcc's "memory" clobber or not for that
inline assembly? Frankly, this kind of stuff isn't documented
anywhere. You could spend days talking to the actual compiler writers
and consult your chipsets assembly docs, but even after that you
probably won't know for sure. I for one think this is an entirely
unsatisfactory state of affairs.

I suppose you could spruce up pthreads to do this, but it seems that
they have not. I /think/ that the C and C++ committees have been in
contact with the POSIX pthreads people. How do the pthreads people
feel about this standardization? Why haven't they updated POSIX
pthreads to fix the known issues and more formalize their model, and
add read, write, data dependent barriers? I wonder if the POSIX people
thought it would be better to put this stuff in the C and C++
standards.

Third, I want portable threading that everyone supports. It's
unfortunate that a certain OS decides to not support it out of the
box. However, does it make sense to talk about pthreads conformance
without the broader scope of POSIX conformance? Windows will never be
POSIX conformant, but it might supply a conforming pthreads interface.
Is the POSIX pthreads standard set up to allow Windows to claim
"pthreads" compliance without any other part of POSIX?

Fourth, as a minor point, I still think that it makes sense to put
something so critical and inherent to compiler code generation into
the language standard and not leave it to a separate standard. It
would be ridiculous if malloc and friends were in a different standard
than the C standard, or if typedef was in a different standard than
the C standard. The same is true of threading. It's so integral to the
language from a user point of view and implementer point of view that
it ought to be in the same standard. (I would argue that the same is
true of "shared objects" aka "shared libraries" aka "DLLs".)
 
J

Joshua Maurice

If I'm not mistaken, the reason behind Microsoft's failure to adopt
standard interfaces for basic features such as threading isn't due to any
technical issue that they failed to overcome.  

Considering this, I don't believe that pushing a standard definition of a
particular API into the C standard will force Microsoft (and any other
company that shares their motivations) to offer a decent, standard API for
that particular feature.

Slightly out of context. That was a rationale for why threads should
go in, but POSIX fork should not. "Sufficiently similar on all
platforms" is a necessary requirement for standardization in the C and
C++ standards, but it's not a sufficient one.

I do admit that this was a rather compelling argument. If it just
became another "C++ export" or supported everywhere but windows, then
I agree it would be rather silly to do. (Apart from fixing all of the
problems in POSIX pthreads and adding read, write, and data dependent
barriers, of course.)

However, Herb Sutter seems to be all for this new threading API, and
hopefully he'll bring Microsoft along. Also, googling has found this
one link from Microsoft
http://www.infoq.com/news/2010/12/visualc-angst
which gives some hope that they actually will implement it, as opposed
to POSIX pthreads. So, at worst, it's a game of politics, and if it
takes moving threading from one standard to another to ensure a
portable API usable everywhere, I'll play the politics.
If the C programming language needs any behavior to be defined in order to
be able to implement a particular library or a feature which is provided
by an underlying platform then it is clear that it is a good idea to
define whatever behavior needs to be defined.  Yet, that doesn't force
anyone to push an entire definition of an API into the standard definition
of that particular programming language.

In the case of threading, there is no other way. In order to define
the necessary semantics of the C language, it's akin to just defining
the threading API. The same is true for POSIX pthreads. The
restrictions on a POSIX pthreads conforming implementation are made in
terms of the pthreads API and observable behavior.
Moreover, if we consider that
this API is designed to handle a feature which already benefits from an
API defined through a international standard for the past 15 years or so,
things become a bit more unjustifiable.

C++0x threads is much more than that. It's not just a refurbished
POSIX pthreads. We get what the Linux kernel calls read, write, and
data dependency barriers as well. We also get "sequentially
consistent" or "acquire and release" semantics, whichever POSIX
pthreads doesn't specify. (I forget which offhand.)

Also, again I ask: can you talk about POSIX pthreads compliance
without the context of a larger POSIX compliance? That is, can someone
claim "pthreads compliant" without any other POSIX compliance, or
would the POSIX people be unhappy and sue? A minor point, but an
interesting one in this game of politics.
 
C

Chris H

In message <[email protected]
..com> said:
Seed7 runs under Linux, Bsd, various Unix variants, Mac OS
and Windows.

What about VMS, MuCos, SAFERTOS, EmbOS, Sciopta, Integrity, ThreadX,
OSE, VXWorks, QNX, CMX, eCOS, OSEK, LynxOS, Nutrino, Nucleus, PikeOS
pSOS,Velocity and many others....
The source code of Seed7 is written in C and
can be compiled with gcc, MS visual C and the Borland C
compiler.

IAR, Keil, ARM, Cosmic, Bytecraft, ImagCraft, Crossware, IBM, Intel,
SUN,


SO basically he ports to Windows and UNIX and uses one of three
compilers... That is NOT "portable"
 
C

Chris H

Keith Thompson <kst- said:
My understanding is that there are several conforming C99
implementions. For example, Intel has claimed that their icc is
fully conforming, and I think the same claim has been made for
lcc-win; there are others (no gcc isn't one of them). (My use of
the word "claim" is not meant to cast doubt, merely to emphasize
that I haven't personally verified anything.)

I'm not disputing your main point that C99 adoption has been slow.

Thanks... So Intel, Lcc and It think Sun That is three compilers out of
dozens. I think you are probably looking at less than 3% take up of C99
as a full implementation which is my point.

C90 standardised what the industry did. Everyone went ISO-C90 compliant
very quickly.

C99 added a whole lot of "cool" and "nice" things that no one really
wanted or needed. At least not enough for anyone to spend any time and
money on them.
 
B

BartC

Chris H said:
In message <[email protected]


What about VMS, MuCos, SAFERTOS, EmbOS, Sciopta, Integrity, ThreadX,
OSE, VXWorks, QNX, CMX, eCOS, OSEK, LynxOS, Nutrino, Nucleus, PikeOS
pSOS,Velocity and many others....


IAR, Keil, ARM, Cosmic, Bytecraft, ImagCraft, Crossware, IBM, Intel,
SUN,


SO basically he ports to Windows and UNIX

And MacOS.
and uses one of three
compilers... That is NOT "portable"

It's pretty good going. The restriction on compilers seems to be be to do
with having to provide specific makefiles for each.

What does it mean exactly to write a portable application in C? Surely you
can't expect someone (especially of free software) to test on dozens on
different compilers and dozens of different architectures? Who does?

Testing on a small number of different systems I'd have thought would at
least show it's not tied to one OS, one compiler, one architecture, a good
prerequisite for portability.

And are there any good examples of sizeable portable C apps, that do run on
*all* of those architectures and compilers you mentioned? (And if there are,
my bet is they would largely consist of a mess of conditional code,
conditional makefiles and conditional scripts.)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads


Members online

No members online now.

Forum statistics

Threads
474,083
Messages
2,570,591
Members
47,212
Latest member
RobynWiley

Latest Threads

Top