From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on polar.synack.me X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00 autolearn=ham autolearn_force=no version=3.4.4 X-Google-Language: ENGLISH,ASCII-7-bit X-Google-Thread: 103376,436e4ce138981b82 X-Google-Attributes: gid103376,public X-Google-ArrivalTime: 2004-03-17 21:58:22 PST Path: archiver1.google.com!news1.google.com!news.glorb.com!border1.nntp.ash.giganews.com!border2.nntp.ash.giganews.com!nntp.giganews.com!news.airnews.net!cabal13.airnews.net!cabal10.airnews.net!cabal11.airnews.net!sn-xit-03!sn-xit-01!sn-post-01!supernews.com!corp.supernews.com!not-for-mail From: "Randy Brukardt" Newsgroups: comp.lang.ada Subject: Re: abstract sub programs overriding Date: Wed, 17 Mar 2004 23:57:28 -0600 Organization: Posted via Supernews, http://www.supernews.com Message-ID: <105ieithg52qo74@corp.supernews.com> References: <1078839257.157439@master.nyc.kbcfp.com> <5cmr40t76va200betf07b7bd6er05ltto9@4ax.com> <1078845298.702789@master.nyc.kbcfp.com> <0ipr40thtf86b520a0qdi003aj87gtuhd4@4ax.com> <1078849973.701176@master.nyc.kbcfp.com> <1078924150.268074@master.nyc.kbcfp.com> <1078934469.744922@master.nyc.kbcfp.com> <1078949096.760629@master.nyc.kbcfp.com> <1079013337.572283@master.nyc.kbcfp.com> <9_mdnfzBlfEC3M_d4p2dnA@comcast.com> <1079361579.900651@master.nyc.kbcfp.com> <105f2jql5ge7f0a@corp.supernews.com> <105h3dkion79348@corp.supernews.com> <3vydndmUiYRplsTdRVn-sQ@comcast.com> X-Priority: 3 X-MSMail-Priority: Normal X-Newsreader: Microsoft Outlook Express 5.50.4807.1700 X-MimeOLE: Produced By Microsoft MimeOLE V5.50.4910.0300 X-Complaints-To: abuse@supernews.com Xref: archiver1.google.com comp.lang.ada:6392 Date: 2004-03-17T23:57:28-06:00 List-Id: "Robert I. Eachus" wrote in message news:3vydndmUiYRplsTdRVn-sQ@comcast.com... > > If the object has an explicit initial value, Initialize is never called. And > > if that initial value is an aggregate, it has to be built directly in the > > object (and none of Finalize, Adjust, or Initialize are called). That's not > > the case we're talking about. > > Whoops, that one sent me back to the reference manual. First, an > aggregate of a controlled type always results in a call to some > Initialize, except perhaps inside of Ada.Finalization where you can use > a regular aggregate instead of an extension aggregate. I'm not in general interested in other type's Initialize/Adjust/Finalize -- I presume the language is defined properly to prevent problems with those. The only exception is the parent, and my personal rule is to always call that operation first in order to avoid any problems with uninitialized stuff. It's annoying that it has to be done explicitly, but real programs need the flexibility (or so I'm told). In most interesting cases, the extension aggregate parent part's Initialize is the predefined one, which does nothing, and is indistinguishable from no call at all. (I suspect that most compilers don't generate statically bound calls to predefined Initialize.) > In the second sentence, I think you are thinking of RM > 7.6(17.1) which was added in the 2000 revision. But that requirement > does not apply to aggregates in assignment statements, and you are right > that is not the case we are talking about here. > This is the case where an exception occurs during the evaluation of the > aggregate, in particular in the call to Initialize there. And this is > where we get into whether partially intialized objects are finalized. > As I read the rules and understand them, the answer is that to some > extent partially initialized objects may have components that have been > fully initialized, these must be finalized. We are back to that other > comment you made. I'm pretty sure that there was an AI on that topic. Let me look...yup, AI-193 (also in the Corrigendum). This AI confirms the language of the standard for the case in question: if Initialize propagates an exception, the (whole) object is not finalized. (Of course, controlled parts that completed initialization will be finalized). That's about what you said. Of course, it's usually a mistake to let any of the controlled routines propagate an exception. > What you as an author want is that any object that is correctly > initialized will be finalized, that any object which is not initialized > will not be finalized, and there are no objects in the middle. Right, but that's a tough property to guarentee, particularly if you want to to be reasonably secure from abort and the like. I think it is best to depend primarily of a valid flag(s) of some sort (as you mentioned, a null pointer works fine, Claw uses that in some cases). And each extension needs its own flag if it has any state of its own > This is why I like to use an extension aggregate as the first line of an > Initialize procedure. If there is an exception raised, Adjust doesn't > get called, and I don't have to worry about cascading exceptions. Once > the aggregate assignment succeeds I have an object which is not > abnormal, in either the Ada technical sense or the practical sense. Fair enough. Of course, that's equivalent to what I wrote Initialize(Parent(Object)); <> except that there are no extra Finalize and Adjust calls to confuse things. (I'm assuming that I'm smart enough to avoid exceptions in setting my components. If not, that's simply a bug, and I don't much care what happens when a bug occurs -- it needs to be fixed. > >>However, > >>I can see that it could occur if the object is assigned a value by an > >>aggregate assignment inside a user-defined initialize. > > > > It *has to* occur in that case, which was Hyman's point. I don't think it > > can be optimized out. > > And I think it can be--but it won't be. I don't see any way that it can be. This is an explicit case of finalization; it is not the finalization of leaving a master that the majority of the rules in 7.6.1 are about. The only way that it could be optimized out is by inspecting the body of the routine to see if it does anything. But that is always a possible optimization, and is not interesting (just as generic sharing that requires looking at the body is not interesting). ... > In this case the wording of 7.6(21) would allow some improper > optimizations except for the phrase "...if it can safely create...", so > every implementation only does this optimization in a way that is > semantically equivalent to the canonical approach. The (original) wording of 7.6(21) allowed many improper optimizations, and implementers were doing some of them. (Adjusting one object, copying the bits, and then finalizing another object. Nasty if you're storing a pointer to the object somewhere...) That's why it was rewritten. "safely" is a noise word in this paragraph; it has no technical meaning, and certainly doesn't require semantic equivalence to the canonical approach. (Such a requirement would be the same as saying that no optimization at all is allowed, because you certainly can tell on which objects Adjust and Finalize are called.) > As all this discussion shows, there are cases where the rules lead into grey areas, > but in practice there is no grey. Well, there was a lot of it with certain compilers in the 1996-98 timeframe. I think that is "in practice". I think its better now (everyone conforms to the rewritten 7.6(21) so far as I know), but that was not true for a long time. > As I mentioned above, an > implmentation is allowed to have regular aggregates in Ada.Finalization, > but aside from that, all values of a controlled type must have been initialized. I don't see any relevancy of that statement at all. It's only useful to reason about a single type's Initialize/Adjust/Finalize; anything further leads directly to madness. Unless you're language lawyering to try to invent a case where the language doesn't properly handle composition. The only case where there's trouble is when you derive from a type with a meaningful Initialize/Adjust/Finalize routines. Those routines are not going to be called automatically, and the programmer had better take care of that, because the parent object may not be initialized as it expects. (Similarly for Finalize, of course.) If the parent type's definition of "properly initialized" requires Initialize to do something, it's trivial for that to be omitted. Your use of extension aggregates does avoid that problem, but it adds extra calls to Finalize and Adjust. The Finalize probably will not do anything (presuming there is a validity flag), but the Adjust will be the full blown deep copy. Moreover, that will be followed by a Finalize of the temporary that the aggregate was built in (essentially the undoing of the deep copy). For Claw, those routines are nearly 500 lines each, and that's not something that you want to be invoking during default initialization. And Hyman's point was simply that these extra calls happened. (For someone who claims to not know Ada very well, Hyman knows Ada very well. He should join the ARG. :-) We could use him.) Randy.