comp.lang.ada
 help / color / mirror / Atom feed
From: taashlo@sandia.gov (Tad Ashlock)
Subject: Re: How to Emulate C++ Macro with Static Local Variable?
Date: 25 Sep 2003 05:59:24 -0700
Date: 2003-09-25T12:59:25+00:00	[thread overview]
Message-ID: <5917f4d0.0309250459.59940bc9@posting.google.com> (raw)
In-Reply-To: 3F722C53.9020808@attbi.com

"Robert I. Eachus" <rieachus@attbi.com> wrote in message news:<3F722C53.9020808@attbi.com>...
> taashlo@sandia.gov wrote:
> > Hello,
> > 
> > I'm trying to port a small C++ library to Ada95.  Most of it is going
> > quite well in that the Ada implementation is smaller, simpler, and
> > easier to follow than the C++ implementation.  But I've ran into a
> > hurdle with the following C++ construction:
> > 
> > class Test {
> > ...
> > protected:
> >    struct s {
> >       int data[8];
> >    };
> > ...
> >    void bar(s *t, int foo);
> >    #define BAR(foo_) if (1) { \
> >       static s t_; \
> >       bar(&t_, foo_);\
> >    } else ((void)0)
>  ...
> > };
> > 
> > What happens is that when you do this:
> > 
> > BAR(10);
> > 
> > it expands to this:
> > 
> > if (1) {
> >   static s t_;
> >   bar(&t_, 10);
> > } else ((void)0);
> > 
> > This, in effect, creates a (hidden) static local variable for each call
> > to bar().  This static variable (actually a structure, t_) is used to
> > cache information for each unique call to bar() such that subsequent
> > calls from that location can be processed *much* faster.
> > 
> > For instance, the following code would create three of the hidden local
> > variables:
> > 
> > for (int i = 0; i < 55; ++i) {
> >    switch (wozit()) {
> >       case 1: BAR(10); break;
> >       case 2: BAR(20); break;
> >       case 3: BAR(30); break;
> >    }
> > }
> > 
> > The first time each BAR() is encountered, it does the full processing,
> > but subsequent calls to the *same* BAR() used it's unique cached
> > information and go much faster.
> > 
> > Any ideas on how I can achieve this with Ada95?
> 
> Wild, I'm going to give you "ideas," and let you implement one of them.
> 
> First, the normal way to implement this in Ada would be to break the 
> action into a generic instantiation followed by a call of the 
> instantiated generic.  But if you want to follow that pattern here it 
> gets tricky to wrap it in a generic.  You would need a subprogram access 
> type declared at an outer level, the generic instantiation would create 
> a procedure and pass back the access value for subsequent calls.

I've been trying ideas along these lines for a few days, but I haven't
been able to make them work.  I understand how the procedure would get
created, but I don't understand where the data is uniquely cached for
each procedure call. (The C++ implementation above does it in t_->data.)

> The fast way to implement this of course is to use self-modifying code. 
>   Ugh!  You can manage this with subprogram parameters.  The first call 
> goes to the 'generic' version which returns among other things the new 
> address to call.  Sort of:
> 
> procedure Subp is
> 
>    type Subprogram_Record;
> 
>    type Subprogram_Pointer is
>         access procedure(X: in Integer; P: in out Subprogram_Record);
> 
>    type Subprogram_Record is record
>      SP: Subprogram_Pointer;
>    end record;
> 
>    procedure Test (X: in Integer; P: in out Subprogram_Record)
>    is begin null; end;
> 
>    Bar_Pointer: constant Subprogram_Record := (SP => Test'Access);
> 
>    Local_Pointer: Subprogram_Record := Bar_Pointer;
> begin
>    Local_Pointer.SP.all(3, Local_Pointer);
> end Subp;

I'm not following this one at all.  Where is the cached data?

> This code is a bit ugly, but it does compile.  And since Bar_Pointer is 
> a constant, you can't accidently pass it to Test.  There might be a 
> cleaner cleverer way to do it, but this works.
> 
> The cleanest option may be to run your code through a preprocessor and 
> use a similar macro.

Yeah, I've thought of that one too.  And due to performance requirements,
it might end up being my only option.  But even that isn't as straight
forward as in C++ due to the fact that the data cache needs to be
declared in the *package's* declarative region with a unique name.
(Where the C++ implementation could declare the data cache statically in
a block immediately before the function call.)

Thank you so much, Robert, for taking the time to reply to my question.

Tad



  parent reply	other threads:[~2003-09-25 12:59 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
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 [this message]
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