[concurrency-interest] ConcurrentMap putIfPresent

Eric Zoerner eric.zoerner@gemstone.com
Fri, 21 Nov 2003 15:48:12 -0800

In addition to:
V putIfPresent(K key, V value);

Another variation on putIfPresent comes up analogous to
ConcurrentMap.remove(Object, Object);

Say you do a get on a ConcurrentMap and do some computation based on that
value and then you want to replace the value with a new value, but only if
the old value hasn't changed in the meantime. You would want a method such

/** Associate key with the given value only if currently mapped to the
expectedValue */
boolean putIfPresent(K key, V value, V expectedValue);

Why is it
boolean remove(Object key, Object value);
...and not...
boolean remove(K key, V value);

----- Original Message -----
From: "Eric Zoerner" <eric.zoerner@gemstone.com>
To: "Doug Lea" <dl@altair.cs.oswego.edu>
Cc: <concurrency-interest@altair.cs.oswego.edu>
Sent: Friday, November 21, 2003 13:26
Subject: Re: [concurrency-interest] Bug in ConcurrentHashMap

> It is fine to add that test case to the tests, but keep in mind that it is
> dependent on the sizing and hash algorithms that are currently used in the
> in order to get a reference to an entry that would be cloned.
> Also, it was not strictly necessary to remove the key from a separate
thread, of
> course, but I wanted it to reflect a more believable scenario.
> Use cases for putIfPresent come up when the existence of a key in the map
> significance beyond what the value associated with the key is. One such
use case
>   is when the map is used for caching data from a relational database and
> presence of the key in the map may provide a hint that the corresponding
> exists in the database*, or it may provide the ability to enumerate the
names of
> all known documents, etc., without necessarily having the value in the map
> the moment. To free up memory in the cache you may want to replace the
value in
> the map with a placeholder indicating that the value is now invalid and
needs to
> be retrieved from the database again the next time it is requested (let's
> the placeholder object INVALID). However, you don't want  to lose the
> information that the key exists. So you want to put(key, INVALID). But
> should not create a new key in the map if that key was just legitimately
> from the map (and the database, e.g. by another thread). So in this case
> would want call putIfPresent(key, INVALID). I'm sure there are other ways
> implementing this use case, but this is a case where a putIfPresent method
> indeed be useful.
> I have other, more complicated use cases where putIfPresent would be
useful, but
> hopefully this simple one suffices to make the point.
> Thanks for fixing the setValue bug so quickly, by the way!
> - Eric
> * The presence of the key might provide a hint as to whether a CREATE or
> is necessary when synchonizing with a RDBMS
> Doug Lea wrote:
> > A better way to do this was to apply the tactics we used in
> > IdentityHashMap of making EntrySet entries mere forwarders (but still
> > more efficiently handling the more common keySet and Values
> > iterators).  As is now checked in.
> >
> > Eric: Is it OK fow us to add your test case to JSR166 tests?
> >
> > I didn't answer before:
> >
> >
> >>Which leads me to another comment. It would be useful to have a
> >>method on ConcurrentMap in addition to the putIfAbsent that is already
> >>for the case where you require the entry to already exist when replacing
> >>value.
> >
> >
> > Can you give a good use case? I can't think of any.
> >
> > -Doug
> _______________________________________________
> Concurrency-interest mailing list
> Concurrency-interest@altair.cs.oswego.edu
> http://altair.cs.oswego.edu/mailman/listinfo/concurrency-interest