Subject: | Patch to enable manual management of the cache |
In some situations it's desirable to manage when the cache is sized to the max length. Here's a patch with a test to enable that.
Subject: | manual_size_management.patch |
diff --git a/lib/Cache/LRU.pm b/lib/Cache/LRU.pm
index 31be5ec..8597ff5 100644
--- a/lib/Cache/LRU.pm
+++ b/lib/Cache/LRU.pm
@@ -23,7 +23,6 @@ sub new {
sub set {
my ($self, $key, $value) = @_;
-
my $entries = $self->{_entries};
if (my $old_value_ref = $entries->{$key}) {
@@ -34,15 +33,19 @@ sub set {
my $value_ref = \$value;
Scalar::Util::weaken($entries->{$key} = $value_ref);
$self->_update_fifo($key, $value_ref);
+ $self->_auto_expire;
+ $value;
+}
+sub _auto_expire {
+ my ($self) = @_;
+ my $entries = $self->{_entries};
# expire the oldest entry if full
while (scalar(keys %$entries) > $self->{size}) {
my $exp_key = shift(@{$self->{_fifo}})->[0];
delete $entries->{$exp_key}
- unless $entries->{$exp_key};
+ unless $entries->{$exp_key};
}
-
- $value;
}
sub remove {
@@ -90,6 +93,13 @@ sub _update_fifo {
}
}
+sub force_update {
+ my ($self, $real_size) = @_;
+ return if $self->{size} != 'inf';
+ local $self->{size} = $real_size;
+ $self->_auto_expire;
+}
+
1;
__END__
@@ -137,6 +147,13 @@ Removes data associated to the given key and returns the old value, if any.
Removes all entries from the cache.
+=head2 $cache->force_update($real_size)
+
+In the case you want to manually manage the cache length yourself, set
+$cache->{size} to be "inf" and pass in $real_size into this method at
+a point in the code of your chosing (e.g. if $cache is a package
+variable, maybe in DESTROY).
+
=head1 AUTHOR
Kazuho Oku
diff --git a/t/manual_management.t b/t/manual_management.t
new file mode 100644
index 0000000..0ddd989
--- /dev/null
+++ b/t/manual_management.t
@@ -0,0 +1,61 @@
+use strict;
+use warnings;
+
+use Test::More;
+
+BEGIN {
+ use_ok("Cache::LRU");
+};
+
+my $cache = Cache::LRU->new(
+ size => "inf",
+);
+
+my $real_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;
+is +($keep = $cache->get('a')), 1; # the order is now a => c => b
+is $cache->set(d => 5), 5;
+is $cache->get('a'), 1;
+$cache->force_update($real_size);
+ok ! defined $cache->get('b');
+is $cache->get('c'), 3;
+is $cache->get('d'), 5; # the order is now d => c => a
+
+is $cache->set('e', 6), 6;
+$cache->force_update($real_size);
+ok ! defined $cache->get('a');
+ok ! defined $cache->get('b');
+is $cache->get('c'), 3;
+is $cache->get('d'), 5;
+is $cache->get('e'), 6;
+
+is $cache->remove('d'), 5;
+is $cache->get('c'), 3;
+ok ! defined $cache->get('d');
+is $cache->get('e'), 6;
+
+$cache->clear;
+ok ! defined $cache->get('c');
+ok ! defined $cache->get('e');
+
+done_testing;