[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
as:

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

Question:
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
very
> dependent on the sizing and hash algorithms that are currently used in the
map
> 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
has
> 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
the
> presence of the key in the map may provide a hint that the corresponding
row
> 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
at
> 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
call
> 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
this
> should not create a new key in the map if that key was just legitimately
removed
> from the map (and the database, e.g. by another thread). So in this case
you
> would want call putIfPresent(key, INVALID). I'm sure there are other ways
of
> implementing this use case, but this is a case where a putIfPresent method
would
> 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
UPDATE
> 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
"putIfPresent"
> >>method on ConcurrentMap in addition to the putIfAbsent that is already
there,
> >>for the case where you require the entry to already exist when replacing
a
> >>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
>