* Behavior of Stream Attributes On Access Types. @ 2002-06-10 19:38 Marin David Condic 2002-06-11 5:33 ` R. Tim Coslet ` (2 more replies) 0 siblings, 3 replies; 19+ messages in thread From: Marin David Condic @ 2002-06-10 19:38 UTC (permalink / raw) I'm checking section 13.13.2 of the ARM to discover the default behavior of the Stream 'Read, 'Write, 'Input and 'Output when they encounter an access type. I'm not finding any clear indication of what gets put to the stream - although there is a mention in paragraph 35 of raising Constraint_Error on input if the value is not of its subtype. Can someone clarify the behavior? My inclination is to think that the sensible thing would be to call the 'Read or 'Write for the thing pointed to by the access type, but this has implications for dynamically allocated objects. Will it write/read a (totally useless) access value? MDC -- Marin David Condic Senior Software Engineer Pace Micro Technology Americas www.pacemicro.com Enabling the digital revolution e-Mail: marin.condic@pacemicro.com ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: Behavior of Stream Attributes On Access Types. 2002-06-10 19:38 Behavior of Stream Attributes On Access Types Marin David Condic @ 2002-06-11 5:33 ` R. Tim Coslet 2002-06-11 14:15 ` Marin David Condic 2002-06-11 13:47 ` Ted Dennison 2002-06-12 3:44 ` David C. Hoos, Sr. 2 siblings, 1 reply; 19+ messages in thread From: R. Tim Coslet @ 2002-06-11 5:33 UTC (permalink / raw) As I understand it, the LRM simply leaves it "implementation defined". I don't expect the value to be of any use... I always write custom 'Read and 'Write functions for access types specifically designed to instead read or write the "subtree" of the data structure the access points to, instead of the value. Of course this only works for types used to define simple "linear" and "tree" shaped data structures. It would get much more involved for the "general" case. -- R. Tim Coslet r_tim_coslet@pacbell.net Technology, n. Domesticated natural phenomena. > From: "Marin David Condic" <dont.bother.mcondic.auntie.spam@[acm.org> > Organization: Posted on a server owned by Pace Micro Technology plc > Newsgroups: comp.lang.ada > Date: Mon, 10 Jun 2002 15:38:20 -0400 > Subject: Behavior of Stream Attributes On Access Types. > > I'm checking section 13.13.2 of the ARM to discover the default behavior of > the Stream 'Read, 'Write, 'Input and 'Output when they encounter an access > type. I'm not finding any clear indication of what gets put to the stream - > although there is a mention in paragraph 35 of raising Constraint_Error on > input if the value is not of its subtype. Can someone clarify the behavior? > > My inclination is to think that the sensible thing would be to call the > 'Read or 'Write for the thing pointed to by the access type, but this has > implications for dynamically allocated objects. Will it write/read a > (totally useless) access value? > > MDC > -- > Marin David Condic > Senior Software Engineer > Pace Micro Technology Americas www.pacemicro.com > Enabling the digital revolution > e-Mail: marin.condic@pacemicro.com > > > ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: Behavior of Stream Attributes On Access Types. 2002-06-11 5:33 ` R. Tim Coslet @ 2002-06-11 14:15 ` Marin David Condic 0 siblings, 0 replies; 19+ messages in thread From: Marin David Condic @ 2002-06-11 14:15 UTC (permalink / raw) That's kind of how I've been handling it - overriding the "default" case with my own operations to get linked data structures in and out of streams. I was just wondering what the ARM had to say on what the "default" case is - if I have a record with pointers to other things and just do a 'Write, what happens? Given the nature of the beast, its hard to imagine anything happening that would be at all useful, so I guess the answer is "Always Roll Your Own." MDC -- Marin David Condic Senior Software Engineer Pace Micro Technology Americas www.pacemicro.com Enabling the digital revolution e-Mail: marin.condic@pacemicro.com "R. Tim Coslet" <R_Tim_Coslet@pacbell.net> wrote in message news:B92AD893.4284%R_Tim_Coslet@pacbell.net... > As I understand it, the LRM simply leaves it "implementation defined". > > I don't expect the value to be of any use... > > I always write custom 'Read and 'Write functions for access types > specifically designed to instead read or write the "subtree" of the data > structure the access points to, instead of the value. > > Of course this only works for types used to define simple "linear" and > "tree" shaped data structures. It would get much more involved for the > "general" case. > ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: Behavior of Stream Attributes On Access Types. 2002-06-10 19:38 Behavior of Stream Attributes On Access Types Marin David Condic 2002-06-11 5:33 ` R. Tim Coslet @ 2002-06-11 13:47 ` Ted Dennison 2002-06-11 14:27 ` Marin David Condic 2002-06-11 21:56 ` Randy Brukardt 2002-06-12 3:44 ` David C. Hoos, Sr. 2 siblings, 2 replies; 19+ messages in thread From: Ted Dennison @ 2002-06-11 13:47 UTC (permalink / raw) "Marin David Condic" <dont.bother.mcondic.auntie.spam@[acm.org> wrote in message news:<ae2v7f$r12$1@nh.pace.co.uk>... > My inclination is to think that the sensible thing would be to call the > 'Read or 'Write for the thing pointed to by the access type, but this has You can pretty much count on it *not* doing that. For instance, what would happen in that case with a circularly-referenced structure like a doubly-linked list? > implications for dynamically allocated objects. Will it write/read a > (totally useless) access value? Pretty much. It isn't *totally* useless. It will work just fine within the same execution (assuming you don't deallocate the memory). However, it is next to useless. If you want better behavior, its up to you to override 'Write and 'Read for your pointer type. Then you can code it to handle things like circular references and deallocating the target's old value on a 'Read. -- T.E.D. Home - mailto:dennison@telepath.com (Yahoo: Ted_Dennison) Homepage - (temporarily down) ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: Behavior of Stream Attributes On Access Types. 2002-06-11 13:47 ` Ted Dennison @ 2002-06-11 14:27 ` Marin David Condic 2002-06-11 14:37 ` Marin David Condic 2002-06-12 13:31 ` Ted Dennison 2002-06-11 21:56 ` Randy Brukardt 1 sibling, 2 replies; 19+ messages in thread From: Marin David Condic @ 2002-06-11 14:27 UTC (permalink / raw) "Ted Dennison" <dennison@telepath.com> wrote in message news:4519e058.0206110547.526d2369@posting.google.com... > "Marin David Condic" <dont.bother.mcondic.auntie.spam@[acm.org> wrote in message news:<ae2v7f$r12$1@nh.pace.co.uk>... > > My inclination is to think that the sensible thing would be to call the > > 'Read or 'Write for the thing pointed to by the access type, but this has > > You can pretty much count on it *not* doing that. For instance, what > would happen in that case with a circularly-referenced structure like > a doubly-linked list? > Giving it a few minutes of thought after I posted, this case occurred to me. Initially, I was thinking about what would make sense and certainly storing the access value is of minimal use the instant it goes out to a file or down a wire. Hence, I thought, "Well maybe it should store the object pointed to..." But clearly, as you point out, its an interesting opportunity to create infinite recursion. > > > implications for dynamically allocated objects. Will it write/read a > > (totally useless) access value? > > Pretty much. It isn't *totally* useless. It will work just fine within > the same execution (assuming you don't deallocate the memory). > However, it is next to useless. > Yeah, I just can't think of many cases where I want to write something into a stream and not have it persist across executions or partitions or whatever, wherein the address starts becoming a totally useless piece of information. In the same execution? Why wouldn't I just keep referencing the data structure I've already got? I suppose the language needs to do *something* if it encounters an access type going into or out of a stream, but its hard to imagine how one might make use of it. > If you want better behavior, its up to you to override 'Write and > 'Read for your pointer type. Then you can code it to handle things > like circular references and deallocating the target's old value on a > 'Read. > > Basically, that's been the story. I was just wondering what the ARM had to say about the default case & couldn't spot something explicit enough to clear through the fog. Thanks for the help. MDC -- Marin David Condic Senior Software Engineer Pace Micro Technology Americas www.pacemicro.com Enabling the digital revolution e-Mail: marin.condic@pacemicro.com ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: Behavior of Stream Attributes On Access Types. 2002-06-11 14:27 ` Marin David Condic @ 2002-06-11 14:37 ` Marin David Condic 2002-06-12 14:19 ` David C. Hoos 2002-06-12 19:39 ` Randy Brukardt 2002-06-12 13:31 ` Ted Dennison 1 sibling, 2 replies; 19+ messages in thread From: Marin David Condic @ 2002-06-11 14:37 UTC (permalink / raw) Just to make sure I'm getting this correct in my brain, try this one out for me: I have a tagged record that does not have any access values in it, so using the standard-issue 'Output and 'Input is just fine. I inherit from this and add some access values, so I need to create my own 'Read and 'Write, correct? (But not 'Output and 'Input) Then, 'Output and 'Input for that descendent should work correctly without overriding anything, right? Further, using the base type's 'Class'Output and 'Class'Input should work correctly by dispatching up the ladder to find my home-grown 'Read and 'Write, correct? Then, just to make it more interesting, I inherit from the second type and add more (non-access) fields. I *must* override my own 'Read and 'Write to include the newly added fields? Or will it dispatch to the 'Read and 'Write in the second level, then go on to call the defaults for the newly added fields? My brain hurts! :-) MDC -- Marin David Condic Senior Software Engineer Pace Micro Technology Americas www.pacemicro.com Enabling the digital revolution e-Mail: marin.condic@pacemicro.com > "Ted Dennison" <dennison@telepath.com> wrote in message > news:4519e058.0206110547.526d2369@posting.google.com... > > If you want better behavior, its up to you to override 'Write and > > 'Read for your pointer type. Then you can code it to handle things > > like circular references and deallocating the target's old value on a > > 'Read. > > ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: Behavior of Stream Attributes On Access Types. 2002-06-11 14:37 ` Marin David Condic @ 2002-06-12 14:19 ` David C. Hoos 2002-06-12 15:18 ` Marin David Condic 2002-06-12 19:39 ` Randy Brukardt 1 sibling, 1 reply; 19+ messages in thread From: David C. Hoos @ 2002-06-12 14:19 UTC (permalink / raw) ----- Original Message ----- From: "Marin David Condic ]" <dont.bother.mcondic.auntie.spam@[acm.org> Newsgroups: comp.lang.ada To: <comp.lang.ada@ada.eu.org> Sent: Tuesday, June 11, 2002 9:37 AM Subject: Re: Behavior of Stream Attributes On Access Types. > Just to make sure I'm getting this correct in my brain, try this one out for > me: I have a tagged record that does not have any access values in it, so > using the standard-issue 'Output and 'Input is just fine. I inherit from > this and add some access values, so I need to create my own 'Read and > 'Write, correct? (But not 'Output and 'Input) Then, 'Output and 'Input for > that descendent should work correctly without overriding anything, right? > Further, using the base type's 'Class'Output and 'Class'Input should work > correctly by dispatching up the ladder to find my home-grown 'Read and > 'Write, correct? Then, just to make it more interesting, I inherit from the > second type and add more (non-access) fields. I *must* override my own 'Read > and 'Write to include the newly added fields? Or will it dispatch to the > 'Read and 'Write in the second level, then go on to call the defaults for > the newly added fields? > You only need to add read and write for the _access_ types. 'Output and 'Input are never overridden, as they always use 'Read and 'Write. The only other cases for which I have had to override the standard stream attributes is when there are machine endianess issues in network representation of data. Did you look at my example of how I do it? ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: Behavior of Stream Attributes On Access Types. 2002-06-12 14:19 ` David C. Hoos @ 2002-06-12 15:18 ` Marin David Condic 2002-06-13 3:00 ` David C. Hoos, Sr. 2002-06-14 18:27 ` Simon Wright 0 siblings, 2 replies; 19+ messages in thread From: Marin David Condic @ 2002-06-12 15:18 UTC (permalink / raw) Yes. That was helpful. But I'm still curious about how it would be done with the scenario I described because I want to understand the inheritance issues. (I can see that it would be better to handle the access values as you describe, but in a more "general" sense - can you describe what happens with the 'Read and 'Write as we travel down the chain of inheritance?) Here's some code snippets to illustrate the questions I have... package Level_1 is type L1 is tagged record A : Integer ; end record ; -- -- Here I have L1'Read, L1'Write, L1'Input, L1'Output -- and L1'Class'Read L1'Class'Write L1'Class'Input L1'Class'Output -- end Level_1 ; package Level_1.Level_2 is type L2 is new Level_1.L1 with record B : Some_Access_Type := null ; end record ; -- -- Now I have to define my own 'Read and 'Write -- procedure My_Read .... for L2'Read use My_Read... procedure My_Write ..... for L2'Write use My_Write... -- -- Here I now have for free L2'Input, L2'Output -- Further L1'Class'Read L1'Class'Write L1'Class'Input L1'Class'Output -- will dispatch to My_Read and My_Write if an L2 parameter is passed? -- end Level_1.Level_2 ; package Level_1.Level_2.Level_3 is type L3 is new Level_2.L2 with record C : Integer ; end record ; -- -- Now must I define my own 'Read and 'Write??? -- procedure My_Read .... for L3'Read use My_Read... procedure My_Write ..... for L3'Write use My_Write... -- -- Or will a call to L1'Class'Write hit the "My_Write" from -- Level_2 to output the access type, then call the default -- 'Write for the new "C" field? -- end Level_1.Level_2.Level_3 ; MDC -- Marin David Condic Senior Software Engineer Pace Micro Technology Americas www.pacemicro.com Enabling the digital revolution e-Mail: marin.condic@pacemicro.com "David C. Hoos" <david.c.hoos.sr@ada95.com> wrote in message news:mailman.1023891618.16755.comp.lang.ada@ada.eu.org... > > Did you look at my example of how I do it? > > > ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: Behavior of Stream Attributes On Access Types. 2002-06-12 15:18 ` Marin David Condic @ 2002-06-13 3:00 ` David C. Hoos, Sr. 2002-06-14 18:27 ` Simon Wright 1 sibling, 0 replies; 19+ messages in thread From: David C. Hoos, Sr. @ 2002-06-13 3:00 UTC (permalink / raw) ----- Original Message ----- From: "Marin David Condic ]" <dont.bother.mcondic.auntie.spam@[acm.org> Newsgroups: comp.lang.ada To: <comp.lang.ada@ada.eu.org> Sent: June 12, 2002 10:18 AM Subject: Re: Behavior of Stream Attributes On Access Types. > Yes. That was helpful. But I'm still curious about how it would be done with > the scenario I described because I want to understand the inheritance > issues. (I can see that it would be better to handle the access values as > you describe, but in a more "general" sense - can you describe what happens > with the 'Read and 'Write as we travel down the chain of inheritance?) I don't see any "inheritance issues." The RM is quite clear as to what happens. Each component of an aggregate is written or read in the order in which it is declared, using either default stream attribute for that component's type, unless that attribute is overridden by an attribute definition clause. If, for example, a component of a record is an array of booleans, each of those booleans will be written or read to or from the stream as an individual octet, because 'read or 'write is called for each element of the array, even if the array is packed. If that behavior is unacceptable, then you can override the default stream attributes for the Boolean array type. I have had to do a lot of that sort of thing when using streams to read and write to and from a network where the network representation is defined with components that do not begin and end on octet boundaries. Here is an example of a 31-bit component adjacent to a one-bit component: type An_Hour_Fraction is delta 3600.0 * 2.0 ** (-31) range 0.0 .. 3600.0; for An_Hour_Fraction'Small use 3600.0 * 2.0 ** (-31); for An_Hour_Fraction'Size use 31; type A_Time_Stamp_Kind is (Relative, Absolute); for A_Time_Stamp_Kind use (Relative => 0, Absolute => 1); for A_Time_Stamp_Kind'Size use 1; type A_Time_Stamp is record Seconds : An_Hour_Fraction; Kind : A_Time_Stamp_Kind; end record; for A_Time_Stamp use record Seconds at 0 range 0 .. 30; Kind at 0 range 31 .. 31; end record; for A_Time_Stamp'Size use 32; procedure Read_Time_Stamp (Stream : access Ada.Streams.Root_Stream_Type'Class; Item : out A_Time_Stamp); procedure Write_Time_Stamp (Stream : access Ada.Streams.Root_Stream_Type'Class; Item : in A_Time_Stamp); for A_Time_Stamp'Read use Read_Time_Stamp; for A_Time_Stamp'Write use Write_Time_Stamp; Here are the bodies of the read and write procedures: procedure Read_Ts is new Byte_Ordering.Read (A_Time_Stamp); procedure Read_Time_Stamp (Stream : access Ada.Streams.Root_Stream_Type'Class; Item : out A_Time_Stamp) renames Read_Ts; procedure Write_Ts is new Byte_Ordering.Write (A_Time_Stamp); procedure Write_Time_Stamp (Stream : access Ada.Streams.Root_Stream_Type'Class; Item : in A_Time_Stamp) renames Write_Ts; Here is the Byte_Ordering generic: with Ada.Streams; package Byte_Ordering is generic type Item_Type is private; procedure Read (Stream : access Ada.Streams.Root_Stream_Type'Class; Item : out Item_type); generic type Item_Type is private; procedure Write (Stream : access Ada.Streams.Root_Stream_Type'Class; Item : Item_type); end Byte_Ordering; with System; package body Byte_Ordering is type U8 is mod 2 ** 8; for U8'Size use 8; type U8_Array is array (Integer range <>) of U8; --======================= -- Private subprograms == --======================= ---------- -- Swap -- ---------- procedure Swap (The_Item : in out U8_Array) is The_Bytes : array (1 .. The_Item'Length) of U8; for The_Bytes'Address use The_Item'Address; Temp : U8; begin for B in 1 .. The_Bytes'Last / 2 loop Temp := The_Bytes (B); The_Bytes (B) := The_Bytes (The_Bytes'Last - B + 1); The_Bytes (The_Bytes'Last - B + 1) := Temp; end loop; end Swap; --====================== -- Public subprograms == --====================== ---------- -- Read -- ---------- procedure Read (Stream : access Ada.Streams.Root_Stream_Type'Class; Item : out Item_type) is The_Bytes : U8_Array (1 .. Item_Type'Size / U8'Size); for The_Bytes'Address use Item'Address; use type System.Bit_Order; begin U8_Array'Read (Stream, The_Bytes); if System.Default_Bit_Order = System.Low_Order_First then Swap (The_Bytes); end if; end Read; ----------- -- Write -- ----------- procedure Write (Stream : access Ada.Streams.Root_Stream_Type'Class; Item : Item_Type) is Item_Copy : Item_type := Item; The_Bytes : U8_Array (1 .. Item_Type'Size / U8'Size); for The_Bytes'Address use Item'Address; use type System.Bit_Order; begin if System.Default_Bit_Order = System.Low_Order_First then Swap (The_Bytes); end if; U8_Array'Write (Stream, The_Bytes); end Write; end Byte_Ordering; If stream representation is important -- e.g., when it is needed to conform to a protocol specification, or when you need to communicate between little- and big- endian architectures, then you need to declare aggregate types that begin and end on octet boundaries, and override their default stream attributes. Yes, I know that some will find fault that I used address clauses to overlay objects instead of using unchecked conversion -- but this was done in the interest of efficiency. ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: Behavior of Stream Attributes On Access Types. 2002-06-12 15:18 ` Marin David Condic 2002-06-13 3:00 ` David C. Hoos, Sr. @ 2002-06-14 18:27 ` Simon Wright 2002-06-14 18:53 ` Marin David Condic 1 sibling, 1 reply; 19+ messages in thread From: Simon Wright @ 2002-06-14 18:27 UTC (permalink / raw) "Marin David Condic" <dont.bother.mcondic.auntie.spam@[acm.org> writes: > package Level_1 is > type L1 is tagged record > A : Integer ; > end record ; > -- > -- Here I have L1'Read, L1'Write, L1'Input, L1'Output > -- and L1'Class'Read L1'Class'Write L1'Class'Input L1'Class'Output > -- > end Level_1 ; > > package Level_1.Level_2 is > type L2 is new Level_1.L1 with record > B : Some_Access_Type := null ; > end record ; > -- > -- Now I have to define my own 'Read and 'Write I think this is where the mistake occurs. At the point where you declared Some_Access_Type, declare procedure My_Read (Stream : access Ada.Streams.Root_Stream_Type'Class; Obj : Some_Access_Type); for Some_Access_Type'Read use My_Read; and also for My_Write, and all magically happens .. ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: Behavior of Stream Attributes On Access Types. 2002-06-14 18:27 ` Simon Wright @ 2002-06-14 18:53 ` Marin David Condic 2002-06-15 14:56 ` Simon Wright 0 siblings, 1 reply; 19+ messages in thread From: Marin David Condic @ 2002-06-14 18:53 UTC (permalink / raw) Nope. Not a "mistake" - except maybe stylistically. I have evolved a very specific question here that seems to be getting misunderstood. I don't want to know how to override the default 'Read and 'Write for an access type. (I know *how* to do that - but not necessarily what the "default" behavior is. From other posts, I suspect just the pointer value is written.) What I want to know is what happens as you go up the food-chain on tagged records once you override the default 'Read and 'Write. I posted this elsewhere: "A" is a tagged type for which I accept the standard issue 'Write. "B" Is a descendend of "A" that adds a new field and for which I create my own 'Write for the type "B" - not for the field. "C" is a descendent of "B" that adds a new field. What happens when I call: "A'Class'Write (C_Object);"? Does the field added in "C" get written out with the standard issue 'Write or does the food-chain stop at the point where I overrode the 'Write? What happens if I call "C'Write (C_Object);" - assuming I didn't create my own user-defined "C'Write"? Hope this clarifies what it is I'm not understanding. Thanks for any help you can give. MDC -- Marin David Condic Senior Software Engineer Pace Micro Technology Americas www.pacemicro.com Enabling the digital revolution e-Mail: marin.condic@pacemicro.com "Simon Wright" <simon@pushface.org> wrote in message news:x7vhek5sokk.fsf@pushface.org... > > I think this is where the mistake occurs. > > At the point where you declared Some_Access_Type, declare > > procedure My_Read > (Stream : access Ada.Streams.Root_Stream_Type'Class; > Obj : Some_Access_Type); > for Some_Access_Type'Read use My_Read; > > and also for My_Write, and all magically happens .. ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: Behavior of Stream Attributes On Access Types. 2002-06-14 18:53 ` Marin David Condic @ 2002-06-15 14:56 ` Simon Wright 2002-06-16 2:27 ` Randy Brukardt 0 siblings, 1 reply; 19+ messages in thread From: Simon Wright @ 2002-06-15 14:56 UTC (permalink / raw) "Marin David Condic" <dont.bother.mcondic.auntie.spam@[acm.org> writes: > Nope. Not a "mistake" - except maybe stylistically. I have evolved a > very specific question here that seems to be getting > misunderstood. I don't want to know how to override the default > 'Read and 'Write for an access type. (I know *how* to do that - but > not necessarily what the "default" behavior is. From other posts, I > suspect just the pointer value is written.) What I want to know is > what happens as you go up the food-chain on tagged records once you > override the default 'Read and 'Write. Oh, sorry; I guess what we're all failing to grasp is why you would want to do that. Since the only contribution I would be able to make would be to try it and see, I'll shut up .. ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: Behavior of Stream Attributes On Access Types. 2002-06-15 14:56 ` Simon Wright @ 2002-06-16 2:27 ` Randy Brukardt 2002-06-17 14:31 ` Marin David Condic 0 siblings, 1 reply; 19+ messages in thread From: Randy Brukardt @ 2002-06-16 2:27 UTC (permalink / raw) Simon Wright wrote in message ... >"Marin David Condic" <dont.bother.mcondic.auntie.spam@[acm.org> writes: > >> Nope. Not a "mistake" - except maybe stylistically. I have evolved a >> very specific question here that seems to be getting >> misunderstood. I don't want to know how to override the default >> 'Read and 'Write for an access type. (I know *how* to do that - but >> not necessarily what the "default" behavior is. From other posts, I >> suspect just the pointer value is written.) What I want to know is >> what happens as you go up the food-chain on tagged records once you >> override the default 'Read and 'Write. > >Oh, sorry; I guess what we're all failing to grasp is why you would >want to do that. > >Since the only contribution I would be able to make would be to try it >and see, I'll shut up .. And I answered that question (in terms of the Corrigendum and the original Ada 95 standard) several days ago (Wednesday to be exact). Here it is again if you all missed it: "The Ada 95 standard doesn't address this. The Technical Corrigendum does, and requires that the default implementation is calls the parent type's 'Read and 'Write. So you are not required to override. But be sure that your compiler is implementing the TC (tests for this area have only recently been added to the ACATS, so it is not unlikely that compilers don't follow the TC in this area)." To expand a bit further, the TC requires that the default implementation calls the parent type's 'Read and 'Write, along with the 'Read and 'Writes for any extension components. So you don't have to do anything special, and you should get what you expect. But, again, be sure that your compiler implements the TC before depending on this! (If it doesn't implement the TC, it could do just about anything; the original Ada 95 standard is very confused when it comes to streams and stream attributes). Randy Brukardt. ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: Behavior of Stream Attributes On Access Types. 2002-06-16 2:27 ` Randy Brukardt @ 2002-06-17 14:31 ` Marin David Condic 2002-06-18 19:30 ` Randy Brukardt 0 siblings, 1 reply; 19+ messages in thread From: Marin David Condic @ 2002-06-17 14:31 UTC (permalink / raw) O.K. *THAT* is the part I was looking for. (I don't think this was in your original answer.) Type A uses the default 'Write. Type B descending from A overrides 'Write to do its own thing. Type C descending from B and adding new fields NEED NOT override 'Write - it will first call type B's 'Write and then will call 'Write for any new fields added. At least that is the behavior that *SHOULD* be there, correct? (If it doesn't call the 'Write for the additional fields, you'd be stuck having to override it.) It is a confusing issue & I'm glad I now have a good answer. As you indicate that it may not be this way in all compilers, I guess one needs to test it out & verify that it works. Too bad - I could see it being a serious portability issue in that one might easily write code as I described above. I suppose that from a stylistic perspective it would be better to override the 'Read and 'Write for the individual fields, but I could easily imagine a situation where the reason for overriding them is to control representation of the overall record. (Suppose I need to make sure that some fields aren't padded within the record - then subsequent extensions to it I might not care because I'm happy with the default behavior.) Thanks for the info. MDC -- Marin David Condic Senior Software Engineer Pace Micro Technology Americas www.pacemicro.com Enabling the digital revolution e-Mail: marin.condic@pacemicro.com "Randy Brukardt" <randy@rrsoftware.com> wrote in message news:ugnu54b8nr87aa@corp.supernews.com... > > To expand a bit further, the TC requires that the default implementation > calls the parent type's 'Read and 'Write, along with the 'Read and > 'Writes for any extension components. So you don't have to do anything > special, and you should get what you expect. But, again, be sure that > your compiler implements the TC before depending on this! (If it doesn't > implement the TC, it could do just about anything; the original Ada 95 > standard is very confused when it comes to streams and stream > attributes). > > Randy Brukardt. > > > > ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: Behavior of Stream Attributes On Access Types. 2002-06-17 14:31 ` Marin David Condic @ 2002-06-18 19:30 ` Randy Brukardt 0 siblings, 0 replies; 19+ messages in thread From: Randy Brukardt @ 2002-06-18 19:30 UTC (permalink / raw) Marin David Condic wrote in message ... >O.K. *THAT* is the part I was looking for. (I don't think this was in your >original answer.) Type A uses the default 'Write. Type B descending from A >overrides 'Write to do its own thing. Type C descending from B and adding >new fields NEED NOT override 'Write - it will first call type B's 'Write and >then will call 'Write for any new fields added. At least that is the >behavior that *SHOULD* be there, correct? (If it doesn't call the 'Write for >the additional fields, you'd be stuck having to override it.) Right, that is what the behavior SHOULD be. But if the compiler doesn't implement the TC and hasn't been tested against the latest ACATS test suite, then it very well may not. The tests for this were added to the ACATS in December, and don't become required until July 1st, so even a recently tested compiler could get this wrong and still pass conformity assessment. Of course, an Ada 0y compiler will have to get this right -- but you may not want to wait that long. :-) Randy. ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: Behavior of Stream Attributes On Access Types. 2002-06-11 14:37 ` Marin David Condic 2002-06-12 14:19 ` David C. Hoos @ 2002-06-12 19:39 ` Randy Brukardt 1 sibling, 0 replies; 19+ messages in thread From: Randy Brukardt @ 2002-06-12 19:39 UTC (permalink / raw) Marin David Condic wrote in message ... ... >Then, just to make it more interesting, I inherit from the >second type and add more (non-access) fields. I *must* override my own 'Read >and 'Write to include the newly added fields? Or will it dispatch to the >'Read and 'Write in the second level, then go on to call the defaults for >the newly added fields? The Ada 95 standard doesn't address this. The Technical Corrigendum does, and requires that the default implementation is calls the parent type's 'Read and 'Write. So you are not required to override. But be sure that your compiler is implementing the TC (tests for this area have only recently been added to the ACATS, so it is not unlikely that compilers don't follow the TC in this area). Randy Brukardt. ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: Behavior of Stream Attributes On Access Types. 2002-06-11 14:27 ` Marin David Condic 2002-06-11 14:37 ` Marin David Condic @ 2002-06-12 13:31 ` Ted Dennison 1 sibling, 0 replies; 19+ messages in thread From: Ted Dennison @ 2002-06-12 13:31 UTC (permalink / raw) "Marin David Condic" <dont.bother.mcondic.auntie.spam@[acm.org> wrote in message news:<ae51cc$9ok$1@nh.pace.co.uk>... > Yeah, I just can't think of many cases where I want to write something into > a stream and not have it persist across executions or partitions or > whatever, wherein the address starts becoming a totally useless piece of > information. In the same execution? Why wouldn't I just keep referencing the > data structure I've already got? I suppose the language needs to do For the language-defined streams, which are files, it would indeed be pretty pointless. However, in the past I've created stream types that lived in RAM and acted as buffers. For those, it could be useful (wasn't in my case, but it could be for someone). -- T.E.D. Home - mailto:dennison@telepath.com (Yahoo: Ted_Dennison) Homepage - (temporarily down) ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: Behavior of Stream Attributes On Access Types. 2002-06-11 13:47 ` Ted Dennison 2002-06-11 14:27 ` Marin David Condic @ 2002-06-11 21:56 ` Randy Brukardt 1 sibling, 0 replies; 19+ messages in thread From: Randy Brukardt @ 2002-06-11 21:56 UTC (permalink / raw) Ted Dennison wrote in message <4519e058.0206110547.526d2369@posting.google.com>... >"Marin David Condic" <dont.bother.mcondic.auntie.spam@[acm.org> wrote in message news:<ae2v7f$r12$1@nh.pace.co.uk>... >> My inclination is to think that the sensible thing would be to call the >> 'Read or 'Write for the thing pointed to by the access type, but this has > >You can pretty much count on it *not* doing that. For instance, what >would happen in that case with a circularly-referenced structure like >a doubly-linked list? > > >> implications for dynamically allocated objects. Will it write/read a >> (totally useless) access value? > >Pretty much. It isn't *totally* useless. It will work just fine within >the same execution (assuming you don't deallocate the memory). >However, it is next to useless. There is one more thing you can do with it: test it for nullness. Although that is not guarenteed to work, it would be an unusual system indeed where it did not. This can be very useful. The Janus/Ada compiler uses this to store and reconstruct linked lists: (Note that Janus/Ada, as an Ada 83 app., doesn't use the stream attributes themselves but a very similar implementation specific package) type Data; type Ptr is access Data; type Data is record ... Next : Ptr; end record; List : Ptr; procedure Write_List (To : Stream_Access) is Walk : Ptr := List; begin Ptr'Write (To, Walk); while Walk /= null loop Data'Write (To, Walk.all); Walk := Walk.Next; end loop; end Write_List; procedure Read_List (From : Stream_Access) is Work : Ptr; begin Ptr'Read (From, Work); if Work /= null then List := new Data; Work := List; else List := null; return; -- Nothing to read. end if; loop Data'Read (From, Work.all); if Work.Next = null then return; else Work.Next := new Data; Work := Work.Next; end; end loop; end Read_List; (There's probably a simpler way to read the list, but you get the idea...) Randy. ^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: Behavior of Stream Attributes On Access Types. 2002-06-10 19:38 Behavior of Stream Attributes On Access Types Marin David Condic 2002-06-11 5:33 ` R. Tim Coslet 2002-06-11 13:47 ` Ted Dennison @ 2002-06-12 3:44 ` David C. Hoos, Sr. 2 siblings, 0 replies; 19+ messages in thread From: David C. Hoos, Sr. @ 2002-06-12 3:44 UTC (permalink / raw) ----- Original Message ----- From: "Marin David Condic ]" <dont.bother.mcondic.auntie.spam@[acm.org> Newsgroups: comp.lang.ada To: <comp.lang.ada@ada.eu.org> Sent: June 10, 2002 2:38 PM Subject: Behavior of Stream Attributes On Access Types. > I'm checking section 13.13.2 of the ARM to discover the default behavior of > the Stream 'Read, 'Write, 'Input and 'Output when they encounter an access > type. I'm not finding any clear indication of what gets put to the stream - > although there is a mention in paragraph 35 of raising Constraint_Error on > input if the value is not of its subtype. Can someone clarify the behavior? > > My inclination is to think that the sensible thing would be to call the > 'Read or 'Write for the thing pointed to by the access type, but this has > implications for dynamically allocated objects. Will it write/read a > (totally useless) access value? > Here is an example of how I do this in a number of ADT packages I have developed. The complete file with appropriate copyright notice, and ratioonale, etc., is available at ftp.ada95.com/pub/access_object_stream_attributes.tgz or ftp.ada95.com/pub/access_object_stream_attributes.tar.gz with Ada.Streams.Stream_IO; with Ada.Text_IO; with Ada.Unchecked_Deallocation; procedure Test_Access_Object_Stream_Attributes is type Node; type Node_Access is access all Node; procedure Node_Access_Read (Stream : access Ada.Streams.Root_Stream_Type'Class; Item : out Node_Access); procedure Node_Access_Write (Stream : access Ada.Streams.Root_Stream_Type'Class; Item : in Node_Access); type Node is record Item : Integer; Next : Node_Access; end record; for Node_Access'Read use Node_Access_Read; for Node_Access'Write use Node_Access_Write; procedure Node_Access_Read (Stream : access Ada.Streams.Root_Stream_Type'Class; Item : out Node_Access) is Is_Non_Null : Boolean; begin Boolean'Read (Stream, Is_Non_Null); if Is_Non_Null then Item := new Node'(Node'Input (Stream)); else Item := null; end if; end Node_Access_Read; procedure Node_Access_Write (Stream : access Ada.Streams.Root_Stream_Type'Class; Item : in Node_Access) is begin Boolean'Write (Stream, Item /= null); if Item /= null then Node'Output (Stream, Item.all); end if; end Node_Access_Write; -- NOTE: Since the Read procedure is an allocator, it is the -- responsibility of the caller to deallocate the memory. -- To this end, a Deallocate procedure is provided. procedure Deallocate (Item : in out Node_Access) is procedure Free is new Ada.Unchecked_Deallocation (Object => Node, Name => Node_Access); begin if Item.Next /= null then -- Not a leaf node; first deallocate node's children, -- then deallocate this node Deallocate (Item.Next); Deallocate (Item); else -- Leaf node; free the storage Free (Item); end if; end Deallocate; Head : Node_Access; Tail : Node_Access; Next : Node_Access; File : Ada.Streams.Stream_IO.File_Type; Stream : Ada.Streams.Stream_IO.Stream_Access; begin -- Link together a few nodes for N in 1 .. 10 loop if N = 1 then Tail := new Node; Head := Tail; else Tail.Next := new Node; Tail := Tail.Next; end if; Tail.Item := N; end loop; -- Verify the list Ada.Text_IO.Put_Line ("Original populated list:"); Next := Head; while next /= null loop Ada.Text_IO.Put_Line (Next.Item'Img); Next := Next.Next; end loop; -- Write the list to a stream file -- Create the file Ada.Streams.Stream_IO.Create (File => File, Mode => Ada.Streams.Stream_IO.Out_File, Name => "nodes.dat"); -- Associate a stream with the file Stream := Ada.Streams.Stream_IO.Stream (File); -- Write the list Node_Access'Output (Stream, Head); -- Close the file Ada.Streams.Stream_IO.Close (File); -- Destroy the list Deallocate (Head); -- Verify the list Ada.Text_IO.Put_Line ("List after deallocation (should be empty):"); Next := Head; while next /= null loop Ada.Text_IO.Put_Line (Next.Item'Img); Next := Next.Next; end loop; -- Read the list from a stream file -- Open the file Ada.Streams.Stream_IO.Open (File => File, Mode => Ada.Streams.Stream_IO.In_File, Name => "nodes.dat"); -- Associate a stream with the file Stream := Ada.Streams.Stream_IO.Stream (File); -- Read the list Head := Node_Access'Input (Stream); -- Close the file Ada.Streams.Stream_IO.Close (File); -- Verify the list Ada.Text_IO.Put_Line ("List after reading file:"); Next := Head; while next /= null loop Ada.Text_IO.Put_Line (Next.Item'Img); Next := Next.Next; end loop; end Test_Access_Object_Stream_Attributes; ^ permalink raw reply [flat|nested] 19+ messages in thread
end of thread, other threads:[~2002-06-18 19:30 UTC | newest] Thread overview: 19+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2002-06-10 19:38 Behavior of Stream Attributes On Access Types Marin David Condic 2002-06-11 5:33 ` R. Tim Coslet 2002-06-11 14:15 ` Marin David Condic 2002-06-11 13:47 ` Ted Dennison 2002-06-11 14:27 ` Marin David Condic 2002-06-11 14:37 ` Marin David Condic 2002-06-12 14:19 ` David C. Hoos 2002-06-12 15:18 ` Marin David Condic 2002-06-13 3:00 ` David C. Hoos, Sr. 2002-06-14 18:27 ` Simon Wright 2002-06-14 18:53 ` Marin David Condic 2002-06-15 14:56 ` Simon Wright 2002-06-16 2:27 ` Randy Brukardt 2002-06-17 14:31 ` Marin David Condic 2002-06-18 19:30 ` Randy Brukardt 2002-06-12 19:39 ` Randy Brukardt 2002-06-12 13:31 ` Ted Dennison 2002-06-11 21:56 ` Randy Brukardt 2002-06-12 3:44 ` David C. Hoos, Sr.
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox