[concurrency-interest] memoizer cache

Christian Vest Hansen karmazilla at gmail.com
Fri Oct 21 12:18:43 EDT 2011


Oh, it seems I overlooked the requirement to not block other threads when a
value is being re-created.

On Fri, Oct 21, 2011 at 18:11, Christian Vest Hansen
<karmazilla at gmail.com>wrote:

>
> 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.
>



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


More information about the Concurrency-interest mailing list