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: Tue, 4 Jan 2005 14:30:23 +0100
Date: 2005-01-04T14:30:23+01:00	[thread overview]
Message-ID: <1ogeykubpns90.2jnblmdu1wg2.dlg@40tude.net> (raw)
In-Reply-To: 1104840326.160879.132400@c13g2000cwb.googlegroups.com

On 4 Jan 2005 04:05:26 -0800, per wrote:

> Dmitry, I think the misunderstandings has reached a point where I need
> to restart.
> 
> I'll make a last attempt to explain the problem (although time is
> running and I'll probably move on to another approach).
> 
> I want to enable a user to schedule actions to be performed att certain
> system ticks on messages that flows in a system. Each message is
> basically a record.
> 
> One sort of action is the "Override" action. This action shall put one
> user-defined value into a user-selected field inside the message
> record. The type of the value is arbitrary, but is known att
> compile-time. The value itself is only known in run-time and is
> provided by the user in an initialization phase. Many many action may
> be scheduled to execute on many or the same message.
> 
> Later, the system enters the execution phase: For each system tick, all
> Actions that are active in that particular tick, are executed upon the
> all current message instances (only if there exist actions for that
> type of message of course).
> 
> There are also other actions such as Record, Error etc, that do other
> stuff (indicated by their names). I leave these actions out in this
> description.
> 
> Messages are separate from Actions and are declared in separate
> packages (probably in separate directories and perhaps by different
> developers).
> 
> Class hierachy (I hope ASCII graphics will work, but google seems to
> throw away spaces...):
> 
> Message
>|
> ---------------------------
>|        |        |
> M1       M2       ...
> 
> Action
>|
> ------------------------------------
>|        |        |        |
> Override Record   Error    ...
> 
> Or with plain text just in case:
> Message
> Message.M1
> Message.M2
> 
> Action
> Action.Override
> Action.Record
> Action.Error
> 
> 
> Details of the classes:
> 
> Message
> ==============
> Attributes
> --------------
> Id : Integer;
> ...
> 
> Operations
> --------------
> Put_Id(This : Message'Class; New_Id : Integer);
> Get_Id(This : Message'Class) return Integer;
> ...
> 
> Message.M1
> ==============
> Attributes
> --------------
> A : Integer;
> B : Float;
> 
> Operations
> --------------
> Put_A(This : in out M1; New_A : in Integer);
> Put_B(This : in out M1; New_B : in Float);
> 
> 
> Message.M2
> ==============
> Attributes
> --------------
> A : Float;
> B : Float;
> C : Natural;
> 
> Operations
> ----------
> Put_A(This : in out M1; New_A : in Float);
> Put_B(This : in out M1; New_B : in Float);
> Put_C(This : in out M1; New_C : in Natural);
> 
> Here comes my attempt on Action (which doesn't work all the way):
> 
> Action
> ==============
> Attributes
> --------------
> Tick : Integer;
> ...
> 
> Operations
> --------------
> Put_Tick(This : in out Action'Class; New_Tick : in Integer);
> Get_Tick(This : in Tick'Class) return Integer;
> Execute(This : in out Action; Message : in Message'Class);
> ...
> 
> Action.Override (generic)
> ==============
> The class is generic to cope with any type of value to override AND to
> store an access to any Put_-procedure connected to the message to
> override values in.
> 
> generic
> type ArgumentType is private;
> type MessageType is private;
> 
> --The procedure-access type to the Put-procedure that performs the
> actual overriding:
> type OverrideMethodRefType is access procedure(M : in out MessageType;
> A : in ArgumentType);
>
> Attributes
> --------------
> Argument         : ArgumentType          -- The value to override with
> ("any" type)
> OverrideMehodRef : OverrideMethodRefType -- The procedure to call with
> the argument in order to override (the specific Put-procedure)
> 
> Operations
> --------------
> Initialize(This      : in out Action.Override;
> Tick      : Integer;
> Argument  : ArgumentType;
> MethodRef : OverrideMethodRefType)
> begin
> ...
> This.ARgument := Argument;
> This.OverrideMethodRef := MethodRef;
> ...
> end;
> 
> Execute(This : in out Action.Override; Message : in Message'Class);
> begin
> -- The actual overriding:
> This.OverrideMethodRef(Message, This.Argument);
> end;
> 
> The contents of the attributes ARgument and OverrideMethodRef is
> assigned in procedure Initialize during the initialization phase.
> 
> I've left out all stuff about queues and such...

OK, try this:

generic
   type Argument_Type is private;
   type Message_Type is new Message with private;
   with procedure Put (This : in out Message_Type; Value : Argument_Type);
package Action.Generic_Override is
   type Override is new Action with record
      Argument : Argument_Type;
   end record;
   Execute (This : in out Override; Message : in Message'Class);
end Action.Generic_Override;

package body Action.Generic_Override is
   ...
   Execute (This : in out Override; Message : in Message'Class) is
   begin
      if This not in Message_Type'Class then
         Ada.Exceptions.Raise_Exception
         (  Constraint_Error'Identity,
            "Illegal message type in Execute, found " &
            Ada.Tags.External_Tag (Message'Tag) &
            "expected a descendant of:"
            Ada.Tags.External_Tag (Message_Type'Tag) &
         );
      end if;
      Put (Message_Type'Class (Message), This.Argument);
   end Execute;
   ...

You have to instantiate Action.Generic_Override for each combination of
parameter / message. For example:

package Action_on_B_for_M2 is
   new Action.Override
       (  Argument_Type => Float;
          Message_Type => M2;
          Put => Put_B
       );

> FYI:
> In C I would have stored a pointer to a Put-function, looking something
> like "void M1_Put_A(void * M1, void * Argument)", in OverrideMethodRef.
> All Put functions would have had identical signatures such as (void *
> Message, void * Argument). Each specific Put-function would make its
> own interpretation of Message and Argument (after all they are specific
> and knows how to interpret both arguments).

You do not need all that stuff with pointers because the package is already
generic. So you can specify the Put procedure you need, during
instantiation. It won't work with other types of arguments and messages
anyway.

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



  reply	other threads:[~2005-01-04 13:30 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
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 [this message]
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