protected float create(double key) {
   long start = System.nanoTime();
   float t = calculatable.calculate(owner, key);
   long end = System.nanoTime();
   miss(end - start);
   save(key, t);
   return t;
 }
  @Override
  public float getOrCreate(double o) {
    if (DependencyTracker.isBypassCaches()) {
      return calculatable.calculate(owner, o);
    } else {
      lock(o);
      try {
        if (isCalculated(o)) {
          DependencyTracker.mark(getDependencyNode());
          hit();
          return load(o);
        }

        DependencyNode callerNode = DependencyTracker.track(getDependencyNode());
        try {
          while (true) {
            try {
              return create(o);
            } catch (ResourceOccupied e) {
              if (callerNode != null) {
                throw e;
              } else {
                unlock(o);
                try {
                  e.getResource().waitForEndOfModification();
                } finally {
                  lock(o);
                }
                if (isCalculated(o)) {
                  hit();
                  return load(o);
                }
              }
            }
          }
        } finally {
          DependencyTracker.exit(callerNode);
        }
      } finally {
        unlock(o);
      }
    }
  }
 @Override
 public CacheDescriptor getDescriptor() {
   CacheId id = CalculatableHelper.getId(calculatable.getClass());
   return CacheFactory.getProvider().getDescriptor(id);
 }