src/main/java/com/stoyanr/evictor/map/ConcurrentMapWithTimedEvictionDecorator.java
/**
     * If the specified key is not already associated with a value, associate it
     * with the given value for the specified duration. This is equivalent to
     * 
     * <pre>
     * if (!map.containsKey(key))
     *     return map.put(key, value, evictMs);
     * else
     *     return map.get(key);
     * </pre>
     * 
     * except that the action is performed atomically.
     * 
     * @param key
     *            key with which the specified value is to be associated
     * 
     * @param value
     *            value to be associated with the specified key
     * 
     * @param evictMs
     *            the time in ms during which the entry can stay in the map
     *            (time-to-live). When this time has elapsed, the entry will be
     *            evicted from the map automatically. A value of 0 for this
     *            argument means "forever", i.e.
     *            <tt>putIfAbsent(key, value, 0)</tt> is equivalent to
     *            <tt>putIfAbsent(key, value)</tt>.
     * 
     * @return the previous value associated with the specified key, or
     *         <tt>null</tt> if there was no mapping for the key. (A
     *         <tt>null</tt> return can also indicate that the map previously
     *         associated <tt>null</tt> with the key, if the implementation
     *         supports null values.)
     * 
     * @throws UnsupportedOperationException
     *             if the <tt>put</tt> operation is not supported by the
     *             delegate map
     * 
     * @throws ClassCastException
     *             if the class of the specified key or value prevents it from
     *             being stored in this map
     * 
     * @throws NullPointerException
     *             if the specified key is null and the delegate map does not
     *             permit null keys, or if the specified value is null
     * 
     * @throws IllegalArgumentException
     *             if some property of the specified key or value prevents it
     *             from being stored in this map, or if evictMs is negative
     */
If the specified key is not already associated with a value, associate it
with the given value for the specified duration. This is equivalent to



except that the action is performed atomically.

@param key
key with which the specified value is to be associated

@param value
value to be associated with the specified key

@param evictMs
the time in ms during which the entry can stay in the map
(time-to-live). When this time has elapsed, the entry will be
evicted from the map automatically. A value of 0 for this
argument means "forever", i.e.

@return the previous value associated with the specified key, or
null if there was no mapping for the key. (A
null return can also indicate that the map previously
associated null with the key, if the implementation
supports null values.)

@throws UnsupportedOperationException
if the put operation is not supported by the
delegate map

@throws ClassCastException
if the class of the specified key or value prevents it from
being stored in this map

@throws NullPointerException
if the specified key is null and the delegate map does not
permit null keys, or if the specified value is null

@throws IllegalArgumentException
if some property of the specified key or value prevents it
from being stored in this map, or if evictMs is negative
If the specified key is not already associated with a value associate it with the given value for the specified duration . This is equivalent to except that the action is performed atomically . @param key key with which the specified value is to be associated @param value value to be associated with the specified key @param evictMs the time in ms during which the entry can stay in the map ( time - to - live ) . When this time has elapsed the entry will be evicted from the map automatically . A value of 0 for this argument means " forever " i . e . @return the previous value associated with the specified key or null if there was no mapping for the key . ( A null return can also indicate that the map previously associated null with the key if the implementation supports null values . ) @throws UnsupportedOperationException if the put operation is not supported by the delegate map @throws ClassCastException if the class of the specified key or value prevents it from being stored in this map @throws NullPointerException if the specified key is null and the delegate map does not permit null keys or if the specified value is null @throws IllegalArgumentException if some property of the specified key or value prevents it from being stored in this map or if evictMs is negative
@Override
    public V putIfAbsent(K key, V value, long evictMs) {
        while (true) {
            EvictibleEntry<K, V> e = new EvictibleEntry<K, V>(this, key, value, evictMs);
            EvictibleEntry<K, V> oe = this.delegate.putIfAbsent(key, e);
            if (oe == null) {
                scheduleEviction(e);
                return null;
            }
            if (evictIfExpired(oe)) {
                continue;
            }
            return oe.getValue();
        }
    }
@ Override public V putIfAbsent ( K key , V value , long evictMs ) { while ( true ) { EvictibleEntry < K , V > e = new EvictibleEntry < K , V > ( this , key , value , evictMs ) ; EvictibleEntry < K , V > oe = this . delegate . putIfAbsent ( key , e ) ; if ( oe == null ) { scheduleEviction ( e ) ; return null ; } if ( evictIfExpired ( oe ) ) { continue ; } return oe . getValue ( ) ; } }
If the specified key is not already associated with a value, associate it
 with the given value for the specified duration.
If the specified key is not already associated with a value associate it with the given value for the specified duration .
// An entry is being added, schedule its automatic eviction