[Date Prev][Date Next][Thread Prev][Thread Next][Author Index][Date Index][Thread Index]

Re: Constructor bombs for copy objects.



> On overheads: My technique is less run-time efficient for the reason
> you point out, but your technique is frighteningly less space
> efficient since (if I understand correctly) you require a "progress"
> style member variable not just per object, but per object times
> inheritance depth of the object.

Nope.

 1) It is only required at those levels of the class hierarchy that:

     - require destruction in more than one state of construction, and

     - cannot determine their state in a natural way from the contents
       of their other member variables.

    Constructors in the first set are rare, and constructors in the
    second set are VERY rare.  I'd be surprised if we ever see one
    member of the second set inheriting from another.

 2) If one such DOES inherit from another, the derived class may recycle
    its base-class' "progress" variable to trade execution time (and some
    modularity loss) for the per-object storage.  You do this by:

      - Changing its protection class to "protected"

      - Adding a "this->progress = BaseCLassFullyConstructedEnumValue;"
        at the end of the derived class' destructor.

    I don't recommend this, because 3) is better:

 3) If space is REALLY a problem, you can make the variable go away
    entirely by doing a transformation on the class hierarchy.  You
    create a superclass to represent each stage of the object's
    construction, thus:

		FooStep0
		FooStep1
		FooStep2
		 ...
		FooStepN-1
		Foo

    Then you:

      - Build the new constructors and destructors by splitting the old
	ones at the "progress" boundaries.
      - Throw out the "progress" variable.
      - Promote member variables and functions baseward until the compiler
	stops complaining.

    and you're done.  The progress variable is gone, its function absorbed
    by the vtable pointer.  Using inline constructors, the construction
    execution-time overhead should be exactly the same, and destruction
    might be slightly faster.  The transformation is ENTIRELY local to
    the class, and invisible to clients, so it can be punted to the tuning
    phase at negative cost.

    (The resulting classes look a bit strange, since the destructors of a
    given stage are uniformly one class leafward from the corresponding
    constructors.  This is a strong argument that the "correct" OOP
    approach is to use such a class hierarchy in the first place, and
    have destructors called the way Markm was suggesting.  But that
    implies the object is promoted to the new class, and the vtable
    pointer is updated, at the END, not the START of a constructor.
    More cans of worms open...)

(I intended this next to be an expression of wonder and a suggestion that
we just do the error-handling right.  But I composed it while just waking
up and hungry, and it came out in type looking like fire and brimstone,
with markm on the roasting spit for having the temerity to intrude on
my sandbox.  Believe me, that's not what I intended.  (And I especially
value markm's participation on those of our problems that I have to work
on.)  But I want to get to breakfast and hacking, not spend time fixing
it, and I think the issues raised are too important to let slide.)

I have been extremely surprised by this correspondence.  I thought our
design approach was to do it the clean, simple, error-repelling way,
ignoring constant-factor performance issues until the code was all
working and tested, and THEN find out where the big constant-factor
eaters live, and THEN kill the big ones.

Yet I find someone who pushes for atomized objects and objects-wrapping-
objects (with all the per-object overhead for vtables, memory-allocation,
garbage-collection, and who-knows-what-all) professing fright of a little
enum, and advocating what I consider convoluted, confusing, and error-prone
constructor/destructor designs to save a few bytes.

The mistaken impression that the overhead was much higher, and penalized
each step of atomization, makes this concern understandable.  And
documenting a brainstorm on how to eliminate it at a later phase is, of
course, exactly the right thing to do.  Nevertheless, the contrast with
our professed beliefs is jarring.  (Especially when, in this case,
deviating from them just happens to do precicely the wrong thing.)

I would think that, if trading (temporary) overhead for simplicity is a
good idea while getting the algorithms to do their job once, it should
be at least as good an idea when trying to get them to do their job right
every single time.  Which do YOU think is the harder problem?  And if
there is ANY place you DON'T want the code to be confusing, it's in the
rarely-exercised, hard-to-test, error-handling.

And I thought >I< was the one who was paying attention to the bit-twiddling.
I tell you, if a few bytes for a "progress" variable scares you, the hunks
of memory dedicated to the above TERRIFY me.  But I accept them, because
the architecture is your area of expertese, and you assure me that they are
a fair trade for the capabilities they give you.

But when it comes to error-handling, I'm speaking from my area of expertese
(and in this case I've already considered the tradeoffs, at least as far as
not exploding the object size).  I can assure you that, even if we COULD'T
make them vanish with a wave of the class-definition wand, progress
variables would be RAM well spent.  The coding style of objects written
WITH them is the sort you can make dinner bets on.

I'd have brought this up in person, but if one of us has backslid this
far, and is sending email that could be a corrupting influence on the
rest of the true believers, it's time for a revival meeting.

(Where's that lectern.  Ah, here it is.  'brothers and...'  Dratted PA
 is fritzed again.  <Whap>  >POP!<  "BROTHERS AND..."  There we go.)

	Brothers and sisters, I have come here before you to
	bear witness to the faith!  (Say Hallelujah.)
	
	I say to you that if you write convoluted code to save a
	few worldly bytes, you are LIVING in SIN!

	You may intend WELL, but good intensions pave the road to HELL!

	Live a CLEAN life.  Write CLEAN code.  Use your MIND POWER
	to make your code RUN!

	And if you live a SINLESS life, your place in heaven is asSURED.
	Your spiritual advisors have surveyed the path.  Relax.  Don't
	worry.  We've got it covered.

	This one won't tear down the house, like the high-speed vibrating
	clocks.  (Oops.  Wrong rant.)

Anyhow, you get the idea.  Do it this way, OK?  Please?  All the time?
I really want to get this stuff working before Deng kicks off.

		michael

PS:  Maybe we should rename Shepherds to something that doesn't keep
     reminding me of Christian imagery.  This is getting silly.  B-)