Example #1
0
  /**
   * Releases the write lock held by the provided tx. If it is null then an attempt to acquire the
   * current transaction from the transaction manager will be made. This is to make safe calling
   * this method as an <code>afterCompletion()</code> hook where the transaction context is not
   * necessarily available. If write count is zero and there are waiting transactions in the queue
   * they will be interrupted if they can acquire the lock.
   */
  synchronized void releaseWriteLock(Object tx) throws LockNotFoundException {
    TxLockElement tle = getLockElement(tx);

    if (tle.writeCount == 0) {
      throw new LockNotFoundException("" + tx + " don't have writeLock");
    }

    totalWriteCount--;
    tle.writeCount--;
    if (tle.isFree()) {
      txLockElementMap.remove(tx);
      ragManager.lockReleased(this, tx);
    }

    // the threads in the waitingList cannot be currentThread
    // so we only have to wake other elements if writeCount is down to zero
    // (that is: If writeCount > 0 a waiting thread in the queue cannot be
    // the thread that holds the write locks because then it would never
    // have been put into wait mode)
    if (totalWriteCount == 0 && waitingThreadList.size() > 0) {
      // wake elements in queue until a write lock is found or queue is
      // empty
      do {
        WaitElement we = waitingThreadList.removeLast();
        if (!we.element.movedOn) {
          we.waitingThread.interrupt();
          if (we.lockType == LockType.WRITE) {
            break;
          }
        }
      } while (waitingThreadList.size() > 0);
    }
  }
Example #2
0
  /**
   * Tries to acquire write lock for a given transaction. If <CODE>this.writeCount</CODE> is greater
   * than the currents tx's write count or the read count is greater than the currents tx's read
   * count the transaction has to wait and the {@link RagManager#checkWaitOn} method is invoked for
   * deadlock detection.
   *
   * <p>If the lock can be acquires the lock count is updated on <CODE>this</CODE> and the
   * transaction lock element (tle).
   *
   * @throws DeadlockDetectedException if a deadlock is detected
   */
  synchronized void acquireWriteLock(Object tx) throws DeadlockDetectedException {
    TxLockElement tle = getOrCreateLockElement(tx);

    try {
      tle.movedOn = false;

      boolean shouldAddWait = true;
      Thread currentThread = currentThread();

      while (totalWriteCount > tle.writeCount || totalReadCount > tle.readCount) {
        ragManager.checkWaitOn(this, tx);

        if (shouldAddWait) {
          waitingThreadList.addFirst(new WaitElement(tle, WRITE, currentThread));
        }

        try {
          wait();
          shouldAddWait = false;
        } catch (InterruptedException e) {
          interrupted();

          shouldAddWait = true;
        }
        ragManager.stopWaitOn(this, tx);
      }

      registerWriteLockAcquired(tx, tle);
    } finally {
      // if deadlocked, remove marking so lock is removed when empty
      tle.movedOn = true;
      marked--;
    }
  }
Example #3
0
  /**
   * Tries to acquire write lock for a given transaction. If <CODE>this.writeCount</CODE> is greater
   * than the currents tx's write count or the read count is greater than the currents tx's read
   * count the transaction has to wait and the {@link RagManager#checkWaitOn} method is invoked for
   * deadlock detection.
   *
   * <p>If the lock can be acquires the lock count is updated on <CODE>this</CODE> and the
   * transaction lock element (tle).
   *
   * @throws DeadlockDetectedException if a deadlock is detected
   */
  synchronized void acquireWriteLock(Object tx) throws DeadlockDetectedException {
    TxLockElement tle = getOrCreateLockElement(tx);

    try {
      tle.movedOn = false;
      while (totalWriteCount > tle.writeCount || totalReadCount > tle.readCount) {
        deadlockGuardedWait(tx, tle, WRITE);
      }

      registerWriteLockAcquired(tx, tle);
    } finally {
      // if deadlocked, remove marking so lock is removed when empty
      tle.movedOn = true;
      marked--;
    }
  }
Example #4
0
  synchronized boolean tryAcquireWriteLock(Object tx) {
    TxLockElement tle = getOrCreateLockElement(tx);

    try {
      tle.movedOn = false;
      if (totalWriteCount > tle.writeCount || totalReadCount > tle.readCount) {
        return false;
      }

      registerWriteLockAcquired(tx, tle);
      return true;
    } finally {
      // if deadlocked, remove marking so lock is removed when empty
      tle.movedOn = true;
      marked--;
    }
  }
Example #5
0
 private void registerLockAcquired(Object tx, TxLockElement tle) {
   if (tle.isFree()) {
     ragManager.lockAcquired(this, tx);
   }
 }
Example #6
0
  /**
   * Releases the read lock held by the provided transaction. If it is null then an attempt to
   * acquire the current transaction will be made. This is to make safe calling the method from the
   * context of an <code>afterCompletion()</code> hook where the tx is locally stored and not
   * necessarily available through the tm. If there are waiting transactions in the queue they will
   * be interrupted if they can acquire the lock.
   */
  synchronized void releaseReadLock(Object tx) throws LockNotFoundException {
    TxLockElement tle = getLockElement(tx);

    if (tle.readCount == 0) {
      throw new LockNotFoundException("" + tx + " don't have readLock");
    }

    totalReadCount--;
    tle.readCount--;
    if (tle.isFree()) {
      txLockElementMap.remove(tx);
      ragManager.lockReleased(this, tx);
    }
    if (waitingThreadList.size() > 0) {
      WaitElement we = waitingThreadList.getLast();

      if (we.lockType == LockType.WRITE) {
        // this one is tricky...
        // if readCount > 0 we either have to find a waiting read lock
        // in the queue or a waiting write lock that has all read
        // locks, if none of these are found it means that there
        // is a (are) thread(s) that will release read lock(s) in the
        // near future...
        if (totalReadCount == we.element.readCount) {
          // found a write lock with all read locks
          waitingThreadList.removeLast();
          if (!we.element.movedOn) {
            we.waitingThread.interrupt();
          }
        } else {
          ListIterator<WaitElement> listItr =
              waitingThreadList.listIterator(waitingThreadList.lastIndexOf(we));
          // hm am I doing the first all over again?
          // think I am if cursor is at lastIndex + 0.5 oh well...
          while (listItr.hasPrevious()) {
            we = listItr.previous();
            if (we.lockType == LockType.WRITE && totalReadCount == we.element.readCount) {
              // found a write lock with all read locks
              listItr.remove();
              if (!we.element.movedOn) {
                we.waitingThread.interrupt();
                // ----
                break;
              }
            } else if (we.lockType == LockType.READ) {
              // found a read lock, let it do the job...
              listItr.remove();
              if (!we.element.movedOn) {
                we.waitingThread.interrupt();
              }
            }
          }
        }
      } else {
        // some thread may have the write lock and released a read lock
        // if writeCount is down to zero we can interrupt the waiting
        // read lock
        if (totalWriteCount == 0) {
          waitingThreadList.removeLast();
          if (!we.element.movedOn) {
            we.waitingThread.interrupt();
          }
        }
      }
    }
  }