(I am copying this to the list, as there might be interest).
Steven Deller wrote:
>
> Mats,
> Could you elaborate on where you think 'object_size is required? And could
> you also elaborate on what you think the spec is for 'object_size (I'd like
> to consider asking for this to be added to Apex, if there is truly a need).
Your phrasing seems to imply that 'Object_Size is not really necessary,
but the GNAT people would not have invented it if this were true :-)
Anyway, here is a piece of code where I need it. This generic is used to
send any type over a socket (on the same machine, so I don't need to
care about endianity issues, and I need it to be as fast as possible).
It must work with indefinite types (e.g. String, and records with
discriminants that have defaults).
I suppose I could replace T'Object_Size with some formula involving
T'Size and T'Alignment, but T'Object_Size is really easier.
I know, I am supposed to use the streams stuff for this kind of thing,
but this is old code that works and I am not going to rewrite it.
Besides, I cannot afford the overhead that I assume this would add (I
haven't done any tests, though).
generic
type Message_Type (<>) is private;
package Communications is
----------------------
-- Higher level communications.
-- If Message_Type has discriminants, then they
-- must have a default initial value.
procedure Send (To : in Subprocess_Link;
Message : in Message_Type);
-- Sends Message to To.
-- Raises Link_Not_Open if To is not open.
procedure Receive (From : in Subprocess_Link;
Message : out Message_Type);
-- Receives the next message from From.
-- If Message_Type has discriminants, then
-- the actual parameter for Message MUST NOT
-- BE CONSTRAINED.
-- Raises Link_Not_Open if From is not open.
end Communications;
package body Communications is
---------------------------
procedure Send (To : in Subprocess_Link;
Message : in Message_Type) is
begin
Low_Level_Communications.Send
(To => To,
Buffer => Message'Address,
Length => Message'Size / System.Storage_Unit);
end Send;
procedure Receive (From : in Subprocess_Link;
Message : out Message_Type) is
Length_Received : Natural;
Max_Length : Natural;
begin
-- berk
begin
if Message_Type'Base'Object_Size = 0 then
Max_Length := 0;
else
Max_Length := (Message_Type'Base'Object_Size - 1) /
System.Storage_Unit + 1;
end if;
exception
when Constraint_Error =>
-- due to evaluation of Message_Type'Base'Object_Size,
-- which can be an unconstrained type such as String
Max_Length := (Message'Size - 1) / System.Storage_Unit + 1;
end;
Low_Level_Communications.Receive
(From => From,
Buffer => Message'Address,
Max_Length => Max_Length,
Length_Received => Length_Received);
end Receive;
end Communications;
For completeness, here is the GNAT documentation on 'Object_Size:
> Object_Size
> The size of an object is not necessarily the same as the size
> of the type of an object. This is because by default object
> sizes are increased to be a multiple of the alignment of the
> object. For example, Natural'Size is 31, but by default
> objects of type Natural will have a size of 32 bits.
> Similarly, a record containing an integer and a character:
>
> type Rec is record
> I : Integer;
> C : Character;
> end record;
>
> will have a size of 40 (that is Rec'Size will be 40. The
> alignment will be 4, because of the integer field, and so the
> default size of record objects for this type will be 64 (8
> bytes). The type'Object_Size attribute has been added to GNAT
> to allow the default object size of a type to be easily
> determined. For example, Natural'Object_Size is 32, and
> Rec'Object_Size (for the record type in the above example)
> will be 64. Note also that, unlike the situation with the
> Size attribute as defined in the Ada RM, the Object_Size
> attribute can be specified individually for different
> subtypes. For example:
>
> type R is new Integer;
> subtype R1 is R range 1 .. 10;
> subtype R2 is R range 1 .. 10;
> for R2'Object_Size use 8;
>
> In this example, R'Object_Size and R1'Object_Size are both 32
> since the default object size for a subtype is the same as
> the object size for the the parent subtype. This means that
> objects of type R or R1 will by default be 32 bits (four
> bytes). But objects of type R2 will be only 8 bits (one
> byte), since R2'Object_Size has been set to 8.
|