code: @Override
      public O compute(final I arg) throws InterruptedException {
          while (true) {
              Future<O> future = cache.get(arg);
              if (future == null) {
                  final Callable<O> eval = new Callable<O>() {
  
                      @Override
                      public O call() throws InterruptedException {
                          return computable.compute(arg);
                      }
                  };
                  final FutureTask<O> futureTask = new FutureTask<>(eval);
                  future = cache.putIfAbsent(arg, futureTask);
                  if (future == null) {
                      future = futureTask;
                      futureTask.run();
                  }
              }
              try {
                  return future.get();
              } catch (final CancellationException e) {
                  cache.remove(arg, future);
              } catch (final ExecutionException e) {
                  if (recalculate) {
                      cache.remove(arg, future);
                  }
  
                  throw launderException(e.getCause());
              }
          }
      }
docs: <p>
  This method will return the result of the calculation and cache it, if it
  has not previously been calculated.
  </p>
  <p>
  This cache will also cache exceptions that occur during the computation
  if the {@code recalculate} parameter is the constructor was set to
  {@code false}, or not set. Otherwise, if an exception happened on the
  previous calculation, the method will attempt again to generate a value.
  </p>
  
  @param arg
  the argument for the calculation
  @return the result of the calculation
  @throws InterruptedException
  thrown if the calculation is interrupted