Ejemplo n.º 1
0
  /**
   * Gets the sequence number associated with a block location.<br>
   * <br>
   * If soft is true, this method counts as a volatile read. Otherwise, it is both a volatile read
   * and a volatile write.<br>
   * <br>
   * Soft reads should only be used for the first of the 2 step process for confirming that data
   * hasn't changed.
   *
   * @param x the x coordinate
   * @param y the y coordinate
   * @param z the z coordinate
   * @return the sequence number, or DatatableSequenceNumber.ATOMIC for a single short record
   */
  public final int getSequence(int x, int y, int z) {
    checkCompressing();
    int index = getIndex(x, y, z);
    int spins = 0;
    boolean interrupted = false;
    try {
      while (true) {
        if (spins++ > SPINS) {
          interrupted |= atomicWait();
        }
        checkCompressing();

        int blockId = blockIds.get(index);
        if (!auxStore.isReserved(blockId)) {
          return DatatableSequenceNumber.ATOMIC;
        } else {
          int sequence = auxStore.getSequence(blockId);
          if (sequence != DatatableSequenceNumber.UNSTABLE) {
            return sequence;
          }
        }
      }
    } finally {
      if (interrupted) {
        Thread.currentThread().interrupt();
      }
    }
  }
Ejemplo n.º 2
0
  /**
   * Sets the block id, data and auxData for the block at (x, y, z), if the current data matches the
   * expected data.<br>
   *
   * @param x the x coordinate
   * @param y the y coordinate
   * @param z the z coordinate
   * @param expectId the expected block id
   * @param expectData the expected block data
   * @param expectAuxData the expected block auxiliary data
   * @param newId the new block id
   * @param newData the new block data
   * @param newAuxData the new block auxiliary data
   * @return true if the block was set
   */
  public final boolean compareAndSetBlock(
      int x,
      int y,
      int z,
      short expectId,
      short expectData,
      T expectAuxData,
      short newId,
      short newData,
      T newAuxData) {
    int index = getIndex(x, y, z);
    int spins = 0;
    boolean interrupted = false;
    try {
      while (true) {
        if (spins++ > SPINS) {
          interrupted |= atomicWait();
        }
        checkCompressing();

        short oldBlockId = blockIds.get(index);
        boolean oldReserved = auxStore.isReserved(oldBlockId);

        if (!oldReserved) {
          if (blockIds.get(index) != expectId || expectData != 0 || expectAuxData != null) {
            return false;
          }
        } else {
          int seq = auxStore.getSequence(oldBlockId);
          short oldId = auxStore.getId(oldBlockId);
          short oldData = auxStore.getData(oldBlockId);
          T oldAuxData = auxStore.getAuxData(oldBlockId);
          if (!testSequence(x, y, z, seq)) {
            continue;
          }
          if (oldId != expectId || oldData != expectData || oldAuxData != expectAuxData) {
            return false;
          }
        }

        if (newData == 0 && newAuxData == null && !auxStore.isReserved(newId)) {
          if (!blockIds.compareAndSet(index, oldBlockId, newId)) {
            continue;
          }
          if (oldReserved) {
            if (!auxStore.remove(oldBlockId)) {
              throw new IllegalStateException(
                  "setBlock() tried to remove old record, but it had already been removed");
            }
          }
          markDirty(x, y, z);
          return true;
        } else {
          int newIndex = auxStore.add(newId, newData, newAuxData);
          if (!blockIds.compareAndSet(index, oldBlockId, (short) newIndex)) {
            if (!auxStore.remove(newIndex)) {
              throw new IllegalStateException(
                  "setBlock() tried to remove old record, but it had already been removed");
            }
            continue;
          }
          if (oldReserved) {
            if (!auxStore.remove(oldBlockId)) {
              throw new IllegalStateException(
                  "setBlock() tried to remove old record, but it had already been removed");
            }
          }
          markDirty(x, y, z);
          return true;
        }
      }
    } finally {
      atomicNotify();
      if (interrupted) {
        Thread.currentThread().interrupt();
      }
    }
  }