Commit | Line | Data |
---|---|---|
86530b38 AT |
1 | .\" Automatically generated by Pod::Man v1.34, Pod::Parser v1.13 |
2 | .\" | |
3 | .\" Standard preamble: | |
4 | .\" ======================================================================== | |
5 | .de Sh \" Subsection heading | |
6 | .br | |
7 | .if t .Sp | |
8 | .ne 5 | |
9 | .PP | |
10 | \fB\\$1\fR | |
11 | .PP | |
12 | .. | |
13 | .de Sp \" Vertical space (when we can't use .PP) | |
14 | .if t .sp .5v | |
15 | .if n .sp | |
16 | .. | |
17 | .de Vb \" Begin verbatim text | |
18 | .ft CW | |
19 | .nf | |
20 | .ne \\$1 | |
21 | .. | |
22 | .de Ve \" End verbatim text | |
23 | .ft R | |
24 | .fi | |
25 | .. | |
26 | .\" Set up some character translations and predefined strings. \*(-- will | |
27 | .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left | |
28 | .\" double quote, and \*(R" will give a right double quote. | will give a | |
29 | .\" real vertical bar. \*(C+ will give a nicer C++. Capital omega is used to | |
30 | .\" do unbreakable dashes and therefore won't be available. \*(C` and \*(C' | |
31 | .\" expand to `' in nroff, nothing in troff, for use with C<>. | |
32 | .tr \(*W-|\(bv\*(Tr | |
33 | .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' | |
34 | .ie n \{\ | |
35 | . ds -- \(*W- | |
36 | . ds PI pi | |
37 | . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch | |
38 | . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch | |
39 | . ds L" "" | |
40 | . ds R" "" | |
41 | . ds C` "" | |
42 | . ds C' "" | |
43 | 'br\} | |
44 | .el\{\ | |
45 | . ds -- \|\(em\| | |
46 | . ds PI \(*p | |
47 | . ds L" `` | |
48 | . ds R" '' | |
49 | 'br\} | |
50 | .\" | |
51 | .\" If the F register is turned on, we'll generate index entries on stderr for | |
52 | .\" titles (.TH), headers (.SH), subsections (.Sh), items (.Ip), and index | |
53 | .\" entries marked with X<> in POD. Of course, you'll have to process the | |
54 | .\" output yourself in some meaningful fashion. | |
55 | .if \nF \{\ | |
56 | . de IX | |
57 | . tm Index:\\$1\t\\n%\t"\\$2" | |
58 | .. | |
59 | . nr % 0 | |
60 | . rr F | |
61 | .\} | |
62 | .\" | |
63 | .\" For nroff, turn off justification. Always turn off hyphenation; it makes | |
64 | .\" way too many mistakes in technical documents. | |
65 | .hy 0 | |
66 | .if n .na | |
67 | .\" | |
68 | .\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). | |
69 | .\" Fear. Run. Save yourself. No user-serviceable parts. | |
70 | . \" fudge factors for nroff and troff | |
71 | .if n \{\ | |
72 | . ds #H 0 | |
73 | . ds #V .8m | |
74 | . ds #F .3m | |
75 | . ds #[ \f1 | |
76 | . ds #] \fP | |
77 | .\} | |
78 | .if t \{\ | |
79 | . ds #H ((1u-(\\\\n(.fu%2u))*.13m) | |
80 | . ds #V .6m | |
81 | . ds #F 0 | |
82 | . ds #[ \& | |
83 | . ds #] \& | |
84 | .\} | |
85 | . \" simple accents for nroff and troff | |
86 | .if n \{\ | |
87 | . ds ' \& | |
88 | . ds ` \& | |
89 | . ds ^ \& | |
90 | . ds , \& | |
91 | . ds ~ ~ | |
92 | . ds / | |
93 | .\} | |
94 | .if t \{\ | |
95 | . ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" | |
96 | . ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' | |
97 | . ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' | |
98 | . ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' | |
99 | . ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' | |
100 | . ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' | |
101 | .\} | |
102 | . \" troff and (daisy-wheel) nroff accents | |
103 | .ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' | |
104 | .ds 8 \h'\*(#H'\(*b\h'-\*(#H' | |
105 | .ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] | |
106 | .ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' | |
107 | .ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' | |
108 | .ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] | |
109 | .ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] | |
110 | .ds ae a\h'-(\w'a'u*4/10)'e | |
111 | .ds Ae A\h'-(\w'A'u*4/10)'E | |
112 | . \" corrections for vroff | |
113 | .if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' | |
114 | .if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' | |
115 | . \" for low resolution devices (crt and lpr) | |
116 | .if \n(.H>23 .if \n(.V>19 \ | |
117 | \{\ | |
118 | . ds : e | |
119 | . ds 8 ss | |
120 | . ds o a | |
121 | . ds d- d\h'-1'\(ga | |
122 | . ds D- D\h'-1'\(hy | |
123 | . ds th \o'bp' | |
124 | . ds Th \o'LP' | |
125 | . ds ae ae | |
126 | . ds Ae AE | |
127 | .\} | |
128 | .rm #[ #] #H #V #F C | |
129 | .\" ======================================================================== | |
130 | .\" | |
131 | .IX Title "Memoize::Expire 3" | |
132 | .TH Memoize::Expire 3 "2002-06-01" "perl v5.8.0" "Perl Programmers Reference Guide" | |
133 | .SH "NAME" | |
134 | Memoize::Expire \- Plug\-in module for automatic expiration of memoized values | |
135 | .SH "SYNOPSIS" | |
136 | .IX Header "SYNOPSIS" | |
137 | .Vb 5 | |
138 | \& use Memoize; | |
139 | \& use Memoize::Expire; | |
140 | \& tie my %cache => 'Memoize::Expire', | |
141 | \& LIFETIME => $lifetime, # In seconds | |
142 | \& NUM_USES => $n_uses; | |
143 | .Ve | |
144 | .PP | |
145 | .Vb 1 | |
146 | \& memoize 'function', SCALAR_CACHE => [HASH => \e%cache ]; | |
147 | .Ve | |
148 | .SH "DESCRIPTION" | |
149 | .IX Header "DESCRIPTION" | |
150 | Memoize::Expire is a plug-in module for Memoize. It allows the cached | |
151 | values for memoized functions to expire automatically. This manual | |
152 | assumes you are already familiar with the Memoize module. If not, you | |
153 | should study that manual carefully first, paying particular attention | |
154 | to the \s-1HASH\s0 feature. | |
155 | .PP | |
156 | Memoize::Expire is a layer of software that you can insert in between | |
157 | Memoize itself and whatever underlying package implements the cache. | |
158 | The layer presents a hash variable whose values expire whenever they | |
159 | get too old, have been used too often, or both. You tell \f(CW\*(C`Memoize\*(C'\fR to | |
160 | use this forgetful hash as its cache instead of the default, which is | |
161 | an ordinary hash. | |
162 | .PP | |
163 | To specify a real-time timeout, supply the \f(CW\*(C`LIFETIME\*(C'\fR option with a | |
164 | numeric value. Cached data will expire after this many seconds, and | |
165 | will be looked up afresh when it expires. When a data item is looked | |
166 | up afresh, its lifetime is reset. | |
167 | .PP | |
168 | If you specify \f(CW\*(C`NUM_USES\*(C'\fR with an argument of \fIn\fR, then each cached | |
169 | data item will be discarded and looked up afresh after the \fIn\fRth time | |
170 | you access it. When a data item is looked up afresh, its number of | |
171 | uses is reset. | |
172 | .PP | |
173 | If you specify both arguments, data will be discarded from the cache | |
174 | when either expiration condition holds. | |
175 | .PP | |
176 | Memoize::Expire uses a real hash internally to store the cached data. | |
177 | You can use the \f(CW\*(C`HASH\*(C'\fR option to Memoize::Expire to supply a tied | |
178 | hash in place of the ordinary hash that Memoize::Expire will normally | |
179 | use. You can use this feature to add Memoize::Expire as a layer in | |
180 | between a persistent disk hash and Memoize. If you do this, you get a | |
181 | persistent disk cache whose entries expire automatically. For | |
182 | example: | |
183 | .PP | |
184 | .Vb 7 | |
185 | \& # Memoize | |
186 | \& # | | |
187 | \& # Memoize::Expire enforces data expiration policy | |
188 | \& # | | |
189 | \& # DB_File implements persistence of data in a disk file | |
190 | \& # | | |
191 | \& # Disk file | |
192 | .Ve | |
193 | .PP | |
194 | .Vb 3 | |
195 | \& use Memoize; | |
196 | \& use Memoize::Expire; | |
197 | \& use DB_File; | |
198 | .Ve | |
199 | .PP | |
200 | .Vb 2 | |
201 | \& # Set up persistence | |
202 | \& tie my %disk_cache => 'DB_File', $filename, O_CREAT|O_RDWR, 0666]; | |
203 | .Ve | |
204 | .PP | |
205 | .Vb 5 | |
206 | \& # Set up expiration policy, supplying persistent hash as a target | |
207 | \& tie my %cache => 'Memoize::Expire', | |
208 | \& LIFETIME => $lifetime, # In seconds | |
209 | \& NUM_USES => $n_uses, | |
210 | \& HASH => \e%disk_cache; | |
211 | .Ve | |
212 | .PP | |
213 | .Vb 2 | |
214 | \& # Set up memoization, supplying expiring persistent hash for cache | |
215 | \& memoize 'function', SCALAR_CACHE => [ HASH => \e%cache ]; | |
216 | .Ve | |
217 | .SH "INTERFACE" | |
218 | .IX Header "INTERFACE" | |
219 | There is nothing special about Memoize::Expire. It is just an | |
220 | example. If you don't like the policy that it implements, you are | |
221 | free to write your own expiration policy module that implements | |
222 | whatever policy you desire. Here is how to do that. Let us suppose | |
223 | that your module will be named MyExpirePolicy. | |
224 | .PP | |
225 | Short summary: You need to create a package that defines four methods: | |
226 | .IP "\s-1TIEHASH\s0" 4 | |
227 | .IX Item "TIEHASH" | |
228 | Construct and return cache object. | |
229 | .IP "\s-1EXISTS\s0" 4 | |
230 | .IX Item "EXISTS" | |
231 | Given a function argument, is the corresponding function value in the | |
232 | cache, and if so, is it fresh enough to use? | |
233 | .IP "\s-1FETCH\s0" 4 | |
234 | .IX Item "FETCH" | |
235 | Given a function argument, look up the corresponding function value in | |
236 | the cache and return it. | |
237 | .IP "\s-1STORE\s0" 4 | |
238 | .IX Item "STORE" | |
239 | Given a function argument and the corresponding function value, store | |
240 | them into the cache. | |
241 | .IP "\s-1CLEAR\s0" 4 | |
242 | .IX Item "CLEAR" | |
243 | (Optional.) Flush the cache completely. | |
244 | .PP | |
245 | The user who wants the memoization cache to be expired according to | |
246 | your policy will say so by writing | |
247 | .PP | |
248 | .Vb 2 | |
249 | \& tie my %cache => 'MyExpirePolicy', args...; | |
250 | \& memoize 'function', SCALAR_CACHE => [HASH => \e%cache]; | |
251 | .Ve | |
252 | .PP | |
253 | This will invoke \f(CW\*(C`MyExpirePolicy\->TIEHASH(args)\*(C'\fR. | |
254 | MyExpirePolicy::TIEHASH should do whatever is appropriate to set up | |
255 | the cache, and it should return the cache object to the caller. | |
256 | .PP | |
257 | For example, MyExpirePolicy::TIEHASH might create an object that | |
258 | contains a regular Perl hash (which it will to store the cached | |
259 | values) and some extra information about the arguments and how old the | |
260 | data is and things like that. Let us call this object `C'. | |
261 | .PP | |
262 | When Memoize needs to check to see if an entry is in the cache | |
263 | already, it will invoke \f(CW\*(C`C\->EXISTS(key)\*(C'\fR. \f(CW\*(C`key\*(C'\fR is the normalized | |
264 | function argument. MyExpirePolicy::EXISTS should return 0 if the key | |
265 | is not in the cache, or if it has expired, and 1 if an unexpired value | |
266 | is in the cache. It should \fInot\fR return \f(CW\*(C`undef\*(C'\fR, because there is a | |
267 | bug in some versions of Perl that will cause a spurious \s-1FETCH\s0 if the | |
268 | \&\s-1EXISTS\s0 method returns \f(CW\*(C`undef\*(C'\fR. | |
269 | .PP | |
270 | If your \s-1EXISTS\s0 function returns true, Memoize will try to fetch the | |
271 | cached value by invoking \f(CW\*(C`C\->FETCH(key)\*(C'\fR. MyExpirePolicy::FETCH should | |
272 | return the cached value. Otherwise, Memoize will call the memoized | |
273 | function to compute the appropriate value, and will store it into the | |
274 | cache by calling \f(CW\*(C`C\->STORE(key, value)\*(C'\fR. | |
275 | .PP | |
276 | Here is a very brief example of a policy module that expires each | |
277 | cache item after ten seconds. | |
278 | .PP | |
279 | .Vb 1 | |
280 | \& package Memoize::TenSecondExpire; | |
281 | .Ve | |
282 | .PP | |
283 | .Vb 5 | |
284 | \& sub TIEHASH { | |
285 | \& my ($package, %args) = @_; | |
286 | \& my $cache = $args{HASH} || {}; | |
287 | \& bless $cache => $package; | |
288 | \& } | |
289 | .Ve | |
290 | .PP | |
291 | .Vb 9 | |
292 | \& sub EXISTS { | |
293 | \& my ($cache, $key) = @_; | |
294 | \& if (exists $cache->{$key} && | |
295 | \& $cache->{$key}{EXPIRE_TIME} > time) { | |
296 | \& return 1 | |
297 | \& } else { | |
298 | \& return 0; # Do NOT return `undef' here. | |
299 | \& } | |
300 | \& } | |
301 | .Ve | |
302 | .PP | |
303 | .Vb 4 | |
304 | \& sub FETCH { | |
305 | \& my ($cache, $key) = @_; | |
306 | \& return $cache->{$key}{VALUE}; | |
307 | \& } | |
308 | .Ve | |
309 | .PP | |
310 | .Vb 5 | |
311 | \& sub STORE { | |
312 | \& my ($cache, $key, $newvalue) = @_; | |
313 | \& $cache->{$key}{VALUE} = $newvalue; | |
314 | \& $cache->{$key}{EXPIRE_TIME} = time + 10; | |
315 | \& } | |
316 | .Ve | |
317 | .PP | |
318 | To use this expiration policy, the user would say | |
319 | .PP | |
320 | .Vb 3 | |
321 | \& use Memoize; | |
322 | \& tie my %cache10sec => 'Memoize::TenSecondExpire'; | |
323 | \& memoize 'function', SCALAR_CACHE => [HASH => \e%cache10sec]; | |
324 | .Ve | |
325 | .PP | |
326 | Memoize would then call \f(CW\*(C`function\*(C'\fR whenever a cached value was | |
327 | entirely absent or was older than ten seconds. | |
328 | .PP | |
329 | You should always support a \f(CW\*(C`HASH\*(C'\fR argument to \f(CW\*(C`TIEHASH\*(C'\fR that ties | |
330 | the underlying cache so that the user can specify that the cache is | |
331 | also persistent or that it has some other interesting semantics. The | |
332 | example above demonstrates how to do this, as does \f(CW\*(C`Memoize::Expire\*(C'\fR. | |
333 | .SH "ALTERNATIVES" | |
334 | .IX Header "ALTERNATIVES" | |
335 | Brent Powers has a \f(CW\*(C`Memoize::ExpireLRU\*(C'\fR module that was designed to | |
336 | work with Memoize and provides expiration of least-recently-used data. | |
337 | The cache is held at a fixed number of entries, and when new data | |
338 | comes in, the least-recently used data is expired. See | |
339 | <http://search.cpan.org/search?mode=module&query=ExpireLRU>. | |
340 | .PP | |
341 | Joshua Chamas's Tie::Cache module may be useful as an expiration | |
342 | manager. (If you try this, let me know how it works out.) | |
343 | .PP | |
344 | If you develop any useful expiration managers that you think should be | |
345 | distributed with Memoize, please let me know. | |
346 | .SH "CAVEATS" | |
347 | .IX Header "CAVEATS" | |
348 | This module is experimental, and may contain bugs. Please report bugs | |
349 | to the address below. | |
350 | .PP | |
351 | Number-of-uses is stored as a 16\-bit unsigned integer, so can't exceed | |
352 | 65535. | |
353 | .PP | |
354 | Because of clock granularity, expiration times may occur up to one | |
355 | second sooner than you expect. For example, suppose you store a value | |
356 | with a lifetime of ten seconds, and you store it at 12:00:00.998 on a | |
357 | certain day. Memoize will look at the clock and see 12:00:00. Then | |
358 | 9.01 seconds later, at 12:00:10.008 you try to read it back. Memoize | |
359 | will look at the clock and see 12:00:10 and conclude that the value | |
360 | has expired. This will probably not occur if you have | |
361 | \&\f(CW\*(C`Time::HiRes\*(C'\fR installed. | |
362 | .SH "AUTHOR" | |
363 | .IX Header "AUTHOR" | |
364 | Mark-Jason Dominus (mjd\-perl\-memoize+@plover.com) | |
365 | .PP | |
366 | Mike Cariaso provided valuable insight into the best way to solve this | |
367 | problem. | |
368 | .SH "SEE ALSO" | |
369 | .IX Header "SEE ALSO" | |
370 | \&\fIperl\fR\|(1) | |
371 | .PP | |
372 | The Memoize man page. | |
373 | .PP | |
374 | http://www.plover.com/~mjd/perl/Memoize/ (for news and updates) | |
375 | .PP | |
376 | I maintain a mailing list on which I occasionally announce new | |
377 | versions of Memoize. The list is for announcements only, not | |
378 | discussion. To join, send an empty message to | |
379 | mjd\-perl\-memoize\-request@Plover.com. |