public static int getOrAddColorIndex(final @NotNull UserDataHolderEx context,
                                       final @NotNull String name,
                                       int colorsCount) {
    int colorIndex;
    while (true) {
      Object data = context.getUserData(USED_COLOR);
      Object newColors;
      if (data == null) {
        colorIndex = hashColor(name, colorsCount);
        newColors = new UsedColor(name, colorIndex); // put an object instead of array to save space
      }
      else if (data instanceof UsedColor usedColor) {
        if (usedColor.name.equals(name)) {
          colorIndex = usedColor.index;
          newColors = null; // found, no need to create new
        }
        else {
          int hashedIndex = hashColor(name, colorsCount);
          if (hashedIndex == usedColor.index) hashedIndex = (hashedIndex + 1) % colorsCount;
          colorIndex = hashedIndex;
          UsedColor newColor = new UsedColor(name, colorIndex);
          newColors = new UsedColor[]{usedColor, newColor};
        }
      }
      else {
        colorIndex = -1;
        int hashedIndex = hashColor(name, colorsCount);
        int[] index2usage = new int[colorsCount];
        UsedColor[] usedColors = (UsedColor[])data;
        for (UsedColor usedColor : usedColors) {
          int index = usedColor.index;
          index2usage[index]++;
          if (usedColor.name.equals(name)) {
            colorIndex = index;
            break;
          }
        }
        if (colorIndex == -1) {
          int minIndex1 = indexOfMin(index2usage, hashedIndex, colorsCount);
          int minIndex2 = indexOfMin(index2usage, 0, hashedIndex);
          colorIndex = index2usage[minIndex1] <= index2usage[minIndex2] ? minIndex1 : minIndex2;
          UsedColor newColor = new UsedColor(name, colorIndex);
          newColors = ArrayUtil.append(usedColors, newColor);
        }
        else {
          newColors = null;
        }
      }
      if (newColors == null || context.replace(USED_COLOR, data, newColors)) {
        break;
      }
    }

    return colorIndex;
  }
public static int getOrAddColorIndex(final @NotNull UserDataHolderEx context,
                                       final @NotNull String name,
                                       int colorsCount)