@NotNull
  public T getValue(@NotNull final TypeEvalContext context) {

    // map is thread safe but not atomic nor getValue() is, so in worst case several threads may produce same result
    // myProvider.fun should never be launched under lock to prevent deadlocks like PY-24300 and PY-24625
    // both explicit locking and computeIfAbsent leads to deadlock
    final ConcurrentMap<TypeEvalConstraints, T> map = myCachedMapStorage.getValue();
    final TypeEvalConstraints key = context.getConstraints();
    final T value = map.get(key);
    if (value != null) {
      return value;
    }
    final T newValue = myProvider.fun(context);
    T oldValue =
      map.putIfAbsent(key, newValue);// ConcurrentMap guarantees happens-before so from this moment get() should work in other threads
    return oldValue == null ? newValue : oldValue;
  }
@NotNull
  public T getValue(@NotNull final TypeEvalContext context)