comp.lang.ada
 help / color / mirror / Atom feed
From: "per" <commander@death-star.com>
Subject: Re: OO problem: Performing actions on messages (very long, sorry)
Date: 22 Dec 2004 09:42:31 -0800
Date: 2004-12-22T09:42:31-08:00	[thread overview]
Message-ID: <1103737351.196460.85450@f14g2000cwb.googlegroups.com> (raw)
In-Reply-To: 13465377.hrn0RlrJV7@linux1.krischik.com

Hi Dimitri, thanx for your answers.

Sorry for the yucky code/text. All indentation and line breaks was
screwed up:( I'm using google groups (for the first time). Not very
user friendly. Had to compose this answer in a separate file and
manually paste in the citations so this answer is also a bit yucky...

>> 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? Execute, for example, may be a primitive
operation of each child regardless of if the parent has declared it or
not. So "primitive operation" doesn't tell that dispatching will be
possible or not, right?

Maybe "dispatching" is the distinction?

>> 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!

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.

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

>> 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.

>> 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.

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?

(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. 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...?

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?

>> 2. Shouldn't a conversion from T11 stored in a T1'Class variable, to
a
>> T11 variable be OK of T11 is a child of T1 (checked during
run-time)?
>
>Yes. If it is not, then Constraint_Error is propagated.

Yay, I've got something right! :)

>> The information needed is of course present in M.all, otherwise
>> dispatching wouldn't be possible. (I have tested dispatching with
the
>> call Message.Print(M.all) commented out in the example and i works
>> fine.)
>
>The information carrier is called "type tag". Each T'Class object has
type
>tag in it.

OK.

>> Note that making every Put-procedure virtual is not an option since
>> they by nature are unique to each message.
>
>> 3. Are there any problems connected to that I use an access to a
>> procedure?
>
>Basically, that it is not much OO. Primitive operations (virtual
methods)
>are for that.
>
>> 4. Is the generic type MessageType causing the problem? The
MessageType
>> is supposed to be a specific sub-class of Message, hence a member of
>> Message'Class so...
>
>Yes.
>
>> 5. Have I designed completely wrong?
>
>Mmm, it is too complex to my taste. I have an impression that you
dealt too
>much with C++ templates. (:-))

Hehe, actually I've most been programming standard C... :)

But I have (very varying) experience from OO languages such as
TurboPascal (back in the 80's), C++, Ada95 and Java.

>> 6. Do you have any suggestions on how to solve this problem in a
good
>> way?
>
>Message = Action to me. Even if there are some constraints like that
>several actions to be executed in a defined order, I would stick to
this
>model using containers of actions.

Would you still after my clarification?

Cause I'm not really with you there just yet. You're most welcome to
explain what you mean further.

Thanks for your effort! I'm taking a Christmas break for a couple of
days now...

Regards

Per




  reply	other threads:[~2004-12-22 17:42 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 [this message]
2004-12-22 18:16     ` Martin Krischik
2004-12-22 19:54     ` Dmitry A. Kazakov
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