RE: Help: Can't use string ("Exchange::Account::My") as a HASH ref while "strict refs" in use trying to use instance variables in my handler

2001-02-07 Thread Chris Strom

> > Anyway, what you should do is create a constructor:
> > 
> > sub new {
[snip]

> 
> You mean like this code segment that I included in my original post
> just below the handler code :)
> 
> sub init {
[snip] 

Ah yes, but you called your's "init", which is quite misleading to those of
us who tend not to pay attention.

> Wait a second.  I have a startup.pl, and inside that I have the lines:
> 
> use Exchange::Account::My;
> my $account_interface = Exchange::Account::My->init;
> 
> Won't that do what I need it to do?  When the root process forks off
> children, won't a complete copy of $account_interface go with it, with
> everything all set and ready to go?
> 

I wouldn't think that this would be the case, but I may be mistaken.  Since
you've declared $account_interface with 'my', that variable should only be
available within the scope of the startup.pl script.  Even if you went with 

use vars qw($account_interface);

I still don't think that it would be available in the Exchange::Account::My
namespace.

> Except for calling the contructor with every call of the handler, 
> I think I've done everything right.  Isn't the part of idea behind 
> mod_perl handlers that one _doesn't_ have to call the contructor 
> _every_ time the handler gets called?  Otherwise invites massive 
> overhead.

Is a bless really massive overhead?  I can't say as I've ever had a problem
calling the constructor with every request (at least with simple objects).
 
> Obviously, what I'm doing doesn't work.  But could someone show me 
> how to call the constructor just once in in a childs lifetime?  

startup.pl is not the place to do this - it gets called at server start-up
(or restart), not child initialization.  What you could do is create a
ChildInitHandler for this class, which sets a global variable within your
package:

use vars qw($SELF);

sub configure {
  my ($class) = shift;
Apache->push_handlers( PerlChildInitHandler =>
sub {
# use that weird "init" constructor name
$SELF = $class->init(@_);
  }
);
}

You can then change your handler to not use the $$ prototype, but get an
object reference from $SELF:

sub handler {
  my $q = shift;
  my $self = $SELF;
  # the rest of your code as is...
}

In your startup.pl, you'd have:

use Exchange::Account::My;
Exchange::Account::My->configure();

I haven't tested that.  As I said, I've never had call to create the object
only upon child initialization.  I'll be the first to admit that I'm
relatively new to the mod_perl thing, so there may be an easier or more
elegant way to do this, but that ought to work.  Hope that helps.

Chris



Re: Help: Can't use string ("Exchange::Account::My") as a HASH ref while "strict refs" in use trying to use instance variables in my handler

2001-02-06 Thread Christopher L. Everett

> Anyway, what you should do is create a constructor:
> 
> sub new {
>   my $class = shift;
>   my $self {@_};
>   bless $self, $class;
>   return $self;
> }

You mean like this code segment that I included in my original post
just below the handler code :)

sub init {
  my $invocant = shift;
  my $class = ref ($invocant) || $invocant;
  my $self = {};
  bless ($self, $class);

  $self->{config}= $self->init_config;
  $self->{dispatch}  = $self->init_dispatch_table;
  $self->{templates} = $self->init_templates;
  $self->{_child_started_up} = 0;
  
  return $self;
}

 ... straight out of "Programming Perl" ...

> 
> Then rewrite the above snippet of your code to:
> 
> sub handler ($$) {
>   my ($class, $q) = @_;
>   my $r = Apache::Request->new($q);
>   my $self = $class->new(request=>$r);

Hunh?!?

Wait a second.  I have a startup.pl, and inside that I have the lines:

use Exchange::Account::My;
my $account_interface = Exchange::Account::My->init;

Won't that do what I need it to do?  When the root process forks off
children, won't a complete copy of $account_interface go with it, with
everything all set and ready to go?

>   $self->child_init unless $self->{_child_started_up};
>   # The rest of the code...
> 
> Then you should be good to go (instance variables and all!).  Hope that
> helps,
> 
> Chris

Except for calling the contructor with every call of the handler, 
I think I've done everything right.  Isn't the part of idea behind 
mod_perl handlers that one _doesn't_ have to call the contructor 
_every_ time the handler gets called?  Otherwise invites massive 
overhead.

Obviously, what I'm doing doesn't work.  But could someone show me 
how to call the constructor just once in in a childs lifetime?  
Please?

  --Christopher



RE: Help: Can't use string ("Exchange::Account::My") as a HASH ref while "strict refs" in use trying to use instance variables in my handler

2001-02-06 Thread Chris Strom

> Subject: Help: Can't use string ("Exchange::Account::My") as 
> a HASH ref
> while "strict refs" in use trying to use instance variables in my
> handler
[snip]

> sub handler ($$) {
>   my ($self, $q) = @_;
> 
>   my $r= Apache::Request->new($q);
> 
>   $self->child_init unless $self->{_child_started_up};  # < dies
> here!
[snip]

I think that you really need to have a legitimate constructor, not one that
is called conditionally.  $self is not a blessed reference - just a string
containing the class name.  The call to $self->child_init works, even with
strict refs, because there is a child_init subroutine defined in your
package's namespace.  With $self->{_child_started_up}, you're just calling
"Exchange::Account::My"->{_child_started_up}, which will cause the error
since the string "Exchange::Account::My" is not a reference to a hash, it's
just a string.

Anyway, what you should do is create a constructor:

sub new {
  my $class = shift;
  my $self {@_};
  bless $self, $class;
  return $self;
}

Then rewrite the above snippet of your code to:

sub handler ($$) {
  my ($class, $q) = @_;
  my $r = Apache::Request->new($q);
  my $self = $class->new(request=>$r);
  $self->child_init unless $self->{_child_started_up};
  # The rest of the code...

Then you should be good to go (instance variables and all!).  Hope that
helps,

Chris