/usr/local/CPAN/CORBA-MICO/CORBA/MICO/BGQueue.pm
package CORBA::MICO::BGQueue;
#--------------------------------------------------------------------
# Queue for background processing
#--------------------------------------------------------------------
use Gtk2 '1.140';
use Carp;
use strict;
use vars qw($DEBUG);
#$DEBUG=1;
#--------------------------------------------------------------------
# Create new queue
# In: $interval - time interval (miliseconds)
#--------------------------------------------------------------------
sub new {
my ($type, $interval) = @_;
my $class = ref($type) || $type;
my $self = { 'TAG' => undef,
'QUEUE' => [],
'INTERVAL' => $interval,
'ACTIVE' => undef };
bless $self, $class;
return $self;
}
#--------------------------------------------------------------------
sub close {
my $self = shift;
$self->deactivate();
foreach my $k (keys %$self) {
$self->{$k} = undef;
}
}
#--------------------------------------------------------------------
sub DESTROY {
my $self = shift;
carp "DESTROYING $self" if $DEBUG;
$self->deactivate();
}
#--------------------------------------------------------------------
# Activate timeout handler
#--------------------------------------------------------------------
sub activate {
my $self = shift;
if( not defined($self->{'TAG'}) ) {
my $interval = $self->{'INTERVAL'};
$interval = 20 if $interval == 0;
$self->{'TAG'} = Glib::Timeout->add($interval, \&timeout_hnd, $self);
}
}
#--------------------------------------------------------------------
# Deactivate timeout handler
#--------------------------------------------------------------------
sub deactivate {
my $self = shift;
warn "deactivate" if $DEBUG;
if( defined($self->{'TAG'}) ) {
Glib::Source->remove($self->{'TAG'});
}
$self->{'TAG'} = undef;
}
#--------------------------------------------------------------------
# Add queue entry: an object supporting method 'do_iteration'
# Return values expected from do_iteration():
# true - keep object in the queue
# false - remove object from the queue
#--------------------------------------------------------------------
sub add_entry {
my($self, $entry_object) = @_;
$self->activate();
push(@{$self->{'QUEUE'}}, $entry_object);
}
#--------------------------------------------------------------------
# Remove queue entry
#--------------------------------------------------------------------
sub remove_entry {
my($self, $entry_object) = @_;
if( defined($self->{'ACTIVE'}) and $self->{'ACTIVE'} == $entry_object ) {
$self->remove_active_object();
}
my $queue = $self->{'QUEUE'};
foreach my $i (0..$#$queue) {
if( $queue->[$i] == $entry_object ) {
# remove the entry from the queue
splice(@$queue, $i, 1);
return;
}
}
}
#--------------------------------------------------------------------
# Set active object. Control will be passed to active object
# (if any) and then, only when if active object is removed, other objects
# from queue may be served
#--------------------------------------------------------------------
sub set_active_object {
my($self, $entry_object) = @_;
$self->activate();
$self->{'ACTIVE'} = $entry_object;
}
#--------------------------------------------------------------------
# Remove active object
#--------------------------------------------------------------------
sub remove_active_object {
my($self) = @_;
$self->set_active_object(undef);
}
#--------------------------------------------------------------------
# Background processing: do an iteration.
# 1. Do an iteration for active object and return if it is defined.
# 2. Do an iteration from the first object from the queue and move it
# to the end of the queue
#--------------------------------------------------------------------
sub timeout_hnd {
my ($self) = @_;
my $active_object = $self->{'ACTIVE'};
if( defined($active_object) ) {
$active_object->do_iteration() || ($self->{'ACTIVE'} = undef);
}
else {
my $queue = $self->{'QUEUE'};
if( $#$queue >= 0 ) {
my $obj = shift @$queue;
$obj->do_iteration() && push(@$queue, $obj);
}
else {
# the queue is empty -> deactivate
$self->{'TAG'} = undef;
return 0;
}
}
return 1;
}
1;