cvsuser     04/09/28 08:20:09

  Modified:    App-Context/lib/App Context.pm
  Log:
  scheduled events, async events
  
  Revision  Changes    Path
  1.17      +164 -6    p5ee/App-Context/lib/App/Context.pm
  
  Index: Context.pm
  ===================================================================
  RCS file: /cvs/public/p5ee/App-Context/lib/App/Context.pm,v
  retrieving revision 1.16
  retrieving revision 1.17
  diff -u -w -r1.16 -r1.17
  --- Context.pm        2 Sep 2004 20:56:51 -0000       1.16
  +++ Context.pm        28 Sep 2004 15:20:09 -0000      1.17
  @@ -1,6 +1,6 @@
   
   #############################################################################
  -## $Id: Context.pm,v 1.16 2004/09/02 20:56:51 spadkins Exp $
  +## $Id: Context.pm,v 1.17 2004/09/28 15:20:09 spadkins Exp $
   #############################################################################
   
   package App::Context;
  @@ -255,6 +255,9 @@
       $self->{events} = [];      # the event queue starts empty
       $self->{returntype} = "default";  # assume default return type
   
  +    $self->{scheduled_events} = [];
  +    $self->{scheduled_event} = {};
  +
       $self->_init(\%options);   # allows the subclass to do initialization
   
       $self->set_current_session($self->session("default"));
  @@ -1663,7 +1666,7 @@
       my $events = $self->{events};
       my ($event, $service, $name, $method, $args);
       my $results = "";
  -    my $display_current_widget = 1;
  +    my $show_current_session_object = 1;
   
       eval {
           while ($#$events > -1) {
  @@ -1674,10 +1677,10 @@
               }
               else {
                   $results = $self->call($service, $name, $method, $args);
  -                $display_current_widget = 0;
  +                $show_current_session_object = 0;
               }
           }
  -        if ($display_current_widget) {
  +        if ($show_current_session_object) {
               my $type = $self->so_get("default","ctype","SessionObject");
               my $name = $self->so_get("default","cname","default");
               $results = $self->service($type, $name);
  @@ -1713,9 +1716,15 @@
   sub call {
       &App::sub_entry if ($App::trace);
       my ($self, $service_type, $name, $method, $args) = @_;
  -    my ($contents, $result);
  +    my ($contents, $result, $service);
  +
  +    if ($service_type eq "Context") {
  +        $service = $self;
  +    }
  +    else {
  +        $service = $self->service($service_type, $name);
  +    }
   
  -    my $service = $self->service($service_type, $name);
       if (!$service) {
           $result = "Service not defined: $service_type($name)\n";
       }
  @@ -1804,6 +1813,155 @@
   }
   
   #############################################################################
  +# SCHEDULED EVENTS
  +#############################################################################
  +
  +# valid attributes:
  +#    REQD: method       => "do_it",
  +#    OPT:  tag          => "tag01",          (identifies an event.)
  +#    OPT:  service_type => "SessionObject",  (method is on a SessionObject rather 
than on the Context)
  +#    OPT:  name         => "prog_controller",
  +#    OPT:  time         => time() + 600,
  +#    OPT:  interval     => 600,
  +#    OPT:  args         => [ 1, 2, 3 ],
  +#    OPT:  scheduled    => 0,
  +
  +sub schedule_event {
  +    &App::sub_entry if ($App::trace);
  +    my $self = shift;
  +    my %event = @_;
  +
  +    my $scheduled_event = $self->{scheduled_event};
  +    my $scheduled_events = $self->{scheduled_events};
  +
  +    if (! defined $event{time}) {
  +        $event{time} = time();
  +        $event{time} += $event{interval} if ($event{interval});
  +    }
  +
  +    my $unschedule = 0;
  +    if (defined $event{scheduled}) {
  +        $unschedule = ! $event{scheduled};
  +        delete $event{scheduled};
  +    }
  +
  +    die "schedule_event(): (tag or method) is a required attribute of an event" if 
(!$event{tag} && !$event{method});
  +    print "[$$] Schedule Event (", join(",",%event), ")\n" if ($self->{verbose} >= 
3);
  +
  +    my $event;
  +    if ($event{tag}) {
  +        $event = $scheduled_event->{$event{tag}};
  +    }
  +    if ($event) {
  +        foreach my $key (keys %event) {
  +            $event->{$key} = $event{$key};
  +        }
  +    }
  +    else {
  +        $scheduled_event->{$event{tag}} = \%event if ($event{tag});
  +        $event = \%event;
  +    }
  +
  +    if ($event->{scheduled}) {
  +        if ($unschedule && $event->{tag}) {
  +            # remove from list of scheduled events
  +            for (my $i = $#$scheduled_events; $i >= 0; $i--) {
  +                if ($scheduled_events->[$i]{tag} eq $event->{tag}) {
  +                    splice(@$scheduled_events, $i, 1); # remove the event
  +                    $event->{scheduled} = 0;
  +                    last;
  +                }
  +            }
  +        }
  +    }
  +    else {
  +        if (!$unschedule) {
  +            push(@$scheduled_events, $event);
  +            $event->{scheduled} = 1;
  +        }
  +    }
  +
  +    &App::sub_exit() if ($App::trace);
  +}
  +
  +sub get_current_events {
  +    &App::sub_entry if ($App::trace);
  +    my ($self, $events, $time) = @_;
  +    $time = time() if (!$time);
  +    my $time_of_next_event = 0;
  +    @$events = ();
  +    my $scheduled_event  = $self->{scheduled_event};
  +    my $scheduled_events = $self->{scheduled_events};
  +    my $verbose          = $self->{verbose};
  +    my ($event);
  +    # note: go in reverse order so that the splice() doesn't throw our indexes off
  +    # we do unshift() to keep events executing in FIFO order for a particular time
  +    for (my $i = $#$scheduled_events; $i >= 0; $i--) {
  +        $event = $scheduled_events->[$i];
  +        print "[$$] Checking event: time=$time [$event->{time}, every 
$event->{interval}] $event->{method}().\n" if ($verbose >= 9);
  +        if ($event->{time} <= $time) {
  +            unshift(@$events, $event);
  +            if ($event->{time} && $event->{interval}) {
  +                $event->{time} += $event->{interval}; # reschedule the event
  +                print "[$$] Event Rescheduled: time=$time [$event->{time}, every 
$event->{interval}] $event->{method}().\n" if ($verbose >= 9);
  +                if ($time_of_next_event == 0 || $event->{time} < 
$time_of_next_event) {
  +                    $time_of_next_event = $event->{time};
  +                }
  +            }
  +            else {
  +                print "[$$] Event Removed: time=$time [$event->{time}, every 
$event->{interval}] $event->{method}().\n" if ($verbose >= 9);
  +                splice(@$scheduled_events, $i, 1); # remove the (one-time) event
  +                $event->{scheduled} = 0;
  +            }
  +        }
  +        else {
  +            if ($time_of_next_event == 0 || $event->{time} < $time_of_next_event) {
  +                $time_of_next_event = $event->{time};
  +            }
  +        }
  +    }
  +    &App::sub_exit($time_of_next_event) if ($App::trace);
  +    return($time_of_next_event);
  +}
  +
  +# NOTE: send_event() is similar to call(). I ought to resolve this.
  +sub send_event {
  +    &App::sub_entry if ($App::trace);
  +    my ($self, $event) = @_;
  +    my $method = $event->{method};
  +    my @args = $event->{args} ? @{$event->{args}} : ();
  +    my $service_type = $event->{service_type};
  +    if ($service_type) {
  +        my $name = $event->{name};
  +        my $service = $self->service($service_type, $name);
  +        print "[$$] Send Event: $service_type($name).$method(@args)\n" if 
($self->{verbose} >= 3);
  +        $service->$method(@args);
  +    }
  +    else {
  +        print "[$$] Send Event: $method(@args)\n" if ($self->{verbose} >= 3);
  +        $self->$method(@args);
  +    }
  +    &App::sub_exit() if ($App::trace);
  +}
  +
  +# NOTE: The baseline context doesn't implement asynchronous events.
  +#       Therefore, it simply sends the event, then sends the callback event.
  +#       See Context::Cluster for a context that spawns processes.
  +sub send_async_event {
  +    &App::sub_entry if ($App::trace);
  +    my ($self, $event, $callback_event) = @_;
  +    $self->send_event($event);
  +    if ($callback_event) {
  +        my $event_tag = "local-$$";
  +        if (! $callback_event->{args}) {
  +            $callback_event->{args} = [ $event_tag ];
  +        }
  +        $self->send_event($callback_event);
  +    }
  +    &App::sub_exit() if ($App::trace);
  +}
  +
  +#############################################################################
   # shutdown()
   #############################################################################
   
  
  
  

Reply via email to