expire.html

来自「perl教程」· HTML 代码 · 共 286 行 · 第 1/2 页

HTML
286 行
字号
<p>Given a function argument, look up the corresponding function value in
the cache and return it.</p>
</dd>
</li>
<dt><strong><a name="item_store">STORE</a></strong>

<dd>
<p>Given a function argument and the corresponding function value, store
them into the cache.</p>
</dd>
</li>
<dt><strong><a name="item_clear">CLEAR</a></strong>

<dd>
<p>(Optional.)  Flush the cache completely.</p>
</dd>
</li>
</dl>
<p>The user who wants the memoization cache to be expired according to
your policy will say so by writing</p>
<pre>
  <span class="keyword">tie</span> <span class="keyword">my</span> <span class="variable">%cache</span> <span class="operator">=&gt;</span> <span class="string">'MyExpirePolicy'</span><span class="operator">,</span> <span class="variable">args</span><span class="operator">...;</span>
  <span class="variable">memoize</span> <span class="string">'function'</span><span class="operator">,</span> <span class="string">SCALAR_CACHE</span> <span class="operator">=&gt;</span> <span class="operator">[</span><span class="string">HASH</span> <span class="operator">=&gt;</span> <span class="operator">\</span><span class="variable">%cache</span><span class="operator">]</span><span class="operator">;</span>
</pre>
<p>This will invoke <a href="#item_tiehash"><code>MyExpirePolicy-&gt;TIEHASH(args)</code></a>.
MyExpirePolicy::TIEHASH should do whatever is appropriate to set up
the cache, and it should return the cache object to the caller.</p>
<p>For example, MyExpirePolicy::TIEHASH might create an object that
contains a regular Perl hash (which it will to store the cached
values) and some extra information about the arguments and how old the
data is and things like that.  Let us call this object `C'.</p>
<p>When Memoize needs to check to see if an entry is in the cache
already, it will invoke <a href="#item_exists"><code>C-&gt;EXISTS(key)</code></a>.  <code>key</code> is the normalized
function argument.  MyExpirePolicy::EXISTS should return 0 if the key
is not in the cache, or if it has expired, and 1 if an unexpired value
is in the cache.  It should <em>not</em> return <a href="../../lib/Pod/perlfunc.html#item_undef"><code>undef</code></a>, because there is a
bug in some versions of Perl that will cause a spurious FETCH if the
EXISTS method returns <a href="../../lib/Pod/perlfunc.html#item_undef"><code>undef</code></a>.</p>
<p>If your EXISTS function returns true, Memoize will try to fetch the
cached value by invoking <a href="#item_fetch"><code>C-&gt;FETCH(key)</code></a>.  MyExpirePolicy::FETCH should
return the cached value.  Otherwise, Memoize will call the memoized
function to compute the appropriate value, and will store it into the
cache by calling <a href="#item_store"><code>C-&gt;STORE(key, value)</code></a>.</p>
<p>Here is a very brief example of a policy module that expires each
cache item after ten seconds.</p>
<pre>
        <span class="keyword">package</span> <span class="variable">Memoize::TenSecondExpire</span><span class="operator">;</span>
</pre>
<pre>
        <span class="keyword">sub</span><span class="variable"> TIEHASH </span><span class="operator">{</span>
          <span class="keyword">my</span> <span class="operator">(</span><span class="variable">$package</span><span class="operator">,</span> <span class="variable">%args</span><span class="operator">)</span> <span class="operator">=</span> <span class="variable">@_</span><span class="operator">;</span>
          <span class="keyword">my</span> <span class="variable">$cache</span> <span class="operator">=</span> <span class="variable">$args</span><span class="operator">{</span><span class="string">HASH</span><span class="operator">}</span> <span class="operator">||</span> <span class="operator">{}</span><span class="operator">;</span>
          <span class="keyword">bless</span> <span class="variable">$cache</span> <span class="operator">=&gt;</span> <span class="variable">$package</span><span class="operator">;</span>
        <span class="operator">}</span>
</pre>
<pre>
        <span class="keyword">sub</span><span class="variable"> EXISTS </span><span class="operator">{</span>
          <span class="keyword">my</span> <span class="operator">(</span><span class="variable">$cache</span><span class="operator">,</span> <span class="variable">$key</span><span class="operator">)</span> <span class="operator">=</span> <span class="variable">@_</span><span class="operator">;</span>
          <span class="keyword">if</span> <span class="operator">(</span><span class="keyword">exists</span> <span class="variable">$cache</span><span class="operator">-&gt;</span><span class="operator">{</span><span class="variable">$key</span><span class="operator">}</span> <span class="operator">&amp;&amp;</span> 
              <span class="variable">$cache</span><span class="operator">-&gt;</span><span class="operator">{</span><span class="variable">$key</span><span class="operator">}{</span><span class="string">EXPIRE_TIME</span><span class="operator">}</span> <span class="operator">&gt;</span> <span class="keyword">time</span><span class="operator">)</span> <span class="operator">{</span>
            <span class="keyword">return</span> <span class="number">1</span>
          <span class="operator">}</span> <span class="keyword">else</span> <span class="operator">{</span>
            <span class="keyword">return</span> <span class="number">0</span><span class="operator">;</span>  <span class="comment"># Do NOT return `undef' here.</span>
          <span class="operator">}</span>
        <span class="operator">}</span>
</pre>
<pre>
        <span class="keyword">sub</span><span class="variable"> FETCH </span><span class="operator">{</span>
          <span class="keyword">my</span> <span class="operator">(</span><span class="variable">$cache</span><span class="operator">,</span> <span class="variable">$key</span><span class="operator">)</span> <span class="operator">=</span> <span class="variable">@_</span><span class="operator">;</span>
          <span class="keyword">return</span> <span class="variable">$cache</span><span class="operator">-&gt;</span><span class="operator">{</span><span class="variable">$key</span><span class="operator">}{</span><span class="string">VALUE</span><span class="operator">}</span><span class="operator">;</span>
        <span class="operator">}</span>
</pre>
<pre>
        <span class="keyword">sub</span><span class="variable"> STORE </span><span class="operator">{</span>
          <span class="keyword">my</span> <span class="operator">(</span><span class="variable">$cache</span><span class="operator">,</span> <span class="variable">$key</span><span class="operator">,</span> <span class="variable">$newvalue</span><span class="operator">)</span> <span class="operator">=</span> <span class="variable">@_</span><span class="operator">;</span>
          <span class="variable">$cache</span><span class="operator">-&gt;</span><span class="operator">{</span><span class="variable">$key</span><span class="operator">}{</span><span class="string">VALUE</span><span class="operator">}</span> <span class="operator">=</span> <span class="variable">$newvalue</span><span class="operator">;</span>
          <span class="variable">$cache</span><span class="operator">-&gt;</span><span class="operator">{</span><span class="variable">$key</span><span class="operator">}{</span><span class="string">EXPIRE_TIME</span><span class="operator">}</span> <span class="operator">=</span> <span class="keyword">time</span> <span class="operator">+</span> <span class="number">10</span><span class="operator">;</span>
        <span class="operator">}</span>
</pre>
<p>To use this expiration policy, the user would say</p>
<pre>
        <span class="keyword">use</span> <span class="variable">Memoize</span><span class="operator">;</span>
        <span class="keyword">tie</span> <span class="keyword">my</span> <span class="variable">%cache10sec</span> <span class="operator">=&gt;</span> <span class="string">'Memoize::TenSecondExpire'</span><span class="operator">;</span>
        <span class="variable">memoize</span> <span class="string">'function'</span><span class="operator">,</span> <span class="string">SCALAR_CACHE</span> <span class="operator">=&gt;</span> <span class="operator">[</span><span class="string">HASH</span> <span class="operator">=&gt;</span> <span class="operator">\</span><span class="variable">%cache10sec</span><span class="operator">]</span><span class="operator">;</span>
</pre>
<p>Memoize would then call <code>function</code> whenever a cached value was
entirely absent or was older than ten seconds.</p>
<p>You should always support a <code>HASH</code> argument to <a href="#item_tiehash"><code>TIEHASH</code></a> that ties
the underlying cache so that the user can specify that the cache is
also persistent or that it has some other interesting semantics.  The
example above demonstrates how to do this, as does <code>Memoize::Expire</code>.</p>
<p>
</p>
<hr />
<h1><a name="alternatives">ALTERNATIVES</a></h1>
<p>Brent Powers has a <code>Memoize::ExpireLRU</code> module that was designed to
work with Memoize and provides expiration of least-recently-used data.
The cache is held at a fixed number of entries, and when new data
comes in, the least-recently used data is expired.  See
<a href="http://search.cpan.org/search?mode=module&query=ExpireLRU">http://search.cpan.org/search</a>.</p>
<p>Joshua Chamas's Tie::Cache module may be useful as an expiration
manager.  (If you try this, let me know how it works out.)</p>
<p>If you develop any useful expiration managers that you think should be
distributed with Memoize, please let me know.</p>
<p>
</p>
<hr />
<h1><a name="caveats">CAVEATS</a></h1>
<p>This module is experimental, and may contain bugs.  Please report bugs
to the address below.</p>
<p>Number-of-uses is stored as a 16-bit unsigned integer, so can't exceed
65535.</p>
<p>Because of clock granularity, expiration times may occur up to one
second sooner than you expect.  For example, suppose you store a value
with a lifetime of ten seconds, and you store it at 12:00:00.998 on a
certain day.  Memoize will look at the clock and see 12:00:00.  Then
9.01 seconds later, at 12:00:10.008 you try to read it back.  Memoize
will look at the clock and see 12:00:10 and conclude that the value
has expired.  This will probably not occur if you have
<code>Time::HiRes</code> installed.</p>
<p>
</p>
<hr />
<h1><a name="author">AUTHOR</a></h1>
<p>Mark-Jason Dominus (mjd-perl-memoize+@plover.com)</p>
<p>Mike Cariaso provided valuable insight into the best way to solve this
problem.</p>
<p>
</p>
<hr />
<h1><a name="see_also">SEE ALSO</a></h1>
<p><code>perl(1)</code></p>
<p>The Memoize man page.</p>
<p><a href="http://www.plover.com/~mjd/perl/Memoize/">http://www.plover.com/~mjd/perl/Memoize/</a>  (for news and updates)</p>
<p>I maintain a mailing list on which I occasionally announce new
versions of Memoize.  The list is for announcements only, not
discussion.  To join, send an empty message to
<a href="mailto:mjd-perl-memoize-request@Plover.com.">mjd-perl-memoize-request@Plover.com.</a></p>

</body>

</html>

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?