Topic: Reentrancy in the C++ standard


Author: rfg@netcom.com (Ronald F. Guilmette)
Date: Fri, 19 Nov 1993 10:07:06 GMT
Raw View
In article <CGJuyr.6LK@microsoft.com> jimad@microsoft.com (Jim Adcock) writes:
>In article <1993Nov9.160304.28444@csrd.uiuc.edu> harrison@sp1.csrd.uiuc.edu (Luddy Harrison) writes:
>
>|The portability of C++ programs may not be in the interest of Microsoft,
>
>Microsoft would seem to disagree.  The Microsoft marketing model seems
>to be: Let us port our Windowing system and/or OS to your machine, then
>you and you application vendors can write to that particular GUI.

Thanks for setting us straight Jim.

It does appear that Microsoft has a stong interest in portability... as
long as people are porting their code *to* some Microsoft OS and/or GUI
(rather than away from one).

So I guess that the portability of C++ programs *is* in the interests of
Microsoft (contrary to what Luddy Harrison claimed).

:-)

--

-- Ronald F. Guilmette, Sunnyvale, California -------------------------------
------ domain address: rfg@netcom.com ---------------------------------------
------ uucp address: ...!uunet!netcom.com!rfg -------------------------------




Author: bagpiper@netcom.com (Michael Hunter)
Date: Mon, 8 Nov 1993 05:05:12 GMT
Raw View
Ronald F. Guilmette (rfg@netcom.com) wrote:
(flame-bait removed....)
: In article <2b2elb$qgg@nic.lth.se> dag@control.lth.se (Dag Bruck) writes:
: >Steve Vinoski and I have tried to move the C++ standards committee a
: >short distance in the "right" direction.
: Your idea of the "right direction" and mine differ greatly.
: >...  I think it is unrealistic to
: >require that every C++ implementation should have support for reentrancy.
: On what exactly do you base this bizzare claim?
The face the machines running messy dog surpass the sum total of all other
machines on earth.  The fact the well over 90% of the people writting code
for messy dog (other wise known as shit) don't give a shit about
reentrancy.
: I'm forced to point out that due to its history, everything in C++ can
: be implemented in C, and that the ANSI/ISO C standard *requires* C
: implementations to generate reentrant code.  If this requirement can
Yes...c implementation *can* generate reentrant code, but as it has been
pointed out there are ways of coding algorithme that are unreentrantizeable.
(strtok in ansi c is an example.)
: be met by C implementations (which it obviously can) what evidence
: (if any) would to offer to support the strange notion that reentrancy
: is something which CANNOT be supported in C++?
I havn't seem anything but assertions that exceptions, signals, etc.,
can be implemented in a reentrant way.  Add to that the fact that c++
isn't a standard yet makes me think that reentrancy could be something that
might have certain tradeoffs.  That gets back to the point that some
implementation might not want to support it.  I personally don't want to go
back to the days of writting flight code in Ada because the DOD said I had
do draging along a whole load of overhead that I would never use in a
RT system just becuase every impl had to have it to be "standard".
: Are you seriously claiming that this *must* be an area in which C++ will
: actually end up being LESS powerful that C?
I never heard him say that.  The almost subset of c++ that is c should be
as c-like as possible (I think BS had a way better way of saying that).
==> that subset would be reentrant.  It would only be when you bit off
on something that is "new" that you might lose something else (trade-off).
: Are you and the X3J16 committee really prepared to deviate (yet again)
: from compatability with ANSI C in such a dramatic way?  Is C++ really
: going to break all of that existing C code which RELIES upon the
: assumption of reentrancy??
What all 1% of the code out there? I write a fair amount of RT  and multi-
threaded code and I don't think much more than 1% of my code assumes
reentrancy.

I think that reentrancy and expecially the part that relates to being able
to implemented a standard compliant c++ compilar that can also exist in a
multi-threaded environment is important.  On the other hand, if it means
handicapping the rest of the users I personally would be totally against
it.

: -- Ronald F. Guilmette, Sunnyvale, California -------------------------------

  Michael Hunter
  BAGPIPER@NETCOM.COM




Author: jimad@microsoft.com (Jim Adcock)
Date: Mon, 8 Nov 1993 20:11:08 GMT
Raw View
In article <1993Nov4.220148.27027@csrd.uiuc.edu> harrison@sp1.csrd.uiuc.edu (Luddy Harrison) writes:
>rmartin@rcmcon.com (Robert Martin) writes:
|I was joking of course, but it made me chuckle to see the argument
|being made that C++ should be kept simple and small for the sake
|of embedded systems (!) while at the same time all the language
|features known to mankind and many never dreamt of by mankind
|are being shoveled wholesale into the standard.

I did not argue that C++ should be kept simple and small for the sake
of embedded systems, rather I argued that all C++ should not be required
to be complicated fat and large for the sake of those people who want
to write multithreaded reentrant code.  There are people and operating
systems where such choices are appropriate, and vendors should be free
to offer reentrant code generators and libraries for C++ users in such
environments.  But not all C++ users are writing in or for such
environments, and these other C++ users should not be hosed just for
the sake of naive concepts of 'portability' on the part of some people
who want to write such reentrant code.  'Naive' because even if C++
mandated reentrant libraries their code *still* isn't going to run on
toaster ovens.

|I had the same thought as you, about toaster ovens as real-time
|multithreaded applications.  Suppose the toaster oven is displaying
|the time on an analog clock rendered on an LCD display using floating
|point routines in the library, when I walk up and toss in an Eggo.
|Bang, we're in the signal handler (SIGEGGO) trying to compute the
|optimal rate of defrost for an Eggo, again using floating point
|routines in the library.  Whoops - they're not reentrant - the Eggo
|gets torched and we have to reboot the toaster oven.

In my humble experience, people writing for "realtime toaster ovens" would
avoid using floating pt, would certainly not use floats in sigs nor
interrupts, wouldn't use sigs period, would use explicit suspends rather
than true multithreading, etc.  When one C++ user group dictates
"the" solution, they in turn prevent C++ from being usable to other
groups.  Writing 'portable' code in C/C++ was never intended to be
a freebie.  It was never intended to even be easy.  The intent was to
allow writing portable code to be *possible*  -- for those few extremely
motivated library writers whose job it is to write and market portable
code.  The vast majority of people writing C/C++ code do not write
portable code, and have no need to write very portable code.  On the
contrary, they typically have strong reasons to want to target only
a few platforms, have their code be reasonably portable to those
platforms -- and want their code to be as small as possible and as
fast as possible -- on those platforms.  Insisting too much out of
all implementations destroys the traditions of C/C++.





Author: harrison@sp1.csrd.uiuc.edu (Luddy Harrison)
Date: Tue, 9 Nov 93 16:03:04 GMT
Raw View
jimad@microsoft.com (Jim Adcock) writes:

>Writing 'portable' code in C/C++ was never intended to be
>a freebie.  It was never intended to even be easy.  The intent was to
>allow writing portable code to be *possible*  -- for those few extremely
>motivated library writers whose job it is to write and market portable
>code.

Good heavens!  Is this all the portability that can be expected
from a high-level language like C++?!  Are you saying that libraries
are to be the only kind of programs that are portable?

>The vast majority of people writing C/C++ code do not write
>portable code, and have no need to write very portable code.  On the
>contrary, they typically have strong reasons to want to target only
>a few platforms, have their code be reasonably portable to those
>platforms -- and want their code to be as small as possible and as
>fast as possible -- on those platforms.  Insisting too much out of
>all implementations destroys the traditions of C/C++.

I suppose it must be true that the "vast majority" of people writing C++
are writing programs for MS-DOS.  Certainly Microsoft cannot be expected
to work hard to help those people port their applications, but are you
certain that those programmers are delighted with that situation, that
they prefer that their code not be portable?  This seems to be what
you are saying.

The portability of C++ programs may not be in the interest of Microsoft,
but it is difficult for me to accept that it is not in the interest
of the user community and of the standardization effort.  If standardization
does not mean portability, what does it mean?

-Luddy Harrison




Author: jimad@microsoft.com (Jim Adcock)
Date: Mon, 8 Nov 1993 19:14:24 GMT
Raw View
In article <1993Nov4.171154.2622@rcmcon.com> rmartin@rcmcon.com (Robert Martin) writes:
|I am not sure that Jim really wants GC in toaster ovens.  From my
|point of view, however, a toaster oven is an embedded real time
|system that could easily be multi-threaded.

I neither want GC in toaster ovens nor reentrant libraries in toaster
ovens.  Nor do I not not want.  What I want is the ability of users
of C++ to CHOOSE the approaches they take to solving their problems,
as opposed to having those solution dictated by people who have not
a clue what those C++ users are trying to do.  Therefore I am against
any requirement that the Standard C Standard Libraries be redefined
to be *required* to be reentrant in C++.  I don't think the C++ committee
has any business redefining ANSI/ISO Standard Libraries in the first place.
Therefore I believe the *choice* as to whether a user of C++ uses a
reentrant set of libraries or not should be left to the user -- and by
implication to the library vendor that they *choose*.

[[Note that what libraries are reentrant or not is a very different
 issue from what code generation features a compiler has towards or
 against reentrancy]]

Likewise I am against certain silly little hacky restrictions built
into the language that act against C++ users making other major
*choices* about how they use the language.  One example being that
cast between ptr/ints that makes GC implementations more difficult
and restrictive.  Or restrictions that force users towards using
pointers in preference to references, etc.





Author: greg@guru.qualcomm.com (Greg Noel)
Date: 10 Nov 1993 02:35:04 GMT
Raw View
In article <2ba9p4$m4t@nic.lth.se> dag@control.lth.se (Dag Bruck) writes:
>That still doesn't answer my question: is "p++" reentrant?  Does the
>C standard guarantee that this operation is atomic?

Not to pick on Dag particularly, but that isn't the right question.  It's
possible to write non-reentrant code in any language, simply by refering to
variables without suitable synchronization.  If you write "p++" on a static
variable (or even store something in a static variable and expect to be able
to recover the same value later), you have written something fundamentally
non-reentrant, so you must provide the necessary synchronization.

(The question as to whether it is _atomic_ is yet another question; given
the range of hardware possibilities, I don't know what promises a standard
could possibly make on that subject.)

A better question would be, "is _switch_ reentrant"?  That is, is the code
generated by the compiler fundamentally non-reentrant for a basic operation?

In this case, it's not a trivial question, since a common implementation
technique for the switch statment is to have two arrays, one containing the
switch values and one containing the transfer points.  The default case is
handled by having one extra slot in the tables at the end.  The code emited
by the compiler stores the switch value in the extra slot, loops through the
array looking for a matching value, and then jumps through the same offset
in the second table.  Since no additional check is needed to test for the
end of the array, this is faster than code that has to include that check.

On a PDP-11, the loop was two short instructions and the jump took one more:
 cmp (r2)+,r0 compare and auto-increment
 bne $-2  branch if not found
 jmp (I forget the syntax for this jump mode)
Because of the way instruction fetching works, the two instructions will
always be in the cache, so all of memory bandwidth is used fetching switch
values.  For a small switch table with widely-scattered values, this was as
fast as you could get---even faster than translating it into if-else tests.

Note the distinction here: the problem is with code that the compiler is
writing for you---if it so much as uses static temporaries when it has to
spill registers, your code is not reentrant, no matter what you do.  The
point is that one would like to have language in the standard that forbade
(or at least made optional) emitting fundamentally non-reentrant code such
as the examples above.

Hope this helps,
--
-- Greg Noel, Unix Guru         greg@qualcomm.com  or  greg@noel.cts.com




Author: ross@utopia.druid.com (Ross Ridge)
Date: Wed, 10 Nov 1993 09:02:49 GMT
Raw View
dag@control.lth.se (Dag Bruck) writes:
>...  I think it is unrealistic to require that every C++ implementation
>should have support for reentrancy.

Ronald F. Guilmette (rfg@netcom.com) writes:
>On what exactly do you base this bizzare claim?

bagpiper@netcom.com (Michael Hunter) provides new flame bait with:
>The face the machines running messy dog surpass the sum total of all other
>machines on earth.

Only if your definition of machines is limited to personal computers.
But the amount machines code might run on is irrelevant.

>The fact the well over 90% of the people writting code for messy dog
>(other wise known as shit) don't give a shit about reentrancy.

Not true, reentrancy is an important issue when writing critical error
and CTRL-Break handlers which are important parts of most MS-DOS
applications.

Ronald F. Guilmette (rfg@netcom.com) writes:
>I'm forced to point out that due to its history, everything in C++ can
>be implemented in C, and that the ANSI/ISO C standard *requires* C
>implementations to generate reentrant code.  If this requirement can

bagpiper@netcom.com (Michael Hunter) continues:
>Yes...c implementation *can* generate reentrant code, but as it has been
>pointed out there are ways of coding algorithme that are unreentrantizeable.
>(strtok in ansi c is an example.)

Unfortunately Ronald Guilmette has been a bit loose with the phrase
"generate reentrant code".  What he means by it is "generate functions
that are reentrant when they meet the conditions defined in the ANSI/ISO
C standard."  While an implemenation of strtok written in standard C
isn't guaranteed to be reentrant by the ANSI C standard there are
functions the are guaranteed to be reentrant and it would be nice if
these functions were also guaranteed to be reentrant in the future ANSI
C++ standard.

      Ross Ridge





Author: sg3235@sw1sta.sbc.com (Stephen Gevers)
Date: 11 Nov 93 15:01:31 GMT
Raw View
It seems to me in following this thread that people are arguing two different
points!

Point #1:
 The Standard libraries should be reentrant

Point #2:
 The code generated by the C++ compilers should be reentrant.

First of all, I think that the first issue should be handled as the C
standard is handled.  All library functions do not need to be reentrant.
However, it should be clear if they are not.

The second point is more important.  If the code I write *can* be compiled
to be reentrant, it should be compiled that way.  In other words, the C++
compiler shouldn't compile my code in such a way as to remove any reentrant
capabilities that I coded into it.  I'm not saying that it should stand on
its head trying to make non-reentrant code reentrant.  Using point #1, if I
want something to be reentrant, don't use routines out of the standard library
that aren't reentrant!  I can't imagine why anyone would write a compiler
that would cause code to not be reentrant on its own, but I do think that to
do so should be unacceptable by the standard.

Stephen Gevers
sg3235@shelob.sbc.com




Author: henry@zoo.toronto.edu (Henry Spencer)
Date: Thu, 11 Nov 1993 19:01:05 GMT
Raw View
In article <1993Nov10.090249.3769@utopia.druid.com> ross@utopia.druid.com (Ross Ridge) writes:
>>The face the machines running messy dog surpass the sum total of all other
>>machines on earth.
>
>Only if your definition of machines is limited to personal computers.

Theorem:  the fraction of computers running MSDOS can never exceed 50%.

Proof:  every MSDOS computer is accompanied by a non-MSDOS computer -- the
one in the keyboard.  Typically, in fact, it is accompanied by several
non-MSDOS computers, since add-on boards are frequently intelligent
enough to have CPUs, but the keyboard CPU is pretty well guaranteed.

>But the amount machines code might run on is irrelevant.

Agreed.
--
Study it forever and you'll still       | Henry Spencer @ U of Toronto Zoology
wonder.  Fly it once and you'll know.   |  henry@zoo.toronto.edu  utzoo!henry




Author: rfg@netcom.com (Ronald F. Guilmette)
Date: Mon, 15 Nov 1993 08:16:49 GMT
Raw View
In article <1993Nov10.090249.3769@utopia.druid.com> ross@utopia.druid.com (Ross Ridge) writes:
>Unfortunately Ronald Guilmette has been a bit loose with the phrase
>"generate reentrant code".  What he means by it is "generate functions
>that are reentrant when they meet the conditions defined in the ANSI/ISO
>C standard."  While an implemenation of strtok written in standard C
>isn't guaranteed to be reentrant by the ANSI C standard there are
>functions the are guaranteed to be reentrant and it would be nice if
>these functions were also guaranteed to be reentrant in the future ANSI
>C++ standard.

Isn't that exactly what I said?  (Nevermind.  No need to waste bandwidth
following up on my retorical question.)  Anyway, if that's not what I said,
it is nontheless essentially what I meant.

--

-- Ronald F. Guilmette, Sunnyvale, California -------------------------------
------ domain address: rfg@netcom.com ---------------------------------------
------ uucp address: ...!uunet!netcom.com!rfg -------------------------------




Author: jimad@microsoft.com (Jim Adcock)
Date: Mon, 15 Nov 1993 20:16:01 GMT
Raw View
In article <1993Nov9.160304.28444@csrd.uiuc.edu> harrison@sp1.csrd.uiuc.edu (Luddy Harrison) writes:
>jimad@microsoft.com (Jim Adcock) writes:
|
|>Writing 'portable' code in C/C++ was never intended to be
|>a freebie.  It was never intended to even be easy.  The intent was to
|>allow writing portable code to be *possible*  -- for those few extremely
|>motivated library writers whose job it is to write and market portable
|>code.
|
|Good heavens!  Is this all the portability that can be expected
|from a high-level language like C++?!  Are you saying that libraries
|are to be the only kind of programs that are portable?

No.  I am saying that the historical intent of the design of the C/C++
languages was to support *efficient* programming with a secondary
goal of enabling portable programming -- at some cost and effort and
intelligence on the part of the programmer.  And that yes, C/C++
is primarily designed with *libraries* as the unit of portability.
Thank god.

|>The vast majority of people writing C/C++ code do not write
|>portable code, and have no need to write very portable code.  On the
|>contrary, they typically have strong reasons to want to target only
|>a few platforms, have their code be reasonably portable to those
|>platforms -- and want their code to be as small as possible and as
|>fast as possible -- on those platforms.  Insisting too much out of
|>all implementations destroys the traditions of C/C++.
|
|I suppose it must be true that the "vast majority" of people writing C++
|are writing programs for MS-DOS.

Probably still true, though today most of the sales volume is in Windows.

|Certainly Microsoft cannot be expected
|to work hard to help those people port their applications, but are you
|certain that those programmers are delighted with that situation, that
|they prefer that their code not be portable?  This seems to be what
|you are saying.

No, I simply try to speak the historical truth about the goals of the
language.  Such history is documented in ANSI X3.159-1989 Introduction
to the Rationale for example,  which clearly states that C code is
intended to be both portable and non-portable, and that the C standard
was explicitly written to keep both distinction in mind, leading to
the distinction between 'conforming' and 'strictly conforming' programs
for example.

Re Microsoft, I am not, nor do I speak for Microsoft, but note with regards
portability: DOS programs run on NT no recompile , OS/2 programs run on NT
no recompile, Posix program run on NT with compile, Win3.1 programs run on
NT no recompile.  MFC programs run NT no recompile, native NT with recompile....

|The portability of C++ programs may not be in the interest of Microsoft,

Microsoft would seem to disagree.  The Microsoft marketing model seems
to be: Let us port our Windowing system and/or OS to your machine, then
you and you application vendors can write to that particular GUI.
The language is not the issue here.  The difficulty
lies in the differences between operating systems, and more importantly
the GUI models implemented on those systems.  The compiler and language
differences are small potatoes by comparison.

|but it is difficult for me to accept that it is not in the interest
|of the user community and of the standardization effort.  If standardization
|does not mean portability, what does it mean?

Standardization means that 1) compiler writers know what they are suppose
to be writing a compiler for and 2) programmers know what they are
suppose to be writing to and 3) library writers know when and when not
they are writing strictly portable sections of code.  Again writing
portable libraries typically means knowing when NOT to write
strictly portable code.





Author: harrison@sp1.csrd.uiuc.edu (Luddy Harrison)
Date: Wed, 3 Nov 93 21:01:05 GMT
Raw View
jimad@microsoft.com (Jim Adcock) writes:

>C *and* C++ get used for a lot of non-systems non-apps non-un*x work.
>For example they both get used in toaster ovens.  I see no reason why
>every library vendor who provides a set of the libraries suitable for
>toaster ovens needs to make those libraries reentrant.  On the contrary,
>such would seem to be mainly dependent on the kind of system
>the libraries' are designed to run on, which in turn would argue that
>these are NOT the kinds of things the C++ standard should be specifying.

You folks at Microsoft certainly have interesting taste in language
features.  Toaster ovens with garbage collection and non-reentrant
libraries.  Hmm.

(;

-Luddy Harrison




Author: fmh@monsoon.com (Francis Hogle)
Date: Wed, 03 Nov 93 11:59:01 EST
Raw View
dag@control.lth.se (Dag Bruck) writes:

> >.... the ANSI/ISO C standard *requires* C
> >implementations to generate reentrant code.  If this requirement can
> >be met by C implementations (which it obviously can) what evidence
> >(if any) would to offer to support the strange notion that reentrancy
> >is something which CANNOT be supported in C++?
> >
> >....  There *are* ways to test code to see
> >if it is reentrant or not.
>
> Is the following code reentrant?
>
>  extern int* p;
>
>  void incr() { p++; }
>
> How do you test it?

  Irrelevant.  What is important is that the implementation allows you
to end up with reentrant code.  I don't want an implementation calling
my platform's synchonization services every time I access memory.  But
by the same token, when I go to the trouble of using those services in
my code, I don't want the compiler to spit out support code that
prevents the result from being reentrant.
  C is an easy language to deal with, beacuse it doesn't really do
much behind the scenes.  You might have to be careful if your calling
convention passes parameters somewhere other than the stack (some
floating point implementations...), but on the whole, not much outside
of what the programmer wrote is implied by the grammar.
  C++ does a lot more on the programmers behalf, but even then, most of
it involves calling code which the user controls (constructors,
destructors, assignment and casting operators...), and the user can
make that code reentrant with respect to a particular environment.
  Exceptions are a new addition to most compilers that support them.
Obviously, they have an uncommon set of requirements.  I can say it
would be REALLY NICE to have exceptions work predictably in
multithreaded environments.  I can also say that I probably won't use
them if I can't have this confidence.

-Francis


Francis Hogle
fmh@monsoon.com




Author: dag@control.lth.se (Dag Bruck)
Date: 4 Nov 1993 07:08:20 GMT
Raw View
In <comp.std.c++,comp.std.c> fmh@monsoon.com (Francis Hogle) writes:
>dag@control.lth.se (Dag Bruck) writes:
>> Is the following code reentrant?
>>
>>  extern int* p;
>>
>>  void incr() { p++; }
>>
>> How do you test it?
>
>  Irrelevant.  What is important is that the implementation allows you
>to end up with reentrant code.

That still doesn't answer my question: is "p++" reentrant?  Does the
C standard guarantee that this operation is atomic?


     -- Dag




Author: ag129@ucs.cam.ac.uk (Alasdair Grant)
Date: Thu, 4 Nov 1993 13:35:24 GMT
Raw View
In article <2ba9p4$m4t@nic.lth.se> dag@control.lth.se (Dag Bruck) writes:
>That still doesn't answer my question: is "p++" reentrant?
>Does the C standard guarantee that this operation is atomic?

That's two questions, and they are different.

p++ as a piece of code is reentrant because you can have two threads
executing it at the same time.  Whether or not it has the effect you
want depends on exactly what p is, and whether the increment is atomic
(and on what you want!).  But as a piece of code it's reentrant.
All the Standard says on this point is that if p is automatic (and
presumably if you haven't exported its address to a static variable)
then p++ will appear to be an atomic operation even when you have
signal handlers.

As for the second question, I think the answer is 'no' but it depends
how seriously you take "the value of the operand is incremented"
[3.3.2.4] and whether you believe p++ is identical to p += 1, which is
defined [3.3.16.2] to differ from p = p + 1 only in lvalue evaluation.
I don't think you can say p = p + 1 is atomic, so neither is p++.

In fact, C doesn't even guarantee atomic _access_ to variables (e.g.
if it takes you two instructions to load a value of type 'float' there
is no guarantee they refer to the same number).  This is what
sig_atomic_t is for; as the Rationale says:
  "about the only thing a strictly conforming program can do in a
   signal handler is to assign a value to a volatile static variable
   which can be written uninterruptedly and promptly return.
   (The header <signal.h> specifies a type sig_atomic_t which can
   be so written.)"
Note that this is atomic _access_; incrementing a value of sig_atomic_t
is not guaranteed to be atomic.  For that you would need hardware
support or a complex algorithm that could take an arbitrary amount of
time.  It has to be said that in a real system you need several levels
of atomicity; for example atomicity in the presence of channel programs
(i.e. DMA) may be stronger than symmetric-multiprocessor atomicity,
which may be stronger than mere uniprocessor multitasking atomicity.
Or to put it another way, whatever the vague words in the standards
mean, there aren't enough of them to mean anything useful.
--
Alasdair Grant




Author: claest@imec.be (Tony Claes)
Date: Thu, 4 Nov 1993 13:37:10 GMT
Raw View
In article <2ba9p4$m4t@nic.lth.se> dag@control.lth.se (Dag Bruck) writes:
>In <comp.std.c++,comp.std.c> fmh@monsoon.com (Francis Hogle) writes:
>>dag@control.lth.se (Dag Bruck) writes:
>>> Is the following code reentrant?
>>>
>>>  extern int* p;
>>>
>>>  void incr() { p++; }
>>>
>>> How do you test it?
>>
>>  Irrelevant.  What is important is that the implementation allows you
>>to end up with reentrant code.
>
>That still doesn't answer my question: is "p++" reentrant?  Does the
>C standard guarantee that this operation is atomic?
>

This is not reentrant.

To my knowledge, no practical language garantees that "statements" are
an atomic piece of code during execution.
Every tread of execution can be preempted at any moment.




Tony







Author: schouten@sp51.csrd.uiuc.edu (Dale Schouten)
Date: 04 Nov 1993 16:21:09 GMT
Raw View
In article <ag129.375.2CD904FF@ucs.cam.ac.uk> ag129@ucs.cam.ac.uk (Alasdair Grant) writes:
>>That still doesn't answer my question: is "p++" reentrant?
>
>p++ as a piece of code is reentrant because you can have two threads
>executing it at the same time.  Whether or not it has the effect you
>want depends on exactly what p is, and whether the increment is atomic
>(and on what you want!).  But as a piece of code it's reentrant.

This is a little confusing, because if you're saying that it's
reentrant but may not act like you expect, then I question the
definition of `reentrant'.

>All the Standard says on this point is that if p is automatic (and
>presumably if you haven't exported its address to a static variable)
>then p++ will appear to be an atomic operation even when you have
>signal handlers.

This clarifys things a lot, and makes a lot of sense.  If this is
correct, then my only question is why C++ doesn't make the same claim.
I mean, reentrancy being just restricted to *locally accessible*
*automatic* variables, not asking reentrancy for member functions
which modify class variables or anything.  Am I still misunderstanding
something?

Dale Schouten
schouten@uiuc.edu




Author: danpop@cernapo.cern.ch (Dan Pop)
Date: Thu, 4 Nov 1993 16:36:36 GMT
Raw View
In <2ba9p4$m4t@nic.lth.se> dag@control.lth.se (Dag Bruck) writes:

>In <comp.std.c++,comp.std.c> fmh@monsoon.com (Francis Hogle) writes:
>>dag@control.lth.se (Dag Bruck) writes:
>>> Is the following code reentrant?
>>>
>>>  extern int* p;
>>>
>>>  void incr() { p++; }
>>>
>>> How do you test it?
>>
>>  Irrelevant.  What is important is that the implementation allows you
>>to end up with reentrant code.
>
>That still doesn't answer my question: is "p++" reentrant?  Does the
>C standard guarantee that this operation is atomic?
>
If this is not a rhetorical question, the answer is no. The only
operation which is guaranteed to be atomic is assignment to a volatile
static variable of sig_atomic_t type.

Dan
--
Dan Pop
CERN, L3 Experiment
Email: danpop@cernapo.cern.ch
Mail:  CERN - PPE, Bat. 21 1-023, CH-1211 Geneve 23, Switzerland




Author: rmartin@rcmcon.com (Robert Martin)
Date: Thu, 4 Nov 1993 17:11:54 GMT
Raw View
harrison@sp1.csrd.uiuc.edu (Luddy Harrison) writes:

>jimad@microsoft.com (Jim Adcock) writes:

>>C *and* C++ get used for a lot of non-systems non-apps non-un*x work.
>>For example they both get used in toaster ovens.  I see no reason why
>>every library vendor who provides a set of the libraries suitable for
>>toaster ovens needs to make those libraries reentrant.  On the contrary,
>>such would seem to be mainly dependent on the kind of system
>>the libraries' are designed to run on, which in turn would argue that
>>these are NOT the kinds of things the C++ standard should be specifying.

>You folks at Microsoft certainly have interesting taste in language
>features.  Toaster ovens with garbage collection and non-reentrant
>libraries.  Hmm.

>(;

I am not sure that Jim really wants GC in toaster ovens.  From my
point of view, however, a toaster oven is an embedded real time
system that could easily be multi-threaded.

--
Robert Martin       | Design Consulting   | Training courses offered:
Object Mentor Assoc.| rmartin@rcmcon.com  |   Object Oriented Analysis
2080 Cranbrook Rd.  | Tel: (708) 918-1004 |   Object Oriented Design
Green Oaks IL 60048 | Fax: (708) 918-1023 |   C++




Author: harrison@sp1.csrd.uiuc.edu (Luddy Harrison)
Date: Thu, 4 Nov 93 22:01:48 GMT
Raw View
rmartin@rcmcon.com (Robert Martin) writes:

>I am not sure that Jim really wants GC in toaster ovens.  From my
>point of view, however, a toaster oven is an embedded real time
>system that could easily be multi-threaded.

I was joking of course, but it made me chuckle to see the argument
being made that C++ should be kept simple and small for the sake
of embedded systems (!) while at the same time all the language
features known to mankind and many never dreamt of by mankind
are being shoveled wholesale into the standard.

I had the same thought as you, about toaster ovens as real-time
multithreaded applications.  Suppose the toaster oven is displaying
the time on an analog clock rendered on an LCD display using floating
point routines in the library, when I walk up and toss in an Eggo.
Bang, we're in the signal handler (SIGEGGO) trying to compute the
optimal rate of defrost for an Eggo, again using floating point
routines in the library.  Whoops - they're not reentrant - the Eggo
gets torched and we have to reboot the toaster oven.

-Luddy Harrison




Author: ag129@ucs.cam.ac.uk (Alasdair Grant)
Date: Thu, 4 Nov 1993 22:06:17 GMT
Raw View
In article <SCHOUTEN.93Nov4102109@sp51.csrd.uiuc.edu> schouten@sp51.csrd.uiuc.edu (Dale Schouten) writes:
>>>That still doesn't answer my question: is "p++" reentrant?
>>
>>p++ as a piece of code is reentrant

>This is a little confusing, because if you're saying that it's
>reentrant but may not act like you expect, then I question the
>definition of `reentrant'.

"Reentrant" means that a bit of code is trying to do "something" and
continues to do "it" even if it is being executed twice at the same time.
But you have to define what you want to do; e.g.
  void myfun (void) { static int x; x = 0; x++; assert(x == 1); }
is not reentrant, but you can't just say "x++ is not reentrant"
because it's not atomic.  The specification of x++ is that it is the
same as x = x + 1 which takes a value out of x, adds one to that value,
and then puts it back into x.  It meets _that_ specification even when
two things are doing it at the same time.  If you specified that the
update had to be atomic, then to keep it reentrant you would have to
modify the code (e.g. make it part of a monitor) or add to the
specification the fact that x was private (e.g. automatic and its
address had not been exported to anything whose specification said it
might modify it, etc.  But if you just say reentrant == atomic you lose
a useful distinction.  Reentrancy is a property of code, not data.

If the problem you are worried about would still happen if the data
was being accessed by two _different_ functions, e.g.
         extern int x;
 funa.c: void a (void) { x++; }
 funb.c: void b (void) { x++; }
then calling it reentrancy is confusing.  Even if a and b serialised
themselves, there would still be a race condition between them.




Author: henry@zoo.toronto.edu (Henry Spencer)
Date: Fri, 5 Nov 1993 16:55:36 GMT
Raw View
In article <2ba9p4$m4t@nic.lth.se> dag@control.lth.se (Dag Bruck) writes:
>>>  extern int* p;
>>>
>>>  void incr() { p++; }
>
>That still doesn't answer my question: is "p++" reentrant?  Does the
>C standard guarantee that this operation is atomic?

No, it doesn't, and there are a good number of systems where it's not.

As others have pointed out, since this operation typically involves two
memory accesses, it won't be atomic against things like DMA I/O without
doing something machine-specific as a defence.  Furthermore, on many
modern machines those two memory accesses are done by two separate
instructions, which means it isn't atomic against context switches either.
(NFS at one point had a number of bugs traceable to the assumption that
++ was an atomic operator.  Since the windows of vulnerability were quite
small, the problem wasn't reproduceable except under very heavy load.)
--
Study it forever and you'll still       | Henry Spencer @ U of Toronto Zoology
wonder.  Fly it once and you'll know.   |  henry@zoo.toronto.edu  utzoo!henry




Author: dag@control.lth.se (Dag Bruck)
Date: 1 Nov 1993 07:42:35 GMT
Raw View
In <comp.std.c++> rfg@netcom.com (Ronald F. Guilmette) writes:
>
>But if *I* had *my* druthers, I'd druther that the ANSI C standard had
>mandated that all library function which *could* be reentrant *must* be
>reentrant.  (And I hope that this is one area in which X3J16 will have
>more intestinal fortutude than did X3J11.)

Steve Vinoski and I have tried to move the C++ standards committee a
short distance in the "right" direction.  Unfortunately, our proposal
has not made it into the working paper yet.

There are in my view two fundamental problems that must be solved:

 1.  What do we mean by reentrancy.  Note that neither C
 nor C++ has any "thread" concept.

 2.  What reentrancy requirement can be written into the
 standard?  Note that we have decided to define no subsets
 of C++, so this requirement is shoved down the throats of
 every C++ implementor.

Ok, Steve found out that (1) is not a great problem, at least from the
legalistic aspect.

One of the standard's base documents is an ANSI dictionary of
technical terms.  The introduction of the C++ working paper says that
all terms not defined in the C++ standard are defined in that
dictionary.  The ANSI dictionary defines "reentrant subroutine" which
apparently seems to cover what Steve and I mean by reentrancy.

Now for (2) -- what can we demand?  I think it is unrealistic to
require that every C++ implementation should have support for
reentrancy.  It is reasonable if your target is a toaster or a
dishwasher, but perhaps not for an IBM mainframe (Kim?).  However, you
would like to make it easy for a potential user of a C++
implementation to determine if it has the necessary features.

Consequently, we have argued for a requirement to *document* the
provided support of reentrancy, not a requirement to actually
implement it.  In other words, every implementation must be
accompanied by a document that says to what degree reentrancy is
supported.

Furthermore, we have proposed that the vendor must document which
routines are not reentrant, i.e., every routine in the standard
library is assumed to be reentrant, unless the vendor documentation
says otherwise.  This position comes from our personal belief that
rentrancy is the "normal" case for most routines.

What is the impact on current implementations, then?  Not much.  If
you do not have an ambition to support reentrancy, you have to add a
one-liner to your documentation:

 No standard C++ library routines are reentrant.

If your library supports reentrancy through-out, you don't have to do
anything.  If you intend to cover some middle ground, you have to list
a number of library routines.

I should also mention one of the main arguments against saying
anything at all about reentrancy:  There is no realistic way to test
that a library really is reentrant, and the standard should not make
any requirements about things that cannot be tested.  That is indeed a
serious argument, but my counter-argument is that the standard already
specifies things that cannot realisticly be tested.  For example, how
can you test that destructors for local variables are called under all
conditions?

Any comments are greatfully accepted.


    -- Dag




Author: rfg@netcom.com (Ronald F. Guilmette)
Date: Mon, 1 Nov 1993 10:43:12 GMT
Raw View
(I am cross posting this to comp.std.c from comp.std.c++ in order to allow
the folks who follow comp.std.c an ample opportunity to shake their heads
in disbelief.)

In article <2b2elb$qgg@nic.lth.se> dag@control.lth.se (Dag Bruck) writes:
>
>Steve Vinoski and I have tried to move the C++ standards committee a
>short distance in the "right" direction.

Your idea of the "right direction" and mine differ greatly.

>...  I think it is unrealistic to
>require that every C++ implementation should have support for reentrancy.

On what exactly do you base this bizzare claim?

I'm forced to point out that due to its history, everything in C++ can
be implemented in C, and that the ANSI/ISO C standard *requires* C
implementations to generate reentrant code.  If this requirement can
be met by C implementations (which it obviously can) what evidence
(if any) would to offer to support the strange notion that reentrancy
is something which CANNOT be supported in C++?

Are you seriously claiming that this *must* be an area in which C++ will
actually end up being LESS powerful that C?

Are you and the X3J16 committee really prepared to deviate (yet again)
from compatability with ANSI C in such a dramatic way?  Is C++ really
going to break all of that existing C code which RELIES upon the
assumption of reentrancy??

>Consequently, we have argued for a requirement to *document* the
>provided support of reentrancy, not a requirement to actually
>implement it.  In other words, every implementation must be
>accompanied by a document that says to what degree reentrancy is
>supported.

Is that supposed to be like the consolation prize?

>I should also mention one of the main arguments against saying
>anything at all about reentrancy:  There is no realistic way to test
>that a library really is reentrant, and the standard should not make
>any requirements about things that cannot be tested.  That is indeed a
>serious argument...

I'm sorry, but I don't think it is.  There *are* ways to test code to see
if it is reentrant or not.

Separately, I might also mention that you are muddying the issues.  There
really are two issues.  One is the question of whether or not implementa-
tions will be required to generate reentrant code for the *user's* source
code.  The other is the question of the reentrancy of the library routines.
The C standard requires that user code be translated into reentrant code,
but does not require the standard library routiens to themselves be
reentrant.  I see no reason why that exact model should not be adopted
for the C++ standard.  What's good for the goose is good for the gander.

--

-- Ronald F. Guilmette, Sunnyvale, California -------------------------------
------ domain address: rfg@netcom.com ---------------------------------------
------ uucp address: ...!uunet!netcom.com!rfg -------------------------------




Author: dag@control.lth.se (Dag Bruck)
Date: 1 Nov 1993 17:43:33 GMT
Raw View
In <comp.std.c++,comp.std.c> rfg@netcom.com (Ronald F. Guilmette) writes:

[Long ramblings deleted.]

>Separately, I might also mention that you are muddying the issues.  There
>really are two issues.  One is the question of whether or not implementa-
>tions will be required to generate reentrant code for the *user's* source
>code.  The other is the question of the reentrancy of the library routines.

Pardon me.  I was writing about the standard C++ library.

>The C standard requires that user code be translated into reentrant code,
>but does not require the standard library routiens to themselves be
>reentrant.  I see no reason why that exact model should not be adopted
>for the C++ standard.

I still hope we can achieve something more useful wrt to standard libraries.


    -- Dag




Author: dag@control.lth.se (Dag Bruck)
Date: 1 Nov 1993 18:30:10 GMT
Raw View
In <comp.std.c++,comp.std.c> rfg@netcom.com (Ronald F. Guilmette) writes:
>(I am cross posting this to comp.std.c from comp.std.c++ in order to allow
>the folks who follow comp.std.c an ample opportunity to shake their heads
>in disbelief.)
>
>.... the ANSI/ISO C standard *requires* C
>implementations to generate reentrant code.  If this requirement can
>be met by C implementations (which it obviously can) what evidence
>(if any) would to offer to support the strange notion that reentrancy
>is something which CANNOT be supported in C++?
>
>....  There *are* ways to test code to see
>if it is reentrant or not.

Is the following code reentrant?

 extern int* p;

 void incr() { p++; }

How do you test it?


    -- Dag




Author: rfg@netcom.com (Ronald F. Guilmette)
Date: Tue, 2 Nov 1993 00:34:52 GMT
Raw View
In article <2b3hs5$dm5@nic.lth.se> dag@control.lth.se (Dag Bruck) writes:
>In <comp.std.c++,comp.std.c> rfg@netcom.com (Ronald F. Guilmette) writes:
>
>[Long ramblings deleted.]
>
>>Separately, I might also mention that you are muddying the issues.  There
>>really are two issues.  One is the question of whether or not implementa-
>>tions will be required to generate reentrant code for the *user's* source
>>code.  The other is the question of the reentrancy of the library routines.
>
>Pardon me.  I was writing about the standard C++ library.

I wasn't.  I was talking (mostly) about the other issue.

>>The C standard requires that user code be translated into reentrant code,
>>but does not require the standard library routiens to themselves be
>>reentrant.  I see no reason why that exact model should not be adopted
>>for the C++ standard.
>
>I still hope we can achieve something more useful wrt to standard libraries.

Oh I do too.  But given that the odds are very good that C++ standard libraries
will themselves be written largely in C++ (and compiled with C++ compilers)
I think you will have to agree that the first-order problem is to get the
standard to require C++ compilers to generate reentrant code.

But the X3J16 drafts don't even require *that* yet!

--

-- Ronald F. Guilmette, Sunnyvale, California -------------------------------
------ domain address: rfg@netcom.com ---------------------------------------
------ uucp address: ...!uunet!netcom.com!rfg -------------------------------




Author: rfg@netcom.com (Ronald F. Guilmette)
Date: Tue, 2 Nov 1993 00:37:20 GMT
Raw View
In article <2b3kji$eun@nic.lth.se> dag@control.lth.se (Dag Bruck) writes:
>In <comp.std.c++,comp.std.c> rfg@netcom.com (Ronald F. Guilmette) writes:
>>(I am cross posting this to comp.std.c from comp.std.c++ in order to allow
>>the folks who follow comp.std.c an ample opportunity to shake their heads
>>in disbelief.)
>>
>>.... the ANSI/ISO C standard *requires* C
>>implementations to generate reentrant code.  If this requirement can
>>be met by C implementations (which it obviously can) what evidence
>>(if any) would to offer to support the strange notion that reentrancy
>>is something which CANNOT be supported in C++?
>>
>>....  There *are* ways to test code to see
>>if it is reentrant or not.
>
>Is the following code reentrant?
>
> extern int* p;
>
> void incr() { p++; }
>
>How do you test it?

Sorry.  It appeasr that I did not express myself very well.

What I meant to say was that I believe that there *are* ways to test
COMPILERS to see that they generate reentrant OBJECT CODE when given
provably reentrant SOURCE CODE.

--

-- Ronald F. Guilmette, Sunnyvale, California -------------------------------
------ domain address: rfg@netcom.com ---------------------------------------
------ uucp address: ...!uunet!netcom.com!rfg -------------------------------




Author: schouten@sp95.csrd.uiuc.edu (Dale Schouten)
Date: 02 Nov 1993 03:57:43 GMT
Raw View
Sorry to butt in, but I'm a little confused by what exactly we mean
by `re-entrant' in this context, and what features of C++ fail to
ensure re-entrancy.

Any ideas?

Thanks
Dale
schouten@uiuc.edu




Author: jimad@microsoft.com (Jim Adcock)
Date: Mon, 1 Nov 1993 20:48:08 GMT
Raw View
In article <2b2elb$qgg@nic.lth.se> dag@control.lth.se (Dag Bruck) writes:
>Any comments are greatfully accepted.
>

My comment, again, would be that X3J16 has no business redefining
how X3J11 routines work.  If X3J16 cannot abide how X3J11 routines
work, then X3J16 ought to define their own routines, with their
own names, and their own uniquely named #include files.  Standard C
libraries come not only from compiler vendors, but also from library
vendors.  Confusing the issue by making Standard C++ versions of the
Standard C Standard libraries, verses Standard C versions of the
Standard C Standard libraries, is just going to hose the users,
the library suppliers, as well as people who write books about the
Standard C Standard libraries [except I guess now they get to write
books "The Standard C Standard Libraries -- Standard C++ Version".

C *and* C++ get used for a lot of non-systems non-apps non-un*x work.
For example they both get used in toaster ovens.  I see no reason why
every library vendor who provides a set of the libraries suitable for
toaster ovens needs to make those libraries reentrant.  On the contrary,
such would seem to be mainly dependent on the kind of system
the libraries' are designed to run on, which in turn would argue that
these are NOT the kinds of things the C++ standard should be specifying.





Author: msb@sq.sq.com (Mark Brader)
Date: Wed, 3 Nov 93 06:47:21 GMT
Raw View
Ronald F. Guilmette (rfg@netcom.com) writes [his emphasis]:
> ... the ANSI/ISO C standard *requires* C implementations to generate
> reentrant code ... but does not require the standard library routines to
> themselves be reentrant.

What the C standard actually says in section 2.2.3/5.2.3 is:

#  Functions shall be implemented such that they may be interrupted at
#  any time by a signal, or may be called by a signal handler, or both,
#  with no alteration to earlier, but still active, invocations' control
#  flow (after the interruption), function return values, or objects
#  with automatic storage duration.  All such objects shall be maintained
#  outside the "function image" (the instructions that comprise the
#  executable representation of a function) on a per-invocation basis.
#
#  The functions in the standard library are not guaranteed to be reentrant
#  and may modify objects with static storage duration.

(What I actually copied that text from is the December 1988 draft, since
I'm at home, but I would have annotated it if there had been a significant
change to the wording in the actual standard.)

This is somewhat weaker than the interpretation of "reentrant" given by
Robert Martin (rmartin@rcmcon.com) in the last-Referenced article -- it
doesn't allow for the possibility of threads, but rather assumes that if
a function is reentered it will be by being re-called.  And this is not
surprising, because in the semantics of the abstract machine that the
C standard describes, there is no such thing as a thread.

So I don't think the C standard does guarantee reentrancy in the sense
that Robert uses the term.


I express no opinion whatever about whether this was for the best, nor about
what C++ should do.
--
Mark Brader   "'You wanted it to WORK?  That costs EXTRA!'
SoftQuad Inc., Toronto   is probably the second-place security hole
utzoo!sq!msb, msb@sq.com  after simple carelessness." -- John Woods

This article is in the public domain.