The earlier posts seem to be missing the point of a ring buffer. They require no locks when they have one writer thread and one reader thread. Using push+shift produces a queue, but not specifically a ring buffer.

For example, the keyboard buffer used to be a ring buffer. The keyboard would place messages into it to be read by the system.

What the OP is missing is that ring buffers are usually implemented using ever growing indexes into an array, mod the size of the buffer. If you don't want to limit the size of the buffer, you can use a linked list instead of an array. Hashes don't figure into the equation.

my $head = 0; # Can only be modified by the lone writer thread my $tail = 0; # Can only be modified by the lone reader thread my $size = 4; # Can hold one less than $size my @buf = (undef) x $size; # Can only be called by the lone reader thread sub is_empty { return $tail == $head; } # Can only be called by the lone reader thread sub dequeue { return () if is_empty(); my $val = $buf[$tail]; $tail = ( $tail + 1 ) % @buf; return $val; } # Can only be called by the lone writer thread sub is_full { return ($head + 1) % @buf == $tail; } # Can only be called by the lone writer thread sub enqueue { my ($val) = @_; return 0 if is_full(); $buf[$head] = $val; $head = ( $head + 1 ) % @buf; return 1; }

If you have more than one writer thread or more than one reader thread, locking is necessary.

Now, if you want to have multiple buffers going, you can use an object.

package Data::RingBuffer; sub new { my ($class, $size) = @_; return bless({ head => 0, tail => 0, buf => [ (undef) x $size ], }, $class); } sub is_empty { my ($self) = @_; return $self->{tail} == $self->{head}; } sub dequeue { my ($self) = @_; my $buf = $self->{buf}; return () if $self->is_empty(); my $val = $buf->[$self->{tail}]; $self->{tail} = ( $self->{tail} + 1 ) % @$buf; return $val; } sub is_full { my ($self) = @_; my $buf = $self->{buf}; return ($self->{head} + 1) % @$buf == $self->{tail}; } sub enqueue { my ($self, $val) = @_; my $buf = $self->{buf}; return 0 if $self->is_full(); $buf->[$self->{head}] = $val; $self->{head} = ( $self->{head} + 1 ) % @$buf; return 1; }

Update: Fixed typos in code. Simplified code.


In reply to Re: Linked lists in an array of hashes by ikegami
in thread Linked lists in an array of hashes by biohisham

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.