🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: comp.std.c++
Article #538

Re: Packing, Ordering, and Rearranging

#538
From: Kent Paul Dolan
Date: Wed, 03 Oct 1990 06:17
299 lines
14237 bytes
jimad@microsoft.UUCP (Jim ADCOCK) writes:
>I have to admit I'm becoming very discouraged by the amount of commentary
>this subject is generating, without any corresponding understanding of
>the issues as applied to object oriented programming.

No more than I am to see you return to a position passed by two weeks
ago as inadequate to the needs of the user community, with no progress
made whatever from opinions stated at that time.

Let's establish a few ground rules:

1) Compilers are not written for the convenience of compiler writers,
but of compiler users and users of compiled code.  Therefore, promoting
user inconvenience in favor of compiler writer convenience is a Bad
Thing.
 
2) Tremendous as the productivity gains can be from using object
oriented programming languages, they are at bottom just notational
conveniences for ordinary imperative languages. In particular, no
new computations become feasible by using OOPLs, though the chance
of implementing the old ones correctly or cost effectively may
improve. In particular, there is a direct translation of C++ into
C, which is merely a change of notation. The price paid for using
a new notation should not be the loss of ability to do some common
programming tasks, compared to the older notation.

3) The purpose of any standard, and in particular a language
standard, is to standardize existing practice, for purposes of
making things adhering to the standard more widely and
conveniently useable, in particular for programming languages, the
code and the programmers trained in its use.

Now let's see if some progress is possible.

> I don't believe any compiler vendor is going to want to reduce the
> amount of capability their C compilers have traditionally provided
> for 'bit-twiddling'.

And, whether standardized or not, past practice has been that
complete, bit by bit control of structure layouts was always made
available to the programmer, albeit not portably so.

> The real issue is what methods shall compilers writers be allowed
> to use to implement inheritence.

This viewpoint is part of the problem in coming to some resolution
in this discussion. The convenience of compiler writers should not
be an issue. Whether something is possible at all, or only
possible with an NP complete computation, is admissible as an
argument, but not the compiler writer's mere convenience, where
that is gained at the expense of the compiler user.

> This cannot have been an issue in the past, because C did not have
> inheritence.

Beside the point.  The same capabilities provided to extend structures
by inheritence existed and were widely used and known, when structures
were embedded in other structures.  The experience of that widely used
programming paradigm is completely applicable to the current question.

> Use a C structure, don't use inheritence, and chances are about
> 99% that your C++ compiler will give you the same layout as your C
> compiler.

Given that C compiler implementors all tended to lay out structure
elements so that they didn't cross boundaries of elements their
size laid out in an array beginning at address zero, and left
padding between them to assure this, and didn't arbitrarily
rearrange structure fields to achieve more efficient packing, and
that this habit is reenforced in the C++ implementors, probably
true, but note _all_ the conditions.

> But, given that a C++ compiler needs to implement inheritence, how
> shall vendors be allowed to do so?

The first choice would be that they follow the model of existing
practice in C, which is to embed the "parent" structure as the
first element of the "child" structure. See for example the very
pretty general link list structure used for the Commodore Amiga
windowing operating system.

_Any_ choice should be evaluated to see whether it has a high cost
that would preclude the general use of inheritance, one of the
great design benefits of an OOPL.  Not to keep the reader in suspense,
loss of control of structure layout by the programmer/user of the
compiler is such a high cost.

> Should C++ compiler vendors all be forced to follow the cfront
> model?

Never having looked at it, I haven't a clue; since I only care about
the part that affects me on the outside as a programmer designing
code, I care much less about the method or model, than about the
final result.

> Or should vendors choose object models that maximize efficiency
> for their target machines?

This choice is not even expressed along the relevant axes. The
question which needs consideration is, should compiler
writers/vendors choose to wrest control of structure layout, in
the case of structures built piecemeal by inheritance, from the
programmer?

Again, it needs emphasis, the same structure _functionality_ can
be built in a non-OOPL, without inheritance. That it is built by
the mechanisms of inheritance is a convenience of notation, but
not an essential characteristic of the structure, so the question
of the structure's utility to the programmer should be considered
_independent_ of the notational mechanism used to build the
structure. (Given that the programmer retains complete control of
the structure layout, the same _structure_ can also be built in a
non-OOPL.)

If the programmer, by deliberate coding choice, expresses no need
to control the layout of a particular structure exactly, which may
be the majority case, then the compiler writer will, simply to
meet competition from other vendors, do the most efficient
implementable optimizing layout possible, but this cannot be
allowed to become the only case, to the exclusion of the
programmer's _preeminent_ right to demand complete control in
order to accomplish the programming task at hand _when_ _needed_.

> I, for one, believe there is a need to allow multiple object
> models.

This only makes sense if it is not allowed to diminish the utility
of the notational convenience which is inheritance. If it does,
then we have put the wrong group's interests foremost.

> Differing object models can allow significant trade offs between
> speed and space.

Wonderful, but if you give me fast, compact code that prevents me
from doing _my_ job, where is the gain?  Your code may look wonderful
in the benchmarks, and sell well in the market place, but when word
gets out that it is unusable, what have you profited by denying the
programmer control of the code's results?

> Differing object models may be necessary to interface to other
> OOPLs, or systems.

Interfacing at the data level, what more than exact layout control
could you offer, and how could you possibly expect to succeed at
this task if you don't offer at least that much?

> Newer object models can provide overall speed enhancements.

If your insistance on control of structure layout, to the
preclusion of my controlling it when I need that control, prevents
me from doing my job, or from using inheritance, and gaining its
productivity benefits, how has your faster compiled code helped
me? Code still costs more to write than it does to run in all but
the most extreme cases, and if you force me back to more primitive
methods and increase the cost of my code implementation, of what
use to me is it when it runs fast but is delivered too late for
its intended task or market window of opportunity?

> Therefore, I believe the issues are different in the face of
> inheritence as opposed to a language without inheritence.

As I hope I have successfully demonstrated, this belief is false.
The premier criterion _must_ be, can the programmer get done the
job s/he needs to do with the tool you have provided.  If you have
impeded that task, all the speed and code size brags in the world
won't repair the damage.

> Please don't just keep dragging out historical C examples of how
> you like to place bits.

I must, until you finally understand the point. The fact that you
find history's lessons inconvenient for your arguments on certain
questions doesn't make that history any less valid in deciding
those questions.

I've been programming a _long_ time; many of those examples
predate the existance of C. Until you understand the point that
this kind of programming is a large part of what the C++
language's audience of programmers will be doing for the lifetime
of the language, these historical examples will keep being brought
up to avoid the old "those who refuse to learn from history..."
problems. Programming's past is also part of its future. New
programming tasks will arise as time proceeds, but all those old
ones keep coming back in new suits of clothes, and the retreads
outnumber the new tasks in day to day programming work.

> That's not the issue. You'll still be able to do that.

But if I cannot do that with the productivity gains of the new
programming model provided by OOPL, but have to revert to the
methods of C, then I lose productivity, portability, reuse, and
the other benefits of OOP.

Also, now with your proposed paradigm, I have to keep two
programming models in mind, keep track of when one or the other is
appropriate, and in general will be led to make a whole new class
of programming mistakes by the added complexity this dual model of
programming structures would cause.

> The question is, what should language users be allowed to do, and
> not do, via inheritence, and what should compiler implementors be
> allowed to do, and not do, regards inheritence?

Completely true.  My answers:

Language users should be allowed to do, via inheritance, at least
those things which were possible with the pre-OOPL methods of
embedding structures that were the predecessors of, and model for,
inheritance. This explicitly includes exact structure layout
control when needed.

Compiler implementors should be allowed to do whatever cute tricks
they can think up to gain speed and compactness so long as those
don't degrade the utility of inheritance compared to the methods
it replaces.

End of direct responses.

Note that there are really several more questions here:

1) Do I know how the compiler will lay out my structures?

2) Can I control that structure layout at all?

3) Can I do it in portable code?

4) Does that portable code produce portable structures?  (I admit
this question is a strange one, but see below.)

5) Can I do it for the full range of notational conveniences that
an OOPL provides, and enjoy the productivity gains that implies?

6) Can I make use of optimizations provided by the compiler writer
when I don't need the structure layout control those optimizations
would prevent?

In terms of a standard, this leads to these further questions.

1) Does the standard mandate that the compiler's structure layout
methods will be documented exactly for each implementation, so
that I can know what layout the code produces by inspecting the
code and reading the implementation documentation?

2) Does the standard mandate that there will be a way in a C++
compiler to control the layout of structures, so that I can read
the implementation documentation expecting to find it?

3) Does the standard mandate that there will be an implementation
independent method of controlling structure layout, where the same
code leads to the same layout, bit for bit?

4) Does the standard mandate what "bit for bit" means into the
teeth of byte order and other machine inconsistencies?

5) Does the standard extend that layout control consistently
across all the ways the language has to define a structure, or
does it treat such layout control as an unusual case, and isolate
it to only the more primitive structure definition methods?

6) Does the standard mandate a #pragma, "exact" keyword, compiler
flag, or similar mechanism to yield control of structure layout to
the programmer (or yield it to the compiler's layout optimization,
depending on which is the default), or does it at least mandate
that some such, implementation dependent, method must exist?

It is not a given that we can agree to answer all, or any, of
these questions "yes", or even agree to answer them at all, but I
think it should be a given that the results of the answers or lack
thereof will have a large impact on the success and lifetime of
the language whose standardization is being discussed here.

I hope it can also become a given that the utility of the language
to the programmer, not to the compiler writer, should be the
paramount criterion for deciding these questions, and that
functionality and programmer productivity should preceed speed or
compactness of compiled code in measuring that utility.

Note that, with history for a guide, we can say with some degree
of confidence that each successful C++ compiler implementation
_will_ provide _some_ way to control structure layout exactly,
since successful past compilers have consistently, though
non-portably, done so.

The question then reduces to one of whether we (you) choose to
capture and mandate that existing practice in this standard, with
the gains implied by _making_ this practice standard rather than
implementation dependent.

If this choice is made in the affirmative, then the next question
is how much control of implementations the standard will take on
behalf of the programmer/user, with respect to the question of
exact structure layout control.  [No sense trying to execute the
"then" portion until the "if" portion is satisfied, so I'll stop
here.]

Kent, the man from xanth.
<xanthian@Zorch.SF-Bay.ORG> <xanthian@well.sf.ca.us>
--
Whew!  ;-)
Technical Details
Message-ID: <1990Oct3.061708.10391@zorch.SF-Bay.ORG>
Path: arc1-ca.pugleaf.net!utzoo!utgpu!news-server.csri.toronto.edu!cs.utexas.edu!wuarchive!julius.cs.uiuc.edu!apple!vsi1!zorch!xanthian
References: <1990Oct1.074231.8639@zorch.SF-Bay.ORG> <57892@microsoft.UUCP> <57898@microsoft.UUCP>

Show Full Headers
Complete Article Headers
Path: arc1-ca.pugleaf.net!utzoo!utgpu!news-server.csri.toronto.edu!cs.utexas.edu!wuarchive!julius.cs.uiuc.edu!apple!vsi1!zorch!xanthian
From: xanthian@zorch.SF-Bay.ORG (Kent Paul Dolan)
Newsgroups: comp.std.c++
Subject: Re: Packing, Ordering, and Rearranging
Message-ID: <1990Oct3.061708.10391@zorch.SF-Bay.ORG>
Date: 3 Oct 90 06:17:08 GMT
References: <1990Oct1.074231.8639@zorch.SF-Bay.ORG> <57892@microsoft.UUCP> <57898@microsoft.UUCP>
Organization: SF-Bay Public-Access Unix
Lines: 299