public <T> void putUserData(@NotNull Key<T> key, @Nullable T value) { while (true) { try { if (value == null) { ConcurrentMap<Key, Object> map = myUserMap; if (map == null) break; @SuppressWarnings("unchecked") T previous = (T) map.remove(key); boolean removed = previous != null; if (removed) { nullifyMapFieldIfEmpty(); } } else { getOrCreateMap().put(key, value); } break; } catch (ConcurrentModificationException ignored) { } } }
public <T> boolean replace(@NotNull Key<T> key, @Nullable T oldValue, @Nullable T newValue) { while (true) { try { ConcurrentMap<Key, Object> map = getOrCreateMap(); if (oldValue == null) { return newValue == null || map.putIfAbsent(key, newValue) == null; } if (newValue == null) { boolean removed = map.remove(key, oldValue); if (removed) { nullifyMapFieldIfEmpty(); } return removed; } return map.replace(key, oldValue, newValue); } catch (ConcurrentModificationException ignored) { // someone blocked modification, retry } } }