Guest User

Untitled

a guest
Jul 15th, 2018
89
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 2.22 KB | None | 0 0
  1. package Cache::Lite::FIFO;
  2.  
  3. use strict;
  4. use warnings;
  5.  
  6. use Scalar::Util qw();
  7.  
  8. sub GC_FACTOR () { 10 }
  9.  
  10. sub new {
  11. my ($klass, %args) = @_;
  12. return bless {
  13. size => 1024,
  14. %args,
  15. _entries => {}, # $key => $valueref
  16. _fifo => [], # fifo queue of [ $key, $weak_valueref ]
  17. }, $klass;
  18. }
  19.  
  20. sub set {
  21. my ($self, $key, $value) = @_;
  22.  
  23. my $entries = $self->{_entries};
  24.  
  25. # register
  26. $entries->{$key} = \$value;
  27. $self->_update_fifo($key, \$value);
  28.  
  29. # expire the oldest entry if full
  30. while (scalar(keys %$entries) > $self->{size}) {
  31. my ($exp_key, $exp_value) = @{shift @{$self->{_fifo}}};
  32. delete $entries->{$exp_key}
  33. if $exp_value;
  34. }
  35.  
  36. $value;
  37. }
  38.  
  39. sub remove {
  40. my ($self, $key) = @_;
  41. my $value_ref = delete $self->{_entries}->{$key};
  42. $value_ref && $$value_ref;
  43. }
  44.  
  45. sub get {
  46. my ($self, $key) = @_;
  47. my $value_ref = $self->{_entries}->{$key};
  48. $value_ref && $$value_ref;
  49. }
  50.  
  51. sub _update_fifo {
  52. my ($self, $key, $value_ref) = @_;
  53. my $fifo = $self->{_fifo};
  54.  
  55. my $fifo_entry = [ $key, $value_ref ];
  56. Scalar::Util::weaken($fifo_entry->[1]);
  57.  
  58. # GC the fifo queue if it has become too large
  59. push @$fifo, $fifo_entry;
  60. if (@$fifo >= $self->{size} * GC_FACTOR) {
  61. $self->{_fifo} = [ grep { $_->[1] } @$fifo ];
  62. }
  63. }
  64.  
  65. 1;
  66. __END__
  67.  
  68. use strict;
  69. use warnings;
  70.  
  71. use Test::More;
  72.  
  73. BEGIN {
  74. use_ok("Cache::Lite::FIFO");
  75. };
  76.  
  77. my $cache = Cache::Lite::FIFO->new(
  78. size => 3,
  79. );
  80.  
  81. ok ! defined $cache->get('a');
  82.  
  83. is $cache->set(a => 1), 1;
  84. is $cache->get('a'), 1;
  85.  
  86. is $cache->set(b => 2), 2;
  87. is $cache->get('a'), 1;
  88. is $cache->get('b'), 2;
  89.  
  90. is $cache->set(c => 3), 3;
  91. is $cache->get('a'), 1;
  92. is $cache->get('b'), 2;
  93. is $cache->get('c'), 3;
  94.  
  95. is $cache->set(b => 4), 4;
  96. is $cache->get('a'), 1;
  97. is $cache->get('b'), 4;
  98. is $cache->get('c'), 3;
  99.  
  100. my $keep = $cache->get('a');
  101. is $keep, 1; # intentionally get "a" now, to check it's FIFO not LRU
  102. is $cache->set(d => 5), 5;
  103. ok ! defined $cache->get('a');
  104. is $cache->get('b'), 4;
  105. is $cache->get('c'), 3;
  106. is $cache->get('d'), 5;
  107.  
  108. is $cache->set('e', 6), 6;
  109. ok ! defined $cache->get('a');
  110. is $cache->get('b'), 4;
  111. ok ! defined $cache->get('c');
  112. is $cache->get('d'), 5;
  113. is $cache->get('e'), 6;
  114.  
  115. done_testing;
Add Comment
Please, Sign In to add comment