diff src/EDU/oswego/cs/dl/util/concurrent/Mutex.java @ 0:3dc0c5604566

Initial checkin of blitz 2.0 fcs - no installer yet.
author Dan Creswell <dan.creswell@gmail.com>
date Sat, 21 Mar 2009 11:00:06 +0000
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/EDU/oswego/cs/dl/util/concurrent/Mutex.java	Sat Mar 21 11:00:06 2009 +0000
@@ -0,0 +1,171 @@
+/*
+  File: Mutex.java
+
+  Originally written by Doug Lea and released into the public domain.
+  This may be used for any purposes whatsoever without acknowledgment.
+  Thanks for the assistance and support of Sun Microsystems Labs,
+  and everyone contributing, testing, and using this code.
+
+  History:
+  Date       Who                What
+  11Jun1998  dl               Create public version
+*/
+
+package EDU.oswego.cs.dl.util.concurrent;
+
+/**
+ * A simple non-reentrant mutual exclusion lock.
+ * The lock is free upon construction. Each acquire gets the
+ * lock, and each release frees it. Releasing a lock that
+ * is already free has no effect. 
+ * <p>
+ * This implementation makes no attempt to provide any fairness
+ * or ordering guarantees. If you need them, consider using one of
+ * the Semaphore implementations as a locking mechanism.
+ * <p>
+ * <b>Sample usage</b><br>
+ * <p>
+ * Mutex can be useful in constructions that cannot be
+ * expressed using java synchronized blocks because the
+ * acquire/release pairs do not occur in the same method or
+ * code block. For example, you can use them for hand-over-hand
+ * locking across the nodes of a linked list. This allows
+ * extremely fine-grained locking,  and so increases 
+ * potential concurrency, at the cost of additional complexity and
+ * overhead that would normally make this worthwhile only in cases of
+ * extreme contention.
+ * <pre>
+ * class Node { 
+ *   Object item; 
+ *   Node next; 
+ *   Mutex lock = new Mutex(); // each node keeps its own lock
+ *
+ *   Node(Object x, Node n) { item = x; next = n; }
+ * }
+ *
+ * class List {
+ *    protected Node head; // pointer to first node of list
+ *
+ *    // Use plain java synchronization to protect head field.
+ *    //  (We could instead use a Mutex here too but there is no
+ *    //  reason to do so.)
+ *    protected synchronized Node getHead() { return head; }
+ *
+ *    boolean search(Object x) throws InterruptedException {
+ *      Node p = getHead();
+ *      if (p == null) return false;
+ *
+ *      //  (This could be made more compact, but for clarity of illustration,
+ *      //  all of the cases that can arise are handled separately.)
+ *
+ *      p.lock.acquire();              // Prime loop by acquiring first lock.
+ *                                     //    (If the acquire fails due to
+ *                                     //    interrupt, the method will throw
+ *                                     //    InterruptedException now,
+ *                                     //    so there is no need for any
+ *                                     //    further cleanup.)
+ *      for (;;) {
+ *        if (x.equals(p.item)) {
+ *          p.lock.release();          // release current before return
+ *          return true;
+ *        }
+ *        else {
+ *          Node nextp = p.next;
+ *          if (nextp == null) {
+ *            p.lock.release();       // release final lock that was held
+ *            return false;
+ *          }
+ *          else {
+ *            try {
+ *              nextp.lock.acquire(); // get next lock before releasing current
+ *            }
+ *            catch (InterruptedException ex) {
+ *              p.lock.release();    // also release current if acquire fails
+ *              throw ex;
+ *            }
+ *            p.lock.release();      // release old lock now that new one held
+ *            p = nextp;
+ *          }
+ *        }
+ *      }
+ *    }
+ *
+ *    synchronized void add(Object x) { // simple prepend
+ *      // The use of `synchronized'  here protects only head field.
+ *      // The method does not need to wait out other traversers 
+ *      // who have already made it past head.
+ *
+ *      head = new Node(x, head);
+ *    }
+ *
+ *    // ...  other similar traversal and update methods ...
+ * }
+ * </pre>
+ * <p>
+ * @see Semaphore
+ * <p>[<a href="http://gee.cs.oswego.edu/dl/classes/EDU/oswego/cs/dl/util/concurrent/intro.html"> Introduction to this package. </a>]
+**/
+
+public class Mutex implements Sync  {
+
+  /** The lock status **/
+  protected boolean inuse_ = false;
+
+  public void acquire() throws InterruptedException {
+      // if (Thread.interrupted()) throw new InterruptedException();
+    synchronized(this) {
+      try {
+        while (inuse_) wait();
+        inuse_ = true;
+      }
+      catch (InterruptedException ex) {
+        notify();
+        throw ex;
+      }
+    }
+  }
+
+  public synchronized void release()  {
+      if (inuse_ == false)
+          throw new RuntimeException("Not locked!!!!");
+    inuse_ = false;
+    notify(); 
+  }
+
+
+  public boolean attempt(long msecs) throws InterruptedException {
+      // if (Thread.interrupted()) throw new InterruptedException();
+    synchronized(this) {
+      if (!inuse_) {
+        inuse_ = true;
+        return true;
+      }
+      else if (msecs <= 0)
+        return false;
+      else {
+        long waitTime = msecs;
+        long start = System.currentTimeMillis();
+        try {
+          for (;;) {
+            wait(waitTime);
+            if (!inuse_) {
+              inuse_ = true;
+              return true;
+            }
+            else {
+              waitTime = msecs - (System.currentTimeMillis() - start);
+              if (waitTime <= 0) 
+                return false;
+            }
+          }
+        }
+        catch (InterruptedException ex) {
+          notify();
+          throw ex;
+        }
+      }
+    }  
+  }
+
+}
+