xtends Throwable> T runUnderAllLocksAcquired(@NotNull ThrowableComputable<T, E> lambda,
                                                             @NotNull VirtualDirectoryImpl dir1,
                                                             @NotNull VirtualDirectoryImpl dir2) throws E {
    Object lock1 = dir1.myData;
    Object lock2 = dir2.myData;
    //order locks acquisition by their identity hash code:
    if (System.identityHashCode(lock1) <= System.identityHashCode(lock2)) {
      synchronized (lock1) {
        synchronized (lock2) {
          return lambda.compute();
        }
      }
    }
    else {
      synchronized (lock2) {
        synchronized (lock1) {
          return lambda.compute();
        }
      }
    }
  }

  /**
   * I
xtends Throwable> T runUnderAllLocksAcquired(@NotNull ThrowableComputable<T, E> lambda,
                                                             @NotNull VirtualDirectoryImpl dir1,
                                                             @NotNull VirtualDirectoryImpl dir2) throws E {
  