[concurrency-interest] memoizer cache

Christian Vest Hansen karmazilla at gmail.com
Fri Oct 21 12:11:58 EDT 2011


One thing that comes to mind is this:
If you determine that the value you are about to return has expired, then
you could replace(key, entry, null) and recursively call get(key) again. If
the replace() call returns `false` then someone got ahead of you and already
put a null or a new CountDownLatch in there, and the get() call will deal
with it. Otherwise it will look, to the following get() call, as if the
entry never existed and get() will create it for you. So you don't really
need to check the return value of replace() with this approach.
If you do it this way then I guess you don't need the Entry class either. As
far as my quick glancing can tell.

On Fri, Oct 21, 2011 at 16:39, bhm <bheem at sbcglobal.net> wrote:

> I'm trying to build a cache for configuration objects for my projects-
> Requirements:
>  1 only one instance per key should be created, either because its absent
>   for a given key or its expired (in that case it will be recreated).
>  2 most common path asking for a value for a key should not block or
> synchronize.
>  3 when a value doesnt exists for a key, one thread should create the
> instance
>   of value and put in the cache, other threads asking for same key should
> wait
>   till thats complete.
>  4 if a value is expired, one thread should (re)create the instance of
> value
>   and other threads asking for same key (when one thread is recreating it)
>   should use expired instance of value and should not block.
>
> My code is largely derived from Christian's reply
>
> http://cs.oswego.edu/pipermail/concurrency-interest/2010-November/007469.html
>
> Please comment or suggest on following, Thanks for you help.
>
>    final ConcurrentMap<K, Object> store = new ConcurrentHashMap<K,
> Object>();
>
>    V get(K key) {
>        Object ret = store.get(key);
>
>        if (ret == null) {
>            CountDownLatch latch = new CountDownLatch(1);
>            ret = store.putIfAbsent(key, latch);
>            if (null == ret) {
>                ret = new Entry<V>(factory.create(key));
>                store.replace(key, ret);
>                latch.countDown();
>            }
>        }
>
>        if (ret instanceof CountDownLatch) {
>            try {((CountDownLatch) ret).await();} // till new value is
> created
>            catch (InterruptedException e) {throw new RuntimeException(e);}
>            ret = store.get(key); // get new value
>        } else {
>            Entry<V> entry = (Entry<V>) ret;
>
>            if (evictionpolicy != null && evictionpolicy.isExpired(entry.v))
> {
>                final AtomicInteger sync = entry.sync;
>
>                if (sync.compareAndSet(0, 1)) { // otherwise retrun old
> value
>                    try {
>                        entry = (Entry<V>) store.get(key); // get again
>                        if (evictionpolicy.isExpired(entry.v)) { //
> double-check
>                            Entry<V> newval = new
> Entry<V>(factory.create(key));
>                            store.replace(key, newval);
>                            ret = newval;
>                        }
>                    }
>                    catch (Throwable catchall) {
>                      catchall.printStackTrace(System.err);//return old
> value
>                    }
>                    finally {sync.set(0);/*unlock*/}
>                }
>            }
>        }
>
>        return ((Entry<V>) ret).v;
>    }
>
>    class Entry<V> {
>        final AtomicInteger sync = new AtomicInteger(0);
>        final V v;
>        Entry(V v) {this.v=v;}
>    }
>
>
> form other discussions about similar topics in the list, I understand there
> are
> libraries to do that (MapMaker etc.), I wanted something specific, small,
> just
> to slove the given problem and avoid generalization.
> I couldnt get jcp's Memoizer to work when cache entries could expire. Its
> good
> for lazy one time load.
>
> Thanks again.
> _______________________________________________
> Concurrency-interest mailing list
> Concurrency-interest at cs.oswego.edu
> http://cs.oswego.edu/mailman/listinfo/concurrency-interest
>



-- 
Venlig hilsen / Kind regards,
Christian Vest Hansen.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://cs.oswego.edu/pipermail/concurrency-interest/attachments/20111021/a2003430/attachment.html>


More information about the Concurrency-interest mailing list