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-Language: ENGLISH,ASCII-7-bit X-Google-Thread: 103376,99ab4bb580fc34cd X-Google-Attributes: gid103376,public From: bobduff@world.std.com (Robert A Duff) Subject: Re: Q: access to subprogram Date: 1996/07/26 Message-ID: X-Deja-AN: 170333313 references: <4t7dvt$cbo@mulga.cs.mu.OZ.AU> <4t8rfo$g71@butch.lmsc.lockheed.com> organization: The World Public Access UNIX, Brookline, MA newsgroups: comp.lang.ada Date: 1996-07-26T00:00:00+00:00 List-Id: In article <4t8rfo$g71@butch.lmsc.lockheed.com>, David Kristola wrote: >Maybe i am misunderstanding the meaning of "distributed overhead", but don't >all shared generics have some? But anyway... I think you're misunderstanding "distrib overhead". "Feature X causes distributed overhead" means that your program will have some overhead, caused by the mere existence of feature X in the language, even if you don't use feature X. If feature X is slow, that's just plain old overhead, not "distributed overhead". An example from another thread: tasking causes distributed overhead, because when generating code for a subprogram containing a package-body-subunit, you have to *assume* that the package body will contain a task, and generate some extra task-waiting code in the subunit. So the poor programmer who wants to use subunits, but never used a task in his life is paying some cost for the mere existence of tasking. This is distributed overhead. Of course, this assumes a certain implementation model -- namely that code is generated for the parent subprogram at compile time, when the subunits might not exist yet. It also assumes the user doesn't have a feature saying "I promise not to use tasking." Another example: Text_IO keeps track of line and column numbers, which is an overhead you pay even if you are just sending characters to stdout, and don't care about line and column numbers. (Assuming a straightforward implementation of Text_IO.) Arguments about distributed overhead generally need to have some implementation model in mind (which usually assumes, for example, that fancy optimizations are not done at link time). The case in *this* thread assumes an always-shared generic implementation. Always sharing generics has a *lot* of overhead, but I don't think it has much *distributed* overhead. We're also assuming that you're not allowed to generate code at run time. Distributed overhead is evil. Overhead is not evil, necessarily, because the programmer can choose whether to use the feature (and incur the overhead). Almost any feature causes *some* distributed overhead. The goal is to make it close enough to zero that nobody cares. >generic > ... >package Pkg is > procedure P; >end Pkg; > >with ... >package body Pkg is > function F(...) return ... is > ... > begin > ... > end F; > > procedure P is > ... > begin > ... > Call_Something(F'Access); > ... > end P; >end Pkg; > >Since F might depend on the generic parameters to Pkg, Yes, or perhaps a variable declared in the package body. >... F'Access would need to >point to a wrapper for F, which is not known inside Pkg at compile time (there >may be no instantiations, and therefore no wrappers created). I do not know if >F would have it's own wrapper anyway, because it is not visible in the spec of >Pkg, and therefore not externally callable. Suppose Call_Something were *outside* the generic, and saved F'Access in a global variable. This is illegal, but we're arging about "what if this were legal?" >BUT, why not have a wrapper for F, and, include in the instantiation data, the >addresses of the wrapper routines (F in this case), so that P could reference the >instantiated data passed to it to get the address to resolve F'Access? There is >a bit of indirection here, but then that is an everyday part of shared generics. Because when you compile F, you don't know about the instantiations. And when you compile the instantiations, you don't know about F, because F is declared in the generic *body*. Sure, you could have the compiler take a peek at the generic body, but as Randy pointed out, that defeats the purpose of the always-share model (i.e. to be able to generate code without seeing the body). So this doesn't work. Therefore you have to *always* have this extra generic related info, even if you're not using generics. Hence, distributed overhead. Hence, Ada 9X outlawed the feature. Note that the workaround isn't so bad: declare F in the private part, and then it's legal (and then the compiler knows about it at instantiation time, and can generate the wrapper at that time). - Bob