comp.lang.ada
 help / color / mirror / Atom feed
From: "Dmitry A. Kazakov" <mailbox@dmitry-kazakov.de>
Subject: Re: OO problem: Performing actions on messages (very long, sorry)
Date: Wed, 22 Dec 2004 20:54:17 +0100
Date: 2004-12-22T20:54:17+01:00	[thread overview]
Message-ID: <1qdvdjid4u58v.1xz6j5ec6nfcy$.dlg@40tude.net> (raw)
In-Reply-To: 1103737351.196460.85450@f14g2000cwb.googlegroups.com

On 22 Dec 2004 09:42:31 -0800, per wrote:

>>> Each action child shall be able to "do something" with a message in the
>>> virtual (is that the Ada term?) procedure Execute.
>>
>>No. It is called "primitive operation".
> 
> OK. But is there no distinction between operations that may dispatch
> and those those who cannot?

For tagged types it will dispatch on a class-wide argument.

> Execute, for example, may be a primitive
> operation of each child regardless of if the parent has declared it or
> not.

No if parent has it, then child overrides it. So a primitive operation of a
tagged type is polymorphic, i.e. defined on the whole class of types
derived from the parent type that has declared it. Override is a part of
the implementation of that operation selected when the actual parameter is
of the derived type.

> So "primitive operation" doesn't tell that dispatching will be
> possible or not, right?

For tagged types it will.

> Maybe "dispatching" is the distinction?

Dispatch = selection of an implementation.

>>> The action Action.Override serves as an example in this post. This
>>> action shall override a field in a message.
>>
>>One cannot override a field. Presently Ada's inheritance model is a type
>>extension one. I.e. you can add a field, but not replace it with another.
> 
> No! I was unclear. I'm not trying to override anything in that sense.
> 
> The messages are basically records filled with values. It's the
> _values_ in the existing message structures the Action.Override is
> supposed to override:
> 
> type Instance is new Message.Instance with
> record
> A : Float;
> B : Integer;
> ...
> end record;
> ...
> 
> Somewhere some mechanism assigns the initial values:
> M1 : Message.M1.Instance;
> Put_A(M1, 1.0);
> Put_B(M1, 1);
> ...
> 
> Later on, an override action shall be able to override these values by
> basically doing:
> 
> Put_A(M1, Some_Other_Value_Stored_In_The_Action);
> 
> again!

And why: M1.A := 10; is bad?

> Other messages may record the entire message and send it to some place
> else, or just extract some specific data field and pass along etc.
> 
>>> All actions are created and then enqueued in certain action queues in a
>>> preparation phase and then executed (real-time) in the execution phase.
>>> The messages are both created and transported through the system in the
>>> execution phase.
>>
>>> In order to store the value to override with, and where to put it when
>>> performing the override, the Action.Override stores an override
>>> argument (like a Float for instance) and an access to the proper
>>> Put-procedure (like Put_A(M : in out Message.M1.Instance; A : Float))
>>> for a certain message class instance (the specific message the action
>>> shall operate upon). The Put procedure takes as arguments the message
>>> instance and a value to put. The procedure name defines what message
>>> field to put the value into, such as Put_A for field A.
>>
>>It is too late. Basically Put should be a primitive operation of
>>Message...Instance. But when you pass a type as a formal generic parameter
>>it is already frozen, which in other words means that you cannot define a
>>primitive Put for it. You can do instead:
>>
>>generic
>>  type ArgumentType is private; -- Type extension
>>package Message.Extender is
>>  type Instance is new Message.Instance with record
>>     Extension : ArgumentType;
>>  end record;
>>  procedure Put (M : Instance; A : ArgumentType);
>>     -- This is a "method" of Instance now
>>
>>procedure Put (M : Instance; A : ArgumentType) is
>>begin
>>  M.Extension := A;
>>end Put;
> 
> You're saying I should replace every single field in every message
> record with an extension as above?
> 
> I sort of get what you mean, but not entirely. I can't see how my
> "complex" message records would look like. Each message consists of
> many variables and sub-records. I don't think this is what I look for.

ArgumentType can be a large record, array. That's no problem.

> It feels like you're answering another question here... maybe due to
> the above misunderstanding?

Yes. I didn't understand why do you need a generic package
Message.Override.

>>> The type of the field to override and the type of the message are
>>> generic parameters in the Action.Override package/class, so there's one
>>> instantiation of Action.Override for each message type and override type:
>>
>>> package M1_Float_Override_Action is new Action.Override
>>> (ArgumentType => Float,
>>> MessageType  => Message.M1.Instance);
>>
>>> There's another abstract parent-class, Message, and non-abstract child
>>> classes Message.M1, Message.M2 etc.
>>
>>It is not clear what are you going to achieve by that. It will not be
>>dynamically polymorphic anyway as long as ArgumentTypes are not derived
>>from the same base. So any possible gain = 0, IMO.
> 
> Correct. No polymorphy (at least not with this action-stuff). But all
> messages has common data and behaviours that I handle in the abstract
> base-class. So there's the gain.

Messages yes, but not the ArgumentTypes. I still do not follow you.

>>> Each child message has its own set of, non-virtual, Put procedures that
>>> writes the contents of the message. The message contents is a record
>>> with arbitrary width, depth and types.
>>
>>If Put is not dispatching, what the use of it. In particular, why ":=" does
>>not fit?
> 
> I want to assign values to fields in the messages from the override
> actions. How could this be done with ":=" only? I will not implement an
> action for EACH field in EACH message.

But there is no difference! ":=" is as good as "Put", two characters
shorter. For the language there is no difference.

> I would love to make Put dispatching but how would a procedure look
> like that can assign a value to any field in a record?

Variant 1. Derive all values from one base

   type Message_Value is abstract tagged ... or Controlled

Variant 2. Use streams. Your record will be a stream (derived from
Ada.Streams.Root_Stream_Type). For each type there are attributes 'Input
and 'Output. See ARM 13.13.

> (Yes, I'm still stuck with that record...)
> 
>>> There will also be a nice general mechanism that basically gets any
>>> type of message, applies any actions enqueued for it and then puts the
>>> message away. It feels like this should be possible with Ada mechanisms
>>> such as inheritage, polymorphy and generics but, I kind of doubt it
>>> now...
>>
>>It is definitely possible:
>>
>>package Messages is
>>  type Message is
>>     abstract new Ada.Finalization.Limited_Controlled with private;
>>  procedure Execute (This : in out Message) is abstract;
>>
>>  type Messages_Queue is
>>     [abstract] new Ada.Finalization.Limited_Controlled with private;
>>  -- Abstract if there should be different implementations of queues
>>  procedure Enqueue
>>     (  Queue : in out Messages_Queue;
>>        Item : in out Message'Class
>>     )  [is abstract];
>>private
>>  ...
>>end Messages;
>>
>>package Messages.My_Messages is
>>  type My_Message is new Message with private;
>>  procedure Finalize (This : in out Message); -- How to destruct
>>  procedure Initialize (This : in out Message); -- How to construct
>>  procedure Execute (This : in out Message); -- What to be done
>>  procedure Put_A (This : in out Message; A : Something);
>>  ...
> 
> Ugh, I don't get it.
> 
> How could the message know what to do in Execute? There may be 0 or 5
> or 500 actions to be taken on each message.

Ok, then replace "Message" with "Action" and make Message an Action
container.

> The messages do not exist
> when the actions are defined and hence can not be prepared with that
> information. Where/how do you store the values to override with for
> example...?

In the message (OK in the action (:-))

type My_Action is new Action with record
   ...- My precious values
end record;

[ Or should it be sort of C's union? Then you should clearly distinguish
the issue of memory allocation and reuse from the type hierarchy. In Ada
for the latter there are variant records and tagged types. For the former
you can use streams and memory pools. ]

> Maybe this too is an effect of the initial misunderstanding?
> 
> But I was enlighted by some other stuff in your example though :)
> 
>>> Code
>>[...]
>>
>>> 1. Why does this not work?
>>
>>The expected type is MessageType as the compiler tells. MessageType is a
>>generic formal type. The compiler does not know of any its possible
>>relationships with Message.Instance. It is just a type:
>>
>>generic
>>  type MessageType is private;
>>
>>It is not even tagged.
> 
> I see.
> 
> But the dispatching call "Message.Print(M.all)" works and that
> procedure expects as a parameter a concrete instance within
> Message.Instance'Class. It too gets this unknown MessageType yet the
> compiler doesn't whine.
> 
> What's the difference?

The difference in the expected type. Print expects a message,
OverrideMethodRefType expects MessageType. Those are different types. The
compiler does not know about your intention to substitute message for
MessageType. Because, next day, you might change your mind and substitute
Boolean instead.

-- 
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de



  parent reply	other threads:[~2004-12-22 19:54 UTC|newest]

Thread overview: 31+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2004-12-22 13:49 OO problem: Performing actions on messages (very long, sorry) per
2004-12-22 15:17 ` Dmitry A. Kazakov
2004-12-22 16:28 ` Martin Krischik
2004-12-22 17:42   ` per
2004-12-22 18:16     ` Martin Krischik
2004-12-22 19:54     ` Dmitry A. Kazakov [this message]
2005-01-03 12:37       ` per
2005-01-03 14:14         ` Dmitry A. Kazakov
2005-01-04 12:05           ` per
2005-01-04 13:30             ` Dmitry A. Kazakov
2005-01-04 15:21               ` per
2005-01-04 17:47                 ` Dmitry A. Kazakov
2005-01-05 12:01                   ` per
2005-01-05 13:23                     ` Dmitry A. Kazakov
2005-01-05 15:59                       ` per
2005-01-05 20:44                         ` Dmitry A. Kazakov
2005-01-10  8:42                           ` per
2005-01-10 14:22                             ` Dmitry A. Kazakov
2005-01-10 16:24                               ` per
2005-01-10 19:09                                 ` Dmitry A. Kazakov
2005-01-11  9:06                                   ` per
2004-12-22 17:46   ` per
2004-12-22 18:02     ` Martin Krischik
2005-01-03 10:05       ` per
2004-12-22 18:35     ` u_int32_t
2004-12-22 18:38       ` u_int32_t
2004-12-24 18:52 ` Nick Roberts
2005-01-03 16:59   ` per
2005-01-10 12:10   ` per
2005-01-10 13:49     ` Marius Amado Alves
2005-01-10 21:54 ` Simon Wright
replies disabled

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox