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,196864e6c216ca4f X-Google-Attributes: gid103376,public X-Google-ArrivalTime: 2003-09-29 08:02:15 PST Path: news1.google.com!newsfeed.stanford.edu!newsfeed.berkeley.edu!news-hog.berkeley.edu!ucberkeley!enews.sgi.com!news-out.superfeed.net!propagator2-maxim!feed-maxim.newsfeeds.com!feeder.nmix.net!feeder.swcp.com!news.sandia.gov!not-for-mail From: taashlo@sandia.gov Newsgroups: comp.lang.ada Subject: Re: How to Emulate C++ Macro with Static Local Variable? Date: 29 Sep 2003 08:57:51 -0600 Organization: Sandia National Laboratories, Albuquerque, NM USA Sender: taashlo@SADL10553 Message-ID: References: <3F73107A.1060502@attbi.com> <04Hcb.577973$Ho3.106182@sccrnsc03> NNTP-Posting-Host: sadl10553.sandia.gov Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii X-Trace: sass2141.sandia.gov 1064847466 5054 134.253.225.126 (29 Sep 2003 14:57:46 GMT) X-Complaints-To: usenet@sass2141.sandia.gov NNTP-Posting-Date: Mon, 29 Sep 2003 14:57:46 +0000 (UTC) User-Agent: Gnus/5.09 (Gnus v5.9.0) Emacs/21.3 Xref: news1.google.com comp.lang.ada:165 Date: 2003-09-29T08:57:51-06:00 List-Id: tmoran@acm.org writes: > I remain confused. I thought the OP wanted something that used storage > that invisibly depended on the static *location* of a call, and that's > why he used separate "static" variables. Your interpretation is precisely correct. > > > cache information for each unique call to bar() such that subsequent > > > calls from that location can be processed *much* faster. > ^^^^^^^^^^^^^^^^^^ > I gather that's not the correct interpretation. If he is willing to > manually specify the particular cache by > BAR(10); -- cache number 10 > or > package P10 is new P(10); -- cache number 10 > package P20 is new P(20); -- cache number 20 > package P30 is new P(30); -- cache number 30 > or > Local_Pointer.SP.all(3, Local_Pointer); -- cache number 3 > > then why not just: > > type s is record ... > t : array(1 .. 100) of s; -- array of caches > ... > for i in 0 .. 54 loop > case wozit is > when 1 => bar(cache_to_use=>t( 3)); > when 2 => bar(cache_to_use=>t(20)); > when 3 => bar(cache_to_use=>t(14)); > end case; > end loop; > > To somewhat change the example, suppose we want to keep track of how > often different sections of code are run. The usual method is to > do something like > type sections is (initialization, processing_input, ... > and sprinkle around statements like > log(initialization); > ... > log(process input); > Suppose that for some reason we don't just want to set a boolean, or > a counter for each section, but we want to raise an exception if any > section is run more than 100 times (maybe we're worried its RAM area > will die of overuse or something ;) Then in C we could > > void log(int *t){if(*t++ > 100)raise_the_exception;} > #define LOG if (1) { \ > static int t_; \ > log(&t_);\ > } else ((void)0) > > and then we could sprinkle the statement > LOG; > around in the program. How could one implement a similar thing in Ada, > where the "log" call does not need a parameter, but implicitly has one > by virtue of its static location in the code? Thank you so much for this tremendously clearer wording and example of my question. You have precisely caught the essence of what I'm trying to accomplish. Hopefully your wording and my discussion (below) of the weaknesses of the solutions provided so far will help others see a solution to the problem that's as good as, or better, than the C++ solution. (If the following discussion sounds ungrateful, I apologize. It isn't intended to be so. On the contrary, I'm quite thankful for, and somewhat impressed by, the amount of attention my little problem has received.) Hyman Rosen had the following to say: "If you want to have a memoizing function, the job of caching old values belongs to the function itself, not scattered in macros and variables all over the place." Which, in general, I agree with. But in this specific case, what do you use to index the caches? Remember that there has to be a separate cache for each unique call site. (E.g. if there are three calls made to this function *in your source code*, then there will need to be three separate caches.) There's only two options that I can think of: 1) Use a unique ID for each call. But this turns into a maintenance nightmare when you get a few hundred calls or more. 2) Use the return address of the call. But there was a short discussion about how Ada doesn't currently have a way of accessing the return address of a subprogram. Robert I. Eachus, Stephen Leake, and Gautier all replied with solutions that required creating a unique identifier for each call. But this, like solution #1 above, doesn't scale well. The C++ solution, which uses an anonymous static variable structure automatically associated with each call, does scale well. You could call the function 1000 times without having to worry about creating a unique ID or allocating a unique cache structure. Although I originally thought that the C++ implementation was a bit of a hack, I'm beginning to think that this is a somewhat elegant solution to a problem that can't be elegantly solved in Ada. By elegant, in this case, I mean simple, extensible, and maintainable. I would sure like to be proved wrong, though. Thanks again, Tad