root/lang/perl/Method-Cached/trunk/lib/Method/Cached.pm @ 20955

Revision 20955, 3.7 kB (checked in by bonnu, 5 years ago)

lang/perl/Method-Cached - change in composition of module

Line 
1package Method::Cached;
2
3use strict;
4use warnings;
5use 5.008007;
6use Attribute::Handlers;
7use Carp qw/croak confess/;
8use UNIVERSAL::require;
9use Method::Cached::KeyRule;
10
11our $VERSION = '0.0199';
12
13my %_DOMAINS;
14my $_DEFAULT_DOMAIN = {
15    storage_class => 'Cache::FastMmap',
16    storage_args  => [],
17    key_rule      => 'LIST',
18};
19
20sub UNIVERSAL::Cached :ATTR(CODE) {
21    my ($pkg, $symbol, $code, $options) = @_[0 .. 2, 4];
22    $options = [ $options || () ] unless ref $options eq 'ARRAY';
23    my $name = $pkg . '::' . *{$symbol}{NAME};
24    my ($domain_name, $expires, $key_rule) = _parse_option(@{ $options });
25    no strict 'refs';
26    no warnings 'redefine';
27    *{$name} = sub {
28        my $domain = $_DOMAINS{$domain_name}
29            ? $_DOMAINS{$domain_name}
30            : $_DEFAULT_DOMAIN;
31        $key_rule ||= $domain->{key_rule};
32        my $key = Method::Cached::KeyRule::regularize($key_rule, $name, @_);
33        my $storage = _storage($domain);
34        my $ret = $storage->get($key);
35        return wantarray ? @{ $ret } : ${ $ret }[0] if $ret;
36        my @ret = ($code->(@_));
37        $storage->set($key, \@ret, $expires || 0);
38        return wantarray ? @ret : $ret[0];
39    };
40}
41
42sub import {
43    my ($class, %args) = @_;
44    if (exists $args{-domains} && defined $args{-domains}) {
45        my $domains = $args{-domains};
46        ref $domains eq 'HASH' or confess '-domains option should be a hash reference';
47        $class->set_domain(%{ $domains });
48    }
49    if (exists $args{-default} && defined $args{-default}) {
50        my $default = $args{-default};
51        ref $default eq 'HASH' or confess '-default option should be a hash reference';
52        $class->default_domain($default);
53    }
54}
55
56sub default_domain {
57    my $class = shift;
58    $_DEFAULT_DOMAIN = {
59        %{ $_DEFAULT_DOMAIN },
60        %{ +shift },
61    };
62}
63
64sub set_domain {
65    my $class = shift;
66    while (my ($name, $args) = splice @_, 0, 2) {
67        if (exists $_DOMAINS{$name}) {
68            warn 'This domain has already been defined: ' . $name;
69            next;
70        }
71        $_DOMAINS{$name} = $args;
72    }
73}
74
75sub _parse_option {
76    my $domain_name = q{};
77    my $expires     = 0;
78    my $key_rule    = undef;
79    if (0 < @_) {
80        if ((! defined $_[0]) || ($_[0] !~ /^-?\d+$/)) {
81            $domain_name = shift;
82        }
83    }
84    $domain_name ||= q{};
85    if (0 < @_) {
86        $expires  =
87            ($_[0] =~ /^-?\d+$/) ? shift @_ :
88            confess 'The first argument or the second argument should be a numeric value.';
89        $key_rule = shift if 0 < @_;
90    }
91    return ($domain_name, $expires, $key_rule);
92}
93
94sub _storage {
95    my $domain = shift;
96    $domain->{_storage_instance} && return $domain->{_storage_instance};
97    my $storage_class = $domain->{storage_class} || croak 'storage_class is necessary';
98    my $storage_args  = $domain->{storage_args}  || undef;
99    $storage_class->require || confess "Can't load module: $storage_class";
100    $domain->{_storage_instance} = $storage_class->new(@{ $storage_args || [] });
101}
102
1031;
104
105__END__
106
107=head1 NAME
108
109Method::Cached - The return value of the method is cached to your storage
110
111=head1 SYNOPSIS
112
113  package Foo;
114   
115  use Method::Cached;
116   
117  sub message :Cached(5) {
118      join ':', @_, time, rand
119  }
120 
121  package main;
122  use Perl6::Say;
123 
124  say Foo::message(1); # 1222333848
125  sleep 1;
126  say Foo::message(1); # 1222333848
127 
128  say Foo::message(5); # 1222333849
129
130=head1 DESCRIPTION
131
132Method::Cached offers the following mechanisms:
133The return value of the method is stored in storage, and
134the value stored when being execute it next time is returned.
135
136=head1 AUTHOR
137
138Satoshi Ohkubo E<lt>s.ohkubo@gmail.comE<gt>
139
140=head1 LICENSE
141
142This library is free software; you can redistribute it and/or modify
143it under the same terms as Perl itself.
144
145=cut
Note: See TracBrowser for help on using the browser.