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!postnews.google.com!c13g2000cwb.googlegroups.com!not-for-mail From: "per" Newsgroups: comp.lang.ada Subject: Re: OO problem: Performing actions on messages (very long, sorry) Date: 5 Jan 2005 04:01:18 -0800 Organization: http://groups.google.com Message-ID: <1104926478.797780.7830@c13g2000cwb.googlegroups.com> 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> <1ogeykubpns90.2jnblmdu1wg2.dlg@40tude.net> <1104852099.054703.265080@f14g2000cwb.googlegroups.com> NNTP-Posting-Host: 138.14.239.132 Mime-Version: 1.0 Content-Type: text/plain; charset="iso-8859-1" X-Trace: posting.google.com 1104926484 15921 127.0.0.1 (5 Jan 2005 12:01:24 GMT) X-Complaints-To: groups-abuse@google.com NNTP-Posting-Date: Wed, 5 Jan 2005 12:01:24 +0000 (UTC) User-Agent: G2/0.2 Complaints-To: groups-abuse@google.com Injection-Info: c13g2000cwb.googlegroups.com; posting-host=138.14.239.132; posting-account=e84-wQ0AAADeDLnjH5yWqnRMVsJLfQJg Xref: g2news1.google.com comp.lang.ada:7470 Date: 2005-01-05T04:01:18-08:00 List-Id: Dmitry, guess what, your solution helped me make my *first* solution (with access to Put-procedures) work! The key point was the contract on generic Message_Type and the type conversion in Execute: generic type Message_Type is new Message with private; ... procedure Execute(Self : in out Instance; M : in Message.Class_Reference) is begin This.OverrideMethodRef(Message_Type(M.all), Self.Argument); end; It may not be the most elegant Ada-ish solution, but my initial idea works and that's encouraging at least. Dmitry: ... >>> Put (Message_Type'Class (Message), This.Argument); > >Remember the rule? The above of course should be > >Put (Message_Type (Message), This.Argument); > >sorry again! > >The reason is that Put is not dispatching, because we pass it explicitly as >a generic parameter. It is logical that then it cannot dispatch on >Message_Type'Class. The compiler should complain. Ada is a safe language! It did :) ... >> I see! So you're saying that I need one instantiation for each >> *Put-procedure* and message (instead of one for each *type* and >> message)? Hm, that's a lot of instances in my system... >Right, generics are said to be statically polymorphic, to underline that >there is a better, true polymorphism. (:-)) OK, I agree true polymorphism is preferable. Do you dare to say that ALL generics *could* be implemented with true polymorphism? If so, do you dare to say that ALL generics *should* be implemented with true polymorphism? (Just curious.) >I would try to get rid of generics. The main problem why generics appear in >your case is that you have parallel type hierarchies. No language, I know >of, can gracefully handle that. Remove parallelism and things will become >much simpler. For example, > >1. If the number of different argument types is limited, you could make all >possible variants of Put primitive operations of Message: > >type Message is abstract tagged ... >procedure Put (M : in out Message; Value : Ihteger); >procedure Put (M : in out Message; Value : Float); But... What if the descendant to Message has many fields of the same type (as definitely is the case for me): type Message.M1 is new Message with record A : Integer; B : Integer; end; What field would be assigned by procedure Put (M : in out Message.M1; Value : Integer); ? ... >2. Another axis is that action have to contain message of potentially >unknown type. You already handled that by declaring a common ancestor for >all messages. So you could aggregate Message'Class into Action instead of >doing so for a specific Message. The latter requires generics, the former >does not. Though you cannot do it directly: (*) > >type Override (Argument : access Message'Class) is new Action with record > Argument : Message'Class; -- This is not Ada!! >end record; > >But you can use mix-in: > >type Override (Argument : access Message'Class) is new Action ...; > >Here each instance of Override has a "pointer" (access discriminant) to its >message. This approach might become difficult when the scope of action is >not nested in one of the message. Also it would require Action to be a >limited type. So, alternatively you can make reference counting for >messages and have handles (smart pointers) to them in actions. There are >ready-to use implementations of smart pointers in Ada. With this approach >you can pass a handle to message instead of the message object. For example >Override would just assign one handle to another without any copying. In >some cases it might become much more efficient than parameter marshaling, >which is what I suppose you are trying to do. The price to pay is that you >will need to handle aliasing, concurrent changes of a message etc. OK, some of this is a bit beyond my Ada knowledge I'm afraid (remember I'm still an Ada newbie ;), but I kind of get your point. Lots of new stuff for me so next questions may be stupid: Would this approach cope with that the actions are not connected to a certain message *instance* until the point the action should execute? The action at most only "knows" what *type* (or should I say class) of message it should execute upon, and the message instance existsonly close (in time) to the moment the action executes and not under the actions entire life-time. When you say "For example Override would just assign one handle to another without any copying" it seems that you mean a handle to an entire message? If so, that's not what an override action is supposed to. Only a single field *inside* the message should be overridden. Or have I misunderstood you completely? I would like to avoid lots of copying since the system is a real-time simulator so using handles is tempting. In practice I think most parameters will be "small" though (Integer, Float, bitfields etc) so it's not a big deal. >---- >* If action is not a descendant of message. This is why I tried to bring >you to this decision, but you were adamant. (:-)) Hm, they keep saying that... ;) Also have in mind that I may fail in digesting everything you say... I'm both an Ada beginner and increasingly stressed... I've spent too much time on this problem by now. But you've been of GREAT help!