Mercurial > hg > blitz_condensed
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; + } + } + } + } + +} +