File Coverage

lib/PEF/CacheLRU.pm
Criterion Covered Total %
statement 56 59 94.9
branch 12 16 75.0
condition n/a
subroutine 9 10 90.0
pod 6 6 100.0
total 83 91 91.2


line stmt bran cond sub pod time code
1             package PEF::CacheLRU;
2 1     1   21799 use strict;
  1         2  
  1         22  
3 1     1   5 use warnings;
  1         2  
  1         41  
4             use constant {
5 1         795 NEXT => 0,
6             PREV => 1,
7             KEY => 2,
8             VALUE => 3,
9             HEAD => 0,
10             TAIL => 1,
11             NODES => 2,
12             SIZE => 3,
13             MAXSIZE => 4,
14 1     1   4 };
  1         5  
15              
16             our $VERSION = "0.02";
17              
18             sub new {
19 4     4 1 18 my ($class, $max_size) = @_;
20 4         13 my $self = bless [[undef, undef], undef, {}, 0, $max_size,], $class;
21 4         8 $self->[TAIL] = $self->[HEAD];
22 4         10 $self;
23             }
24              
25             sub max_size {
26 0     0 1 0 $_[0]->[MAXSIZE];
27             }
28              
29             sub size {
30 1     1 1 16 $_[0]->[SIZE];
31             }
32              
33             sub _promote {
34 1034     1034   1188 my ($self, $node) = @_;
35 1034         1209 my $pre = $node->[PREV];
36 1034         1176 $node->[PREV] = undef;
37 1034         1144 $pre->[NEXT] = $node->[NEXT];
38 1034         1157 $pre->[NEXT][PREV] = $pre;
39 1034         1178 $node->[NEXT] = $self->[HEAD];
40 1034         1066 $self->[HEAD] = $node;
41 1034         1572 $self->[HEAD][NEXT][PREV] = $self->[HEAD];
42             }
43              
44             sub remove {
45 1     1 1 2 my ($self, $key) = @_;
46 1 50       4 return if not exists $self->[NODES]{$key};
47 1         3 my $node = $self->[NODES]{$key};
48 1         3 --$self->[SIZE];
49 1 50       4 if ($node == $self->[HEAD]) {
50 0         0 $self->[HEAD] = $node->[NEXT];
51 0         0 $self->[HEAD][PREV] = undef;
52             } else {
53 1         2 my $pre = $node->[PREV];
54 1         2 $pre->[NEXT] = $node->[NEXT];
55 1         3 $node->[NEXT][PREV] = $pre;
56             }
57 1         2 delete $self->[NODES]{$node->[KEY]};
58 1         2 $node->[NEXT] = undef;
59 1         2 $node->[PREV] = undef;
60 1         5 $node->[VALUE];
61             }
62              
63             sub set {
64 1768     1768 1 6234 my ($self, $key, $value) = @_;
65 1768 100       3207 if (my $node = $self->[NODES]{$key}) {
66 1         2 $node->[VALUE] = $value;
67 1 50       10 $self->_promote($node) if $node != $self->[HEAD];
68             } else {
69 1767         3531 $self->[HEAD] = [$self->[HEAD], undef, $key, $value];
70 1767         2406 $self->[HEAD][NEXT][PREV] = $self->[HEAD];
71 1767         2740 $self->[NODES]{$key} = $self->[HEAD];
72 1767 100       3529 if (++$self->[SIZE] > $self->[MAXSIZE]) {
73 1756         2175 my $pre_least = $self->[TAIL][PREV];
74 1756 50       3466 if (my $pre = $pre_least->[PREV]) {
75 1756         2591 delete $self->[NODES]{$pre_least->[KEY]};
76 1756         2310 $pre->[NEXT] = $self->[TAIL];
77 1756         2144 $self->[TAIL][PREV] = $pre;
78 1756         1888 $pre_least->[NEXT] = undef;
79 1756         1898 $pre_least->[PREV] = undef;
80 1756         3116 --$self->[SIZE];
81             }
82             }
83             }
84 1768         3170 $value;
85             }
86              
87             sub get {
88 3032     3032 1 13057 my ($self, $key) = @_;
89 3032 100       5635 if (my $node = $self->[NODES]{$key}) {
90 1268 100       3177 $self->_promote($node) if $node != $self->[HEAD];
91 1268         2344 $node->[VALUE];
92             } else {
93 1764         2800 return;
94             }
95             }
96              
97             1;
98              
99             __END__