comp.lang.ada
 help / color / mirror / Atom feed
From: taashlo@sandia.gov
Subject: Re: How to Emulate C++ Macro with Static Local Variable?
Date: 29 Sep 2003 08:57:51 -0600
Date: 2003-09-29T08:57:51-06:00	[thread overview]
Message-ID: <uhe2vvdzk.fsf@sandia.gov> (raw)
In-Reply-To: 04Hcb.577973$Ho3.106182@sccrnsc03

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



  reply	other threads:[~2003-09-29 14:57 UTC|newest]

Thread overview: 28+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2003-09-24 22:06 How to Emulate C++ Macro with Static Local Variable? taashlo
2003-09-24 23:44 ` Robert I. Eachus
2003-09-25  3:27   ` Hyman Rosen
2003-09-25  4:53     ` tmoran
2003-09-25 15:57       ` Robert I. Eachus
2003-09-25 19:09         ` tmoran
2003-09-29 14:57           ` taashlo [this message]
2003-09-29 18:12             ` Jeffrey Carter
2003-09-29 18:51               ` taashlo
2003-09-30  1:32                 ` Jeffrey Carter
2003-09-30  1:54                   ` tmoran
2003-09-30 13:02                   ` taashlo
2003-09-30 20:25                     ` Jeffrey Carter
2003-09-30  2:45             ` Robert I. Eachus
2003-09-30  3:24               ` tmoran
2003-09-25 13:43     ` Stephen Leake
2003-09-25 12:59   ` Tad Ashlock
2003-09-25 16:11     ` Robert I. Eachus
2003-09-25 18:13       ` Randy Brukardt
2003-09-25 23:40         ` Robert I. Eachus
2003-09-25 11:54 ` Gautier
2003-09-25 16:14   ` Robert I. Eachus
2003-09-25 18:06   ` Tad Ashlock
2003-09-28  8:42     ` Gautier Write-only
2003-09-28 20:06       ` Jeffrey Carter
2003-09-29  2:13         ` Gautier Write-only
2003-09-25 13:41 ` Stephen Leake
2003-09-25 17:23   ` Tad Ashlock
replies disabled

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox