[concurrency-interest] Adding a createIfAbsent() API?

Joe Bowbeer joe.bowbeer at gmail.com
Tue Aug 14 03:02:22 EDT 2007


On 8/13/07, Neal Gafter wrote:
> On 8/13/07, Doug Lea wrote:
> > It's about time to recycle this (that I first posted May 15, 2006):
>
> From an API point of view (i.e. the user of the API), the callback approach
> is, in my opinion, a much neater solution to the problem. A few details make
> it unappealing - for example the ExecutionException instead of Java's
> ordinary exception checking (whatever the passed code can actually throw
> should be known by the compiler to be thrown by the invocation of
> createIfAbsent). My hope is that closures would make this approach more
> appealing. However, this kind of API may be inappropriate for a concurrent
> map unless the implementation is sometimes allowed to invoke the callable
> and then discard the value (Doug's solution 1a). If the map is implemented
> using locking, the lock must be held for an arbitrarily long time while the
> callable is invoked. It may be very difficult to implement in a wait-free
> map.
>

It just occurred to me that createIfAbsent, if it were to exist,
should probably return the current mapping rather than the previous
one.  That way it will return the newly constructed value when it is
used.  This is the opposite of putIfAbsent.

1a. If the createIfAbsent implementation doesn't use locking, I assume
it must be allowed to throw away the constructed value:

  if (!containsKey(key))
    putIfAbsent(key, callable.call());
  return get(key);

1b. However, if the value is expensive to create, then some kind of
cleanup is more likely to be needed when it is discarded:

  V val = get(key);
  if (val == null) {
    V next = callable.call();
    val = putIfAbsent(key, next);
    if (val == null)
      val = next;
    else
      next.dispose();
  }
  return val;

--Joe


More information about the Concurrency-interest mailing list