!standard 13.13.01 (04) 99-08-31 AI95-00181/03 !standard 13.13.01 (09) !class binding interpretation 97-03-19 !status Corrigendum 2000 99-05-27 !status WG9 Approved 97-11-14 !status ARG Approved (letter ballot: 9-1-1) 97-10-27 !status ARG Approved (subject to letter ballot) 8-1-1 97-04-11 !status work item 97-03-19 !status received 97-03-19 !priority High !difficulty Easy !qualifier Clarification !subject Components of Stream_Element_Array should be Aliased !summary The components of Streams.Stream_Element_Array are aliased: type Stream_Element_Array is array(Stream_Element_Offset range <>) of aliased Stream_Element; ^^^^^^^ Implementation Permission: If Stream_Element'Size is not a multiple of System.Storage_Unit, then the components of Stream_Element_Array need not be aliased. !question 13.13.1(4) does not define the components of Streams.Stream_Element_Array to be aliased. However, this makes various uses of this type inconvenient. What is the intent? !recommendation On machines where it is feasible, the components should be aliased. !wording (See Summary.) !discussion On machines where it is feasible, one should be allowed to form access values pointing to any component within a Stream_Element_Array. However, this package was intentionally designed to support machines where the addressable unit is different from the unit of storage used by the "network". Therefore, the requirement to be aliased is relaxed on such machines. Programmers wishing to write code that is portable to such machines should not take advantage of the aliased components. !corrigendum 13.13.01(4) @dprepl @xcode< @b Stream_Element_Array @b @b(Stream_Element_Offset @b <@>) @b Stream_Element;> @dby @xcode< @b Stream_Element_Array @b @b(Stream_Element_Offset @b <@>) @b Stream_Element;> !corrigendum 13.13.01(9) @dinsa The Write operation appends Item to the specified stream. @dinst @i<@s8> If Stream_Element'Size is not a multiple of System.Storage_Unit, then the components of Stream_Element_Array need not be aliased. !ACATS test A C-Test should be created to check that the components are aliased. There should be applicability criteria allowing the test to be rejected (similarly to the representation clause tests), and marked Not Applicable for an implementation taking advantage of the implementation permission. !appendix !section 13.13.1(00) !subject components of Stream_Element_Array should be ALIASED !reference RM95-13.13.1 !from Ted Baker 97-3-7 !reference 97-15725.a Ted Baker 97-3-7>> !discussion The word "aliased" should be added to the declaration of type Stream_Element array. The intended use of this type is for buffers. When one attempts to use this type for that purpose, one finds it necessary to pass pointers to buffers (and to subfields within buffers) to device drivers or the operating system. At present, this is not possible, and so one either must waste time copying entire buffers into aliased arrays (terribly inefficient) or use some non-portable hack. I suspect the omission of "aliased" was an oversight, and hope that it can be corrected. **************************************************************** !section 13.13.1(00) !subject components of Stream_Element_Array should be ALIASED !reference RM95-13.13.1 !reference as 97-15725.a Ted Baker 97-3-7 !from Ted Baker 97-3-10 !reference 97-15726.a Ted Baker 97-3-9>> !discussion Thanks to Art for pointing our a typo in my posting. "Stream_Element array" should be "Stream_Element_Array". --Ted Baker **************************************************************** !section 13.13.1(0) !subject components of Stream_Element_Array should be ALIASED !reference RM95-13.13.1 !reference 97-15725.a Ted Baker 97-3-7 !from Tucker Taft 97-3-20 !reference 1997-15731.a Tucker Taft 1997-3-20>> !discussion > The word "aliased" should be added to the declaration of type > Stream_Element array. There is no requirement that a Stream_Element be as big as a Storage_Element. In fact, it was anticipated that on word-addressible machines with word sizes such as 24 bits or 36 bits, Stream_Elements would still be 8 or 9 bits, representing the unit of I/O, rather than the unit of addressibility. > The intended use of this type is for buffers. When one attempts > to use this type for that purpose, one finds it necessary to pass > pointers to buffers (and to subfields within buffers) to device > drivers or the operating system. At present, this is not > possible, and so one either must waste time copying entire buffers > into aliased arrays (terribly inefficient) or use some > non-portable hack. Either you can pass a slice, or pass 'Address (which doesn't seem like a non-portable "hack" at this level). > I suspect the omission of "aliased" was an oversight, and hope that > it can be corrected. No, it was not an oversight. We should have explained why. -Tuck **************************************************************** !section 13.13.1(0) !subject components of Stream_Element_Array should be ALIASED !reference RM95-13.13.1 !reference 97-15725.a Ted Baker 97-3-7 !from Ted Baker 97-3-21 !reference 97-15732.a Ted Baker 97-3-21>> !discussion Tucker Taft said: | There is no requirement that a Stream_Element be as big as | a Storage_Element. In fact, it was anticipated that | on word-addressible machines with word sizes such as 24 bits or | 36 bits, Stream_Elements would still be 8 or 9 bits, representing | the unit of I/O, rather than the unit of addressibility. Such machines are rather rare. Could we not at least give a recommendation (or at least permission) for an implementation to add "aliased" to this array type declaration if Stream_Element's are addressable units? This comes from our work with POSIX Ada bindings. We are always interfacing to C libraries for system services. In C, stream elements are referenced as "char *" or "u_char *". In such environments, there is no question about whether a stream element is addressable. | Either you can pass a slice Taking 'unchecked_access of an Ada slice and passing it as a C "char *" will not work, since the slice includes the index range information which the C side is not expecting. | or pass 'Address (which doesn't seem | like a non-portable "hack" at this level). Yes, I am currently using 'Address and unchecked-converting it to an Ada type that corresponds to a C "char *" -- just like I did in Ada'83. This makes the whole Ada'95 business of Interfaces.C, 'unchecked_access, etc. look pretty futile. --Ted Baker **************************************************************** !section 13.13.1(0) !subject components of Stream_Element_Array should be ALIASED !reference RM95-13.13.1 !reference 97-15725.a Ted Baker 97-3-7 !reference 97-15731.a Tucker Taft 97-3-20 !reference 97-15732.a Ted Baker 97-3-21 !from Tucker Taft 97-3-21 !reference 1997-15734.a Tucker Taft 1997-3-21>> !discussion > Tucker Taft said: > > | There is no requirement that a Stream_Element be as big as > | a Storage_Element. In fact, it was anticipated that > | on word-addressible machines with word sizes such as 24 bits or > | 36 bits, Stream_Elements would still be 8 or 9 bits, representing > | the unit of I/O, rather than the unit of addressibility. > > Such machines are rather rare. Could we not at least give a > recommendation (or at least permission) for an implementation to > add "aliased" to this array type declaration if Stream_Element's > are addressable units? This seems like the wrong way to "address" this problem ;-). How about declaring your own array type Aliased_Stream_Element_Array, and converting to that when you need to take '[Unchecked_]Access. Surprisingly, and perhaps mistakenly, conversions are permitted from an array with unaliased components to one with aliased components. Now whether that will result in a copy depends on the compiler, but I suspect it won't in any compiler for which stream elements are individually addressible (though heaven help the high-powered optimizer). That should be as portable as relying on the vendor to put "aliased" on Stream_Element itself. > This comes from our work with POSIX Ada bindings. > We are always interfacing to C libraries for system services. > In C, stream elements are referenced as "char *" or "u_char *". > In such environments, there is no question about whether a > stream element is addressable. Actually, it was the POSIX idea of "IO_element" or equivalent that suggested that we define Stream_Element rather than reuse Storage_Element. > --Ted Baker -Tuck **************************************************************** !section 13.13.1(0) !subject components of Stream_Element_Array should be ALIASED !reference RM95-13.13.1 !reference 97-15725.a Ted Baker 97-3-7 !reference 97-15731.a Tucker Taft 97-3-20 !reference 97-15732.a Ted Baker 97-3-21 !from Ted Baker 97-3-21 !reference 97-15735.a Ted Baker 97-3-21>> !discussion | How about declaring your own array type Aliased_Stream_Element_Array, | and converting to that when you need to take '[Unchecked_]Access. | Surprisingly, and perhaps mistakenly, conversions are permitted | from an array with unaliased components to one with aliased | components. Now whether that will result in a copy depends | on the compiler, but I suspect it won't in any compiler for | which stream elements are individually addressible (though heaven | help the high-powered optimizer). That should be as portable | as relying on the vendor to put "aliased" on Stream_Element itself. Interesting idea. I will try it with GNAT, and see whether a copy is generated. | Actually, it was the POSIX idea of "IO_element" or equivalent | that suggested that we define Stream_Element rather than reuse | Storage_Element. Very strange. That must have been a very early draft you looked at. There is no "IO_Element" in the POSIX.5 standard. The IO operations are defined as follows: subtype IO_Buffer is POSIX.POSIX_String; procedure Read (File: in File_Descriptor; Buffer: out IO_Buffer; Last: out POSIX.IO_Count; Masked_Signals: in POSIX.Signal_Masking:= POSIX.RTS_Signals); procedure Write -- obsolescent (File: in File_Descriptor; Buffer: in IO_Buffer; Last: out POSIX.IO_Count; Masked_Signals: in POSIX.Signal_Masking:= POSIX.RTS_Signals); In POSIX.5b, these are marked as obsolescent. The new interfaces are: procedure Read (File: in File_Descriptor; Buffer: out Ada_Streams.Stream_Element_Array; Last: out Ada_Streams.Stream_Element_Offset; Masked_Signals: in POSIX.Signal_Masking:= POSIX.RTS_Signals); procedure Write (File: in File_Descriptor; Buffer: in Ada_Streams.Stream_Element_Array; Last: out Ada_Streams.Stream_Element_Offset; Masked_Signals: in POSIX.Signal_Masking:= POSIX.RTS_Signals); The message queue extensions use the same style: procedure Send (MQ: in Message_Queue_Descriptor; Message: in Ada_Streams.Stream_Element_Array; Priority: in Message_Priority; Masked_Signals: in POSIX.Signal_Masking:= POSIX.RTS_Signals); procedure Receive (MQ: in Message_Queue_Descriptor; Message: out Ada_Streams.Stream_Element_Array; Last: out Ada_Streams.Stream_Element_Offset; Priority: out Message_Priority; Masked_Signals: in POSIX.Signal_Masking:= POSIX.RTS_Signals); IEEE Std 1003.5b-1996 also specifies some other things: Instantiation of Unchecked_Conversion shall be supported for conversions, in both directions, between the type Ada_Streams.Stream_Element_Array and all other types. The function To_POSIX_String taking arguments of type Stream_Element_Array shall convert an Ada_Streams.Stream_Element_Array value to a POSIX_String value. The function To_Stream_Element_Array shall convert a POSIX_String value to a Ada_Streams.Stream_Element_Array value. These operations shall obey the semantics of instantiations of Unchecked_Conversion, as defined in [ARM 13.9 J.1]. I suspect now that the first quoted paragraph above was probably a mistake, and maybe the second also. Users of the POSIX Ada binding will routinely need to perform bitwise conversions to and from segments of Stream_Element_Array, and will need some portable POSIX way of doing this that they can rely will not involve making extra copies. --Ted Baker (wearing hat of JTC1 Project Editor for POSIX Ada bindings on top of ARG hat) **************************************************************** !section 13.13.1(0) !subject components of Stream_Element_Array should be ALIASED !reference RM95-13.13.1 !reference 97-15725.a Ted Baker 97-3-7 !reference 97-15731.a Tucker Taft 97-3-20 !from Randy Brukardt 97-3-21 !reference 97-15736.a Randy Brukardt 97-3-21>> !discussion >> The word "aliased" should be added to the declaration of type >> Stream_Element array. > >There is no requirement that a Stream_Element be as big as >a Storage_Element. In fact, it was anticipated that >on word-addressible machines with word sizes such as 24 bits or >36 bits, Stream_Elements would still be 8 or 9 bits, representing >the unit of I/O, rather than the unit of addressibility. Indeed, in the U2200 compiler, we did exactly that. Storage_Element'Size = 36; Stream_Element'Size =9. That was the only way to match the operating system (a Unix variant) behavior. **************************************************************** !section 13.13.1(0) !subject components of Stream_Element_Array should be ALIASED !reference RM95-13.13.1 !reference 97-15725.a Ted Baker 97-3-7 !reference 97-15731.a Tucker Taft 97-3-20 !reference 97-15732.a Ted Baker 97-3-21 !reference 1997-15734.a Tucker Taft 1997-3-21 !from Bob Duff !reference 97-15738.a Robert A Duff 97-3-22>> !discussion > Actually, it was the POSIX idea of "IO_element" or equivalent > that suggested that we define Stream_Element rather than reuse > Storage_Element. As I recall, we originally used Storage_Element, but we changed it because we wanted to make Streams declared-Pure. But we did not make System declared-Pure, because some compiler vendor(s) wanted to use an access type as the full type for type Address. Given that, it would be illegal to make Streams depend on System. Then, having decided that Streams needed its own type, we realized that it made sense for this type to be of a different size than Storage_Element, at least on some machines. - Bob ****************************************************************