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-Thread: 103376,7fcf9180e7ba7ab1 X-Google-NewGroupId: yes X-Google-Attributes: gida07f3367d7,domainid0,public,usenet X-Google-Language: ENGLISH,ASCII-7-bit Path: g2news1.google.com!news3.google.com!fu-berlin.de!uni-berlin.de!individual.net!not-for-mail From: Niklas Holsti Newsgroups: comp.lang.ada Subject: Re: A suggestion for resource management Date: Sun, 22 Aug 2010 13:53:52 +0300 Organization: Tidorum Ltd Message-ID: <8dcdu1F4v9U1@mid.individual.net> References: <8762z4gcoi.fsf@mid.deneb.enyo.de> <8darikF1b0U1@mid.individual.net> <87eidr3cje.fsf@mid.deneb.enyo.de> Mime-Version: 1.0 Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit X-Trace: individual.net cN4R4a4EDp5F9eBPxSjGcQST5OlJjc33cFYmQXjIdnLgBbyWpB Cancel-Lock: sha1:bTLOoOB6oZIcECVt0BgMHEyq8GI= User-Agent: Mozilla-Thunderbird 2.0.0.24 (X11/20100328) In-Reply-To: <87eidr3cje.fsf@mid.deneb.enyo.de> Xref: g2news1.google.com comp.lang.ada:13604 Date: 2010-08-22T13:53:52+03:00 List-Id: Florian Weimer wrote: > * Niklas Holsti: > >> Florian Weimer wrote: >>> Here's a proposal for a resource management pragma, tentatively called >>> pragma Scoped. It is similar to the scope(exit) directive in D, the >>> C++ scope guard idom, and (to a lesser degree) Go's rescue statement. >>> >>> The syntax is: >>> >>> pragma Scoped (procedure_call_statment); >> I strongly dislike the idea of using "pragma" to introduce such >> non-obvious flow of control. > > In a sense, it's just repeating what Unchecked_Deallaction does behind > the scenes. I don't understand your comment at all. An instance of Unchecked_Deallocation is explicitly executed where it is called, not at some later point in time, and no pragma is involved. Or do you mean Finalize for controlled types? >> Flow of control should be clearly represented in the syntactic >> structure, with textual order matching execution order. The current >> exception-handling syntax is good in that respect. > > I understand that goal. However, this approach separates the > initialization from the clean-up code, I understand your point, but these are conflicting goals, as long as text remains one-dimensional, so it is a judgement call. > and the clean-up code might > need repeating in several places. This cannot be good. I take it you mean that one and the same occurrence of an "Open" call may require more than one occurrence of a "clean-up" call of "Close". But in some cases the converse happens, too: One and the same call of "Close" may clean up after different (alternative) "Open"s. That's life... To focus the discussion, your proposal contains the following four distinct parts, as I see it: 1. The introduction of a new executable construct (in your proposal, a pragma Scoped) that, *when* and *if* executed, dynamically "schedules" something else (the procedure call) to be executed at a later point in the execution (just before the "end" of the handled_sequence_of_statements). Advantages: The dynamic semantics gives LIFO nesting of initialization and finalization actions, without a corresponding nested syntax, even if exceptions occur (that is, transparently with respect to exceptions). Disadvantages: Flow of control differs strongly from text order. If your application or coding style puts, in the same subprogram, many things that need such clean-up (several levels of dynamic nesting), I understand that the advantages may be valued higher than the disadvantages. 2. The syntax of that new executable construct. You suggest a pragma, and I don't like that. I think pragmas should be "compiler directives" (RM 2.8(1)) and should not contribute materially to the algorithm that the program implements. I accept that there are already some pragmas that are really executable statements, such as pragma Assert, but I see those as special cases that are not part of the program's algorithm. 3. The nature and form of the code that is "scheduled" for later execution. You suggest a procedure call; I don't see why such a feature should not allow any form of statement. 4. The dynamic semantics of the "scheduled" code, in particular whether some parts of it are evaluated and fixed at the time of "scheduling", as you suggest, instead of later when the code is executed. If point (1) is accepted, I would like a non-pragma syntax, preferably using existing keywords. For example: at end do some-statement; (Following normal Ada principles, this should really be closed by an "end at", or even "end at end", but that may be too much...) There could be an optional subprogram or block identifier between the "end" and "do", as in at end of Test_External_Formats do Close (COBOL_File); >>> Regarding dynamic semantics: When a Scoped pragma which is part of a >>> handled_sequence_of_statements is executed or when it is elaborated as >>> part of a declarative_part, the procedure_name or procedure_prefix and >>> actual parameters of the procedure_call_statment are evaluated. >> ... and, if I understand your suggestion, the evaluated parameters are >> saved somewhere, in case they are needed for the later call. I think >> this can cause large run-time overheads, as well as confusion and >> errors. How "deeply" are the parameters saved? > > renaming-declaration-deeply, so it really depends on the types > involved. This happens with any procedure call, so the overhead > cannot be huge. Yes, it happens at every procedure call, but the values are then normally discarded after the procedure call. Here, they would not be discarded until the "end". But I agree that a renaming is not expensive. However, if the evaluate-and-save is *only* equivalent to renaming, you can get weird effects where a scalar variable seems to have different values at different places in the parameter list. For example, consider (using the pragma syntax): begin I : Integer := 4; A : array (1 .. 10) of Float := ( some values ); pragma Scoped (Foo (I, A(I))); begin I := 9; end; I think your suggestion is that the pragma is equivalent to: Saved_I : Integer renames I; Saved_AI : Float renames A(I); followed (before the "end") by the call Foo (Saved_I, Saved_AI); The call that is executed before the "end" is then Foo (9, A(4)), where the variable "I" seems to have two different values, 4 and 9. Moreover, what happens if an actual parameter is a function call? Should the function be called at the point of the "pragma Scoped", or later? >> The semantics will depend on whether a type is passed by value or by >> access, right? > > Not really. The idea is to avoid strange action-at-a-distance if the > actual arguments change their value between execution of the pragma > and the embedded procedure call. But the example above shows that this produces other (?) strange effects, since renaming "fixes" the value of a variable in some contexts but not in others. >> Also, saved parameters of access type may become unusable (hanging >> pointers) if the statement_sequence deallocates the accessed object. > > Ordinary procedure calls suffer from this problem, too. My point is that the early evaluation of the parameters at the point of the pragma suggests that the procedure call occurs in that state, but actually the state may have changed, and the evaluated and saved parameters only capture some part of the state. This is confusing; when the call occurs, before the "end", the parameters are a mixture of the two states. In the example above, "I" seems to have two values... > As far as I > can see, this can only happen with Unchecked_Deallaction, so it is > acceptable. Why? Do you never use Unchecked_Deallocation? AFAIK it is the only way to recover global memory resources in Ada, so it is a normal part of Ada programming. I think the clearest solution to point (4) is to say that all of the "scheduled" code is evaluated and executed later (before the "end"). If the programmer needs to save some values that may change, this can be done with ordinary declarations or statements, for example Saved_I : constant Integer := I; Saved_AI : constant Float := A(I); >> You did not discuss if "pragma Scoped" could be executed >> conditionally, as in: >> >> Do_Something ( ... Success => Ok); >> if Ok then >> pragma Scoped (Undo_Something (...)); >> end if; >> >> Is this included in your suggestion? > > The branches of an if statement aren't a > handled_sequence_of_statements, so it's not allowed. Ok, I misunderstood your suggestion: you would only allow pragma Scoped on the "top" level in a handled_sequence_of_statements. But why make this limitation? It seems to me not unlikely that some application may conditionally Open a COBOL_File, and then a similarly conditional Close should occur at the end. One could even let "pragma Scoped" be used in loops and execute the clean-up code just before the present iteration of the loop ends. >> I would >> very much prefer new syntax for a "finally" structure placed at the >> end of the handled_sequence_of_statements, after the exception handler >> if any, over the "pragma" suggestion. > > "finally" was state-of-the-art in 1995. That is not an argument by itself. > I'm not sure if it still can > be considered good language design. Most languages which strive for > exception safety are gradually moving to different constructs (even > Java). That could be an argument. Can you present these "different constructs" here as examples that we could compare to "finally" and to your proposal? -- Niklas Holsti Tidorum Ltd niklas holsti tidorum fi . @ .