[concurrency-interest] How to implement a self populating memoizer cache?

Charles Fry fry at google.com
Wed Nov 3 16:59:23 EDT 2010


It looks like you're looking at an old version of MapMaker. Check out the
version in the guava project:


http://code.google.com/p/guava-libraries/source/browse/trunk/src/com/google/common/collect/ComputingConcurrentHashMap.java#76

Charles

On Wed, Nov 3, 2010 at 16:47, Nader Aeinehchi <nader at aeinehchi.com> wrote:

>  Dear Kevin,
>
> If I understand you correctly, MapMaker.ExpiringComputingMap (which I
> believe you are referring to) is thread safe.  Furthermore, it guarantees
> that threads will wait until the first thread computes for a given key.
>
> Following is an excerpt of MapMaker.ExpiringComputingMap.  Here, if the
> result is null, the compute method is called and the calculated value is
> put.  How is it guaranteed that another thread does not concurrently perform
> the latter (calculation and put operations)?  Is not this a
> read-modify-write scheme which according to JCiP book is a compound (not
> atomic) operation?
>
>
> In advance, thank you very much.
>
>
>     @Override
>     public V get(Object k) {
>       // from CustomConcurrentHashMap
>       V result = super.get(k);
>       if (result == null && computer != null) {
>         /*
>          * This cast isn't safe, but we can rely on the fact that K is
> almost
>          * always passed to Map.get(), and tools like IDEs and Findbugs can
>          * catch situations where this isn't the case.
>          *
>          * The alternative is to add an overloaded method, but the chances
> of
>          * a user calling get() instead of the new API and the risks
> inherent
>          * in adding a new API outweigh this little hole.
>          */
>         @SuppressWarnings("unchecked")
>         K key = (K) k;
>         result = compute(key);
>       }
>       return result;
>     }
>
>     private V compute(K key) {
>       // from MapMaker
>       V value;
>       try {
>         value = computer.apply(key);
>       } catch (Throwable t) {
>         throw new ComputationException(t);
>       }
>
>       if (value == null) {
>         String message = computer + " returned null for key " + key + ".";
>         throw new NullPointerException(message);
>       }
>       put(key, value);
>       return value;
>
>     }
>
>
>
> On 11/03/2010 03:15 PM, Kevin Bourrillion wrote:
>
> On Wed, Nov 3, 2010 at 5:31 AM, Nader Aeinehchi <nader at aeinehchi.com>wrote:
>
>  1. Please forgive me for my ignorance, but ExpiringComputingMap does not
>> guarantee that a computable to be calculated only once for concurrent
>> threads?
>>
>
>  "Map.get(java.lang.Object)<http://java.sun.com/javase/6/docs/api/java/util/Map.html?is-external=true#get%28java.lang.Object%29>
>  either returns an already-computed value for the given key, atomically
> computes it using the supplied function, or, if another thread is currently
> computing the value for this key, simply waits for that thread to finish and
> returns its computed value. Note that the function may be executed
> concurrently by multiple threads, but only for distinct keys."
>
>
>  --
> Kevin Bourrillion @ Google
> http://guava-libraries.googlecode.com
>
>
> _______________________________________________
> Concurrency-interest mailing list
> Concurrency-interest at cs.oswego.edu
> http://cs.oswego.edu/mailman/listinfo/concurrency-interest
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://cs.oswego.edu/pipermail/concurrency-interest/attachments/20101103/f1c8fdfb/attachment.html>


More information about the Concurrency-interest mailing list