From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on polar.synack.me X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00 autolearn=ham autolearn_force=no version=3.4.4 X-Google-Thread: 103376,a8d137db7a5f6c81 X-Google-Attributes: gid103376,public X-Google-Language: ENGLISH,ASCII-7-bit Path: g2news1.google.com!news2.google.com!fu-berlin.de!uni-berlin.de!individual.net!not-for-mail From: "Dmitry A. Kazakov" Newsgroups: comp.lang.ada Subject: Re: OO problem: Performing actions on messages (very long, sorry) Date: Tue, 4 Jan 2005 14:30:23 +0100 Organization: cbb software GmbH Message-ID: <1ogeykubpns90.2jnblmdu1wg2.dlg@40tude.net> References: <1103723394.299024.314670@c13g2000cwb.googlegroups.com> <13465377.hrn0RlrJV7@linux1.krischik.com> <1103737351.196460.85450@f14g2000cwb.googlegroups.com> <1qdvdjid4u58v.1xz6j5ec6nfcy$.dlg@40tude.net> <1104755823.837077.74630@z14g2000cwz.googlegroups.com> <8oknh024yb43$.71qlyp6g8y2x$.dlg@40tude.net> <1104840326.160879.132400@c13g2000cwb.googlegroups.com> Mime-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit X-Trace: individual.net Otx9N6xwJRH/IXKwaXUlzA0q5Il/QvpEMY5MlznLBdwauRB3U= User-Agent: 40tude_Dialog/2.0.12.1 Xref: g2news1.google.com comp.lang.ada:7425 Date: 2005-01-04T14:30:23+01:00 List-Id: 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