#! perl -slw use strict; package Q; use threads; use threads::shared; use constant { NEXT_WRITE => -2, N => -1, }; sub new { # warn "new: @_\n"; my( $class, $Qsize ) = @_; $Qsize //= 3; my @Q :shared; $#Q = $Qsize; @Q[ NEXT_WRITE, N ] = ( 0, 0 ); ## nextWrite, N # warn sprintf "new: size %d\n\n", scalar @Q; return bless \@Q, $class; } sub nq { # warn "nq: @_\n"; my $self = shift; lock @$self; for( @_ ) { cond_wait @$self until $self->[ N ] < ( @$self-2 ); $self->[ $self->[ NEXT_WRITE ]++ ] = $_; ++$self->[ N ]; $self->[ NEXT_WRITE ] %= ( @$self - 2 ); cond_signal @$self; } } sub dq { # warn "dq: @_\n"; my $self = shift; lock @$self; cond_wait @$self until $self->[ N ] > 0; my $p = $self->[ NEXT_WRITE ] - $self->[ N ]--; $p += @$self -2 if $p < 0; my $out = $self->[ $p ]; cond_signal @$self; return $out; } sub n { my $self = shift; # lock @$self; return $self->[ N ]; } sub _state { no warnings; my $self = shift; lock @$self; return join '|', @{ $self }; } return 1 if caller;