T (@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; }