FileDocCategorySizeDatePackage
LinkList.javaAPI DocExample2929Wed May 05 10:51:16 BST 2004com.oreilly.tiger.ch10

LinkList

public class LinkList extends Object

Fields Summary
E
value
LinkList
rest
Lock
lock
Condition
valueChanged
Condition
linkChanged
Constructors Summary
public LinkList(E value)

    this.value = value;
    rest = null;
    lock = new ReentrantLock();
    valueChanged = lock.newCondition();
    linkChanged = lock.newCondition();
  
Methods Summary
public voidappend(E value)

    // Start the pointer at this node
    LinkList<E> node = this;
    node.lock.lock();

    while (node.rest != null) {
      LinkList<E> next = node.rest;

      // Here's the hand-over-hand locking
      try {
        // Lock the next node
        next.lock.lock();
      } finally {
        // unlock the current node
        node.lock.unlock();
      }

      // Traverse
      node = next;      
    }

    // We're at the final node, so append and then unlock
    try {
      node.rest = new LinkList<E>(value);

      // Let any waiting threads know that this node's link has changed
      node.linkChanged.signalAll();
    } finally {
      node.lock.unlock();
    }
  
public voidexecuteOnValue(E desiredValue, java.lang.Runnable task)

 
    lock.lock();
    try {
      // Checks the value against the desired value
      while (!value.equals(desiredValue)) {
        // This will wait until the value changes
        valueChanged.await();
      }

      // When we get here, the value is correct -- Run the task
      task.run();
    } finally {
      lock.unlock();
    }
  
public voidprintUntilInterrupted(java.lang.String prefix)

    // Start the pointer at this node
    LinkList<E> node = this;
    node.lock.lock();

    while (true) {
      LinkList<E> next;
      try {
        System.out.println(prefix + ": " + node.value);

        // Wait for the next node if not available
        while (node.rest == null) {
          node.linkChanged.await();
        }

        // Get the next node
        next = node.rest;

        // Lock it - more hand-to-hand locking
        next.lock.lock();
      } catch (InterruptedException e) {
        // reset the interrupt status
        Thread.currentThread().interrupt();
        return;
      } finally {
        node.lock.unlock();
      }

      // Traverse
      node = next;
    }
  
public voidsetValue(E value)

    lock.lock();
    try {
      this.value = value;

      // Let waiting threads that the value has changed
      valueChanged.signalAll();
    } finally {
      lock.unlock();
    }