Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- package Cache::Lite::FIFO;
- use strict;
- use warnings;
- use Scalar::Util qw();
- sub GC_FACTOR () { 10 }
- sub new {
- my ($klass, %args) = @_;
- return bless {
- size => 1024,
- %args,
- _entries => {}, # $key => $valueref
- _fifo => [], # fifo queue of [ $key, $weak_valueref ]
- }, $klass;
- }
- sub set {
- my ($self, $key, $value) = @_;
- my $entries = $self->{_entries};
- # register
- $entries->{$key} = \$value;
- $self->_update_fifo($key, \$value);
- # expire the oldest entry if full
- while (scalar(keys %$entries) > $self->{size}) {
- my ($exp_key, $exp_value) = @{shift @{$self->{_fifo}}};
- delete $entries->{$exp_key}
- if $exp_value;
- }
- $value;
- }
- sub remove {
- my ($self, $key) = @_;
- my $value_ref = delete $self->{_entries}->{$key};
- $value_ref && $$value_ref;
- }
- sub get {
- my ($self, $key) = @_;
- my $value_ref = $self->{_entries}->{$key};
- $value_ref && $$value_ref;
- }
- sub _update_fifo {
- my ($self, $key, $value_ref) = @_;
- my $fifo = $self->{_fifo};
- my $fifo_entry = [ $key, $value_ref ];
- Scalar::Util::weaken($fifo_entry->[1]);
- # GC the fifo queue if it has become too large
- push @$fifo, $fifo_entry;
- if (@$fifo >= $self->{size} * GC_FACTOR) {
- $self->{_fifo} = [ grep { $_->[1] } @$fifo ];
- }
- }
- 1;
- __END__
- use strict;
- use warnings;
- use Test::More;
- BEGIN {
- use_ok("Cache::Lite::FIFO");
- };
- my $cache = Cache::Lite::FIFO->new(
- size => 3,
- );
- ok ! defined $cache->get('a');
- is $cache->set(a => 1), 1;
- is $cache->get('a'), 1;
- is $cache->set(b => 2), 2;
- is $cache->get('a'), 1;
- is $cache->get('b'), 2;
- is $cache->set(c => 3), 3;
- is $cache->get('a'), 1;
- is $cache->get('b'), 2;
- is $cache->get('c'), 3;
- is $cache->set(b => 4), 4;
- is $cache->get('a'), 1;
- is $cache->get('b'), 4;
- is $cache->get('c'), 3;
- my $keep = $cache->get('a');
- is $keep, 1; # intentionally get "a" now, to check it's FIFO not LRU
- is $cache->set(d => 5), 5;
- ok ! defined $cache->get('a');
- is $cache->get('b'), 4;
- is $cache->get('c'), 3;
- is $cache->get('d'), 5;
- is $cache->set('e', 6), 6;
- ok ! defined $cache->get('a');
- is $cache->get('b'), 4;
- ok ! defined $cache->get('c');
- is $cache->get('d'), 5;
- is $cache->get('e'), 6;
- done_testing;
Add Comment
Please, Sign In to add comment