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.3 required=5.0 tests=BAYES_00,INVALID_MSGID autolearn=no autolearn_force=no version=3.4.4 X-Google-Language: ENGLISH,ASCII-7-bit X-Google-Thread: 103376,3ccb707f4c91a5f2 X-Google-Attributes: gid103376,public From: dewar@merv.cs.nyu.edu (Robert Dewar) Subject: Re: Unbounded strings (Was: Java vs Ada 95 (Was Re: Once again, Ada absent from DoD SBIR solicitation)) Date: 1996/11/23 Message-ID: #1/1 X-Deja-AN: 198289014 references: <325BC3B3.41C6@hso.link.com> organization: New York University newsgroups: comp.lang.ada Date: 1996-11-23T00:00:00+00:00 List-Id: Bob Duff asks "And you still haven't answered my main objection to your reading -- if you read it that way, then why isn't practically everything in Annex A erroneous? And lots of other stuff. E.g: X, Y: Calendar.Time := Clock; X := Y; -- Erroneous? (No tasks here.) How do we know that the implementer has not evilly made the full type for Time controlled, with an Adjust routine that does something erroneous? Or raises GNAT.Evil_Exceptions ...." No, I don't accept this as equivalent. The issue of the extent to which library routines are task/thread safe is quite different from the issue of single task semantics, which I think is clearly defined, and that is why the above example definitely cannot be erroneous. Obviously it is not the case that anything works in a threaded environment. Your answer indeed agrees that certain things will be erroneous (e.g. if the above assignment X := Y appeared in two tasks with no synhronization then you would agree that it is probably erroneous -- not necessarily of course, since the implementatoin may have a pragma atomic on its Calendar.Time type, so this kind of erroneousness is definitely impl dependent to some extent. So just what *is* task safe, well the only guideline we have is the clause in the reference manual that you don't think should be there, but I think Tuck clearly was right to insist on it, otherwise we could not assume anything about task safety of the libraryt routines. As for your Text_IO example, what exactly IS required if two tasks do a Put_Line to the same file at the same time? To me that can still be erroneous (it is the same case as any other case where two tasks molest the same variable, in this case the object for the file type) at the same time, and I can't see why even the phrase in the RM that you think is redundant gathers otherwise. Let's repeat the RM phrase for reference: 3 The implementation shall ensure that each language defined subprogram is reentrant in the sense that concurrent calls on the same subprogram perform as specified, so long as all parameters that could be passed by reference denote nonoverlapping objects. Even if we decide that for the case of Put_Line with no file argument *is* covered by this phrase, what does it mean? What level of interspersing of output is implied by this wording (lines, characters, pixels???) And of course it is quite clear that two writes to the same file using Put_Line with a file argument are NOT covered by paragraph 3. So that's mightly curious: Put_Line (Standard_Output, "xxxx"); appearing in two tasks is not covered, and could be erroneous, but Put_Line ("xxxx"); is OK. That seems quite weird to me, though I see how paragraph 3 could be read this way. Without paragraph 3, I have no idea why Bob Duff thinks that the language has anything to say about either of these cases. Friendly readings are fine, but I do not know what is friendly and what is not. Let' s look at the reference count case. I see two friendly readings here: 1. An efficient implementation with reference counts is permitted, no locks are needed, since if two tasks mess with the same sets of variables or values, the execution is erroneous. 2. If reference counts are used, task locks are required, requiring a kernel call on some systems, and therefore, becuase of the quite unacceptable efficiency effect, reference counts are out of the question. Which of these is friendlier? Well if you don't use tasking, or if you use only completely separated sets of values and variables in the tasking case, you find 1 much friendlier, since a reference count implementation makes a lot of sense in these cases. If you insist on using unbounded strings across tasks, thinking that the assignment semantics are like ordinary scalar types, then of course you might find 1 friendlier. Relying on a friendly reading is risky. I must say that initially I assumed that reference counts could not be used and that consequently a copy on modify approach is not practical, but I found Robert Eachus argument here illuminating and convincing. So Bob Duff thinks that the RM should say nothing, and that we should rely on a friendly reading of what is and is not erroneous (he agrees that certain calls to runtime routines are erroneous because of violating shared variable rules, so this is a question of judgment). But in this case (reference counts), people do not agree on what is friendly. So I think it is something the ARG should pin down. I don't think that either decision (1 or 2 above) would be a major problem, but failure to resolve this could lead to a very significant portability problem.