in reply to Linked lists in an array of hashes

Ring buffers are used in performance critical situations, often in embedded code, where a fixed size chunk of memory is allocated and used as a queue for buffering data.

The usual implementation uses two pointers (indexes). Details vary a little, but by inspecting the pointers you can determine if the buffer is full (incrementing the input pointer would make it match the output pointer), empty (input pointer matches output pointer) or somewhere between. Very often the buffer size is a power of 2 to take advantage binary arithmetic operations to reduce code complexity and increase speed.

Except as an exercise there is no application I can think of where writing a ring buffer in Perl would be useful. The following may be of interest though:

use strict; use warnings; my $buffer = new (); print "Buffer has ", $buffer->count (), " values\n"; $buffer->push ($_) for 1 .. 200; print "Buffer has ", $buffer->count (), " values\n"; $buffer->pop () for 1 .. 100; print "Buffer has ", $buffer->count (), " values\n"; $buffer->push ($_ + 200) for 1 .. 150; print "Buffer has ", $buffer->count (), " values\n"; sub new { my @bufferArray; my $buffSize = 256; $#bufferArray = 256; # set buffer size return $buffer = bless { buffer => \@bufferArray, in => 0, out => 0, buffSize => $buffSize, }; } sub count { my ($self) = @_; my $used = $self->{in} - $self->{out}; $used += $self->{buffSize} if $used < 0; return $used; } sub pop { my ($self) = @_; die "Buffer underflow" if $self->{in} == $self->{out}; my $value = $self->{buffer}[$self->{out}]; $self->{out} = ($self->{out} + 1) % $self->{buffSize}; return $value; } sub push { my ($self, $value) = @_; die "Buffer overflow" if $self->count () + 1 == $self->{buffSize}; $self->{buffer}[$self->{in}] = $value; $self->{in} = ($self->{in} + 1) % $self->{buffSize}; }

Prints:

Buffer has 0 values Buffer has 200 values Buffer has 100 values Buffer has 250 values

Update: Fixed reporting error in push - thanks ikegami!


True laziness is hard work