!standard 6.3.2(3) 01-10-16 AC95-00016/01 !class amendment 01-10-16 !status received no action 01-10-10 !subject pragma Read_Only !summary !appendix From: V. Santhanam (Boeing) Sent: Wednesday, October 10, 2001 9:12 AM Issue: In Ada, it is awkward to create a variable in a package for read/write use internally but read-only use by clients. To achieve this, one would have to declare the variable either in the private part of the package spec or in the body, and provide a visible function to read the variable. Solution: Provide a Read_Only pragma which can be applied to variables in the visible part of a package so that they are treated as constants by the clients of the package. Example: Error_Count : Natural := 0; pragma Read_Only (Error_Count); The read-only restriction is not applicable the declaring package itself. Reasoning: The reader function approach incurs a significant run-time penalty. I know of at least one program in which a decision was made to declare all such variables in the visible part of the package, exposing them to potential modifications by clients, in order to avoid the function call penalty. Inlining the function call was not an option for certification reasons. The proposed solution will avoid the run-time penalty without sacrificing safety. **************************************************************** From: Randy Brukardt Sent: Tuesday, October 16, 2001 7:12 PM > The reader function approach incurs a significant run-time penalty. It shouldn't have any runtime penalty, if combined with a pragma Inline. Why doesn't that solve your problem without introducing any new language features? (If your vendor doesn't Inline these properly, either pressure or change the vendor! This is the sort of thing that Inline was designed to handle). **************************************************************** From: Craig Carey Sent: Thursday, October 18, 2001 7:23 PM At 2001.October.10 09:12 -0500 Wednesday, Santhanam, Vdot wrote: >Issue: > >In Ada, it is awkward to create a variable in a package for read/write use >internally but read-only use by clients. To achieve this, one would have to >declare the variable either in the private part of the package spec or in >the body, and provide a visible function to read the variable. > >Solution: > >Provide a Read_Only pragma which can be applied to variables in the visible What about "exported constant" (etc.) ?, or "pragma Export_As_Constant(...)" ?. 'Read_Only' sounds like a description that can make the variable be constant, even inside of the body of the package. >part of a package so that they are treated as constants by the clients of >the package. Example: > > Error_Count : Natural := 0; > pragma Read_Only (Error_Count); > >The read-only restriction is not applicable the declaring package itself. > In GNAT there is this error message: "error: access-to-variable designates constant"; when the 'Access attribute is applied to a constant. Pointers to constants can't be assigned and the language does not dynamically keep track of whether a pointer is to a constant or to a variable. I saw a comment (not public at this list) that suggested that this could be a difficult thing for a compiler vendor to implement. Note that there was no mention of interfacing with another language, e.g. C. ------------------------------------------------- At 2001.October.16 19:13 -0500 Tuesday, Randy Brukardt wrote: > >> The reader function approach incurs a significant run-time penalty. > >It shouldn't have any runtime penalty, if combined with a pragma Inline. >Why doesn't that solve your problem without introducing any new language >features? It could be bugs in the compiler that Boeing was using or a suspicion of them. > (If your vendor doesn't Inline these properly, either pressure or >change the vendor! This is the sort of thing that Inline was designed to >handle). > Inlining is something that may not happen even after the compiler is told to inline. If it is a serious suggestion, then universities could teach students how to study Ada code in its assembly language form. In GNAT there are restrictions on inlining: (quoting from the user guide): "The call appears in a body (not in a package spec).". Also the -gnatn option must be specified and so must a -O1 or -On optimising option. An option could be to put the many variables of the package spec, into a a single record and then have two of those records overlaid. One record would be constant and exported to other packages. The other record would be not constant, and its components could be used inside of the package. Some trick I can't think of at the moment is used to circumvent the prohibition against applying 'Access to a constant. That could be regarded as a proof that compiler vendors can implement the feature easily. But I am not sure. Another option might be to have a simple dummy package to get around the safety problem. Here is an example": generic Pkg_Security_ID_Code : Boolean; package West_Coast_Consts is ... A69 : constant Boolean := East_Coast_Vars.A96; ... -- 555 more lines end West_Coast_Consts; **************************************************************** From: Tucker Taft Sent: Thursday, October 18, 2001 9:18 PM [Perhaps this was already suggested?] One quite efficient way to accomplish this is to make the variable aliased but in the private part, and then export an access-to-constant pointing to it, as follows: package P is type T is ...; type Acc_Const_T is access constant T; Read_Only_Ptr : constant Acc_Const_T; -- Read_Only_Ptr.all is read-only ... private Read_Write_Variable : aliased T; Read_Only_PTr : constant Acc_Const_T := Read_Write_Variable'Access; ... end P; I suppose one simple language change would be to allow a deferred "constant" to be completed with a variable declaration. However, that might mask true errors. **************************************************************** From: Pascal Leroy Sent: Friday, October 19, 2001 1:21 AM I believe that you can do that by completing the deferred constant by a pragma Import, and exporting the variable with a pragma Export, both pragmas having convention Ada. Of course, this is assuming that your compiler supports these pragmas, but then convention Ada is not too hard to support. **************************************************************** From: Robert Dewar Sent: Friday, October 19, 2001 10:05 AM But one would think that most coding standards should prohibit this usage, since it takes you totally outside the Ada type system (it is really amazing how much damage pragma Import/Export (Ada does to the Ada model, for instance it also allows you to go completely outside the elaboration model). **************************************************************** From: Robert Duff Sent: Friday, October 19, 2001 12:13 PM I evilly use it to put debugging printouts in pragma-Pure packages! **************************************************************** From: V. Santhanam (Boeing) Sent: Friday, October 19, 2001 8:44 AM I am trying to catch up on the various e-mail messages that have gone back and forth on this subject. Let me begin by pointing out that inlining was not an option on the programs in which I encountered the need, due to certification reasons. If it is not immediately obvious why certification authorities have heartburn with inlining, let me know and I will explain the rationale. **************************************************************** From: Robert Dewar Sent: Friday, October 19, 2001 9:43 AM <> Well in this particular case the restriction on calls in the spec could not be an issue, since this would be an access before elaboration error. As for requiring optimization for inlining, I see no problem with that. It seems to me that, for GNAT at least, there is zero penalty for using a function for this purpose, so the proposed feature adds no expressive power, or efficiency gain. **************************************************************** From: Pascal Leroy Sent: Sunday, October 21, 2001 3:52 AM > If it is not immediately obvious why certification > authorities have heartburn with inlining, let me know and I will explain > the rationale. But then I fail to see why the same certification authorities would not have the same heartburn with pragma Read_Only. If the problem with inlining is that you don't trust the optimizers to do the right thing, then surely pragma Read_Only would be much worse. In essence we would have an object which is constant when seen from certain places and variable when seen from other places. Now constancy is a fundamental property for optimizers, as they use it to avoid reevaluating certain expressions. If constancy can vary from place to place, I am ready to bet that optimizers would occasionally get confused, and assume constancy at the wrong place, resulting in plague and pestilence. **************************************************************** From: Dan Eilers Sent: Thursday, October 25, 2001 2:46 AM I believe the certification authorities who don't trust optimizers to do the right thing with inlining, don't trust optimizers in general. So they insist that the optimizer be turned off. The idea of pragma Read_Only is that it should generate reasonable code without needing the optimizer. Unfortunately, this isn't the only case in Ada where optimization is relied on to generate reasonable code. **************************************************************** From: Randy Brukardt Sent: Thursday, October 25, 2001 12:51 PM > But then I fail to see why the same certification authorities would not > have the same heartburn with pragma Read_Only. ... An even more important question is why those certification authorities would have a problem with Tucker's suggested why to get this behavior in Ada 95 with very little extra code. To remind, his suggestion was to export an access-to-constant type and a constant object which points at the variable that you need to protect from outside modification. The original example would look like: package Stuff is ... type Access_Error_Count is access constant Natural; Error_Count_Access : constant Access_Error_Count; ... private ... Error_Count : aliased Natural := 0; Error_Count_Access : constant Access_Error_Count := Error_Count'access; ... end Try; This is perfectly legal Ada 95. The overhead is only a single dereference per use (plus a null check if the compiler is stupid). The accesses can't fail (Error_Count_Access is not null). No dynamic allocation is involved (one could put an empty storage pool on the type to insure this, if the certification guys are freaked out by it). If one of the Ada 0y proposals is adopted, we could even declare that the object cannot be null (eliminating the check and the only realistic objection that I can think of): type Access_Error_Count is access constant Natural not null; So why do we need a complex (to implement and describe in RM language) new feature here??? **************************************************************** From: Craig Carey Sent: Thursday, October 25, 2001 12:51 PM At 01.10.19 08:20 +0200 Friday, Pascal Leroy wrote: >> I suppose one simple language change would be to allow a deferred >> "constant" to be completed with a variable declaration. > >I believe that you can do that by completing the deferred constant by a >pragma Import, and exporting the variable with a pragma Export, both pragmas >having convention Ada. Of course, this is assuming that your compiler >supports these pragmas, but then convention Ada is not too hard to support. > >Pascal > I tried that and it seems to be a solution. [No syntax error can appear [in GNAT] when the text in the External_Name is wrong (but that was with the imported local variable being not used). So some of the checking could be done after the compile.] ----- There is also this associated topic of read-only record fields!. I guess that neither feature: read-only spec vars, read-only non-discrete record fields; may arrive in Ada 0y unless the two appear together. I found out that Ada 95 has already implemented read-only record fields, in its own way. Research into the usage of Ada quite possibly might show that the current syntax is not designed quite right. Here is an example showing how to have a read-only access type. ---------------------------------------- package P is type TP is access all TR; Null_TP : aliased constant TP := new TR'(...); type T (Ptr : TP := Null_TP) is limited null record; procedure G (L : in out T); end P; package body P is procedure G (L : in out T) is X : TP; for X'Address use L.Ptr'Address; begin X := new TR'(...); end G; end P; -- The use of 'limited' makes T be passed by reference (RM 6.2) -- whenever it is passed as a parameter. ---------------------------------------- The syntax above looks like it is one that users do not know about or that former C programmers might want to avoid even if they do know about it (unless they like using 'Address). I had to get information by e-mail before I found out that Ada 95 already implements read-only record fields. The last Rationale on "the needs of users" said this: >Wherever possible, enhanced functionality in Ada 95 has been achieved by >seeking and eliminating such unnecessary assumptions, thereby permitting >the generalization of features already in Ada, and the removal of special >cases and restrictions. Someone with similar views, might be noting that: Ada 95 implements a constant or read-only record field feature, but only for fields that are an access type or a discrete type. RM 3.7 says: >A discriminant of an object is a component of the object, and is either >of a discrete type or an access type. What about making removing the read-only feature from discriminants?. Variants could be auto-resized as needed. While it could be opposed, it could improve consistency inside the topic. ----- At 01.10.21 10:51 +0200 Sunday, Pascal Leroy wrote: >> If it is not immediately obvious why certification >> authorities have heartburn with inlining, let me know and I will explain >> the rationale. > >But then I fail to see why the same certification authorities would not have >the same heartburn with pragma Read_Only. If the problem with inlining is >that you don't trust the optimizers to do the right thing, then surely >pragma Read_Only would be much worse. In essence we would have an object >which is constant when seen from certain places and variable when seen from >other places. Now constancy is a fundamental property for optimizers, as >they use it to avoid reevaluating certain expressions. If constancy can >vary from place to place, I am ready to bet that optimizers would >occasionally get confused A read-only field or spec variable ought be seen as being not 'constant' if this is feature occurs: procedures in the defining package can freely alter that package's read-only fields and exported read-only variables. Currently seems improvable: to make a record field be read-only, this sort technique can be used: package Code_Quality_Stats is ... type EC_Ptr is access constant EC_Rec; type Safe ( ... Error_Counters : EC_Ptr; -- lots of fields ... ) is limited null record; ... end Code_Quality_Stats is The keyword 'aliased' is not allowed for discriminant declarations. Can Ada be made so that users get a guarantee that the memory holding the value of the discriminant will always be able to be written too, no matter what the machine ?. The rationale listed interfacing (with C, etc.) as a 1st aim (that was in "I.3 The main user needs", Intermetrics, Jan 1995). The use of 'private' interferes with interfacing and the finer control of allowing specifying of a read-only property can advance a need seen by Intermetrics years ago. If record fields can be read-only then why not just make the package spec variables also be able to be read-only ?. It is an indirect way to solving that issue. ****************************************************************