comparison 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
comparison
equal deleted inserted replaced
-1:000000000000 0:3dc0c5604566
1 /*
2 File: Mutex.java
3
4 Originally written by Doug Lea and released into the public domain.
5 This may be used for any purposes whatsoever without acknowledgment.
6 Thanks for the assistance and support of Sun Microsystems Labs,
7 and everyone contributing, testing, and using this code.
8
9 History:
10 Date Who What
11 11Jun1998 dl Create public version
12 */
13
14 package EDU.oswego.cs.dl.util.concurrent;
15
16 /**
17 * A simple non-reentrant mutual exclusion lock.
18 * The lock is free upon construction. Each acquire gets the
19 * lock, and each release frees it. Releasing a lock that
20 * is already free has no effect.
21 * <p>
22 * This implementation makes no attempt to provide any fairness
23 * or ordering guarantees. If you need them, consider using one of
24 * the Semaphore implementations as a locking mechanism.
25 * <p>
26 * <b>Sample usage</b><br>
27 * <p>
28 * Mutex can be useful in constructions that cannot be
29 * expressed using java synchronized blocks because the
30 * acquire/release pairs do not occur in the same method or
31 * code block. For example, you can use them for hand-over-hand
32 * locking across the nodes of a linked list. This allows
33 * extremely fine-grained locking, and so increases
34 * potential concurrency, at the cost of additional complexity and
35 * overhead that would normally make this worthwhile only in cases of
36 * extreme contention.
37 * <pre>
38 * class Node {
39 * Object item;
40 * Node next;
41 * Mutex lock = new Mutex(); // each node keeps its own lock
42 *
43 * Node(Object x, Node n) { item = x; next = n; }
44 * }
45 *
46 * class List {
47 * protected Node head; // pointer to first node of list
48 *
49 * // Use plain java synchronization to protect head field.
50 * // (We could instead use a Mutex here too but there is no
51 * // reason to do so.)
52 * protected synchronized Node getHead() { return head; }
53 *
54 * boolean search(Object x) throws InterruptedException {
55 * Node p = getHead();
56 * if (p == null) return false;
57 *
58 * // (This could be made more compact, but for clarity of illustration,
59 * // all of the cases that can arise are handled separately.)
60 *
61 * p.lock.acquire(); // Prime loop by acquiring first lock.
62 * // (If the acquire fails due to
63 * // interrupt, the method will throw
64 * // InterruptedException now,
65 * // so there is no need for any
66 * // further cleanup.)
67 * for (;;) {
68 * if (x.equals(p.item)) {
69 * p.lock.release(); // release current before return
70 * return true;
71 * }
72 * else {
73 * Node nextp = p.next;
74 * if (nextp == null) {
75 * p.lock.release(); // release final lock that was held
76 * return false;
77 * }
78 * else {
79 * try {
80 * nextp.lock.acquire(); // get next lock before releasing current
81 * }
82 * catch (InterruptedException ex) {
83 * p.lock.release(); // also release current if acquire fails
84 * throw ex;
85 * }
86 * p.lock.release(); // release old lock now that new one held
87 * p = nextp;
88 * }
89 * }
90 * }
91 * }
92 *
93 * synchronized void add(Object x) { // simple prepend
94 * // The use of `synchronized' here protects only head field.
95 * // The method does not need to wait out other traversers
96 * // who have already made it past head.
97 *
98 * head = new Node(x, head);
99 * }
100 *
101 * // ... other similar traversal and update methods ...
102 * }
103 * </pre>
104 * <p>
105 * @see Semaphore
106 * <p>[<a href="http://gee.cs.oswego.edu/dl/classes/EDU/oswego/cs/dl/util/concurrent/intro.html"> Introduction to this package. </a>]
107 **/
108
109 public class Mutex implements Sync {
110
111 /** The lock status **/
112 protected boolean inuse_ = false;
113
114 public void acquire() throws InterruptedException {
115 // if (Thread.interrupted()) throw new InterruptedException();
116 synchronized(this) {
117 try {
118 while (inuse_) wait();
119 inuse_ = true;
120 }
121 catch (InterruptedException ex) {
122 notify();
123 throw ex;
124 }
125 }
126 }
127
128 public synchronized void release() {
129 if (inuse_ == false)
130 throw new RuntimeException("Not locked!!!!");
131 inuse_ = false;
132 notify();
133 }
134
135
136 public boolean attempt(long msecs) throws InterruptedException {
137 // if (Thread.interrupted()) throw new InterruptedException();
138 synchronized(this) {
139 if (!inuse_) {
140 inuse_ = true;
141 return true;
142 }
143 else if (msecs <= 0)
144 return false;
145 else {
146 long waitTime = msecs;
147 long start = System.currentTimeMillis();
148 try {
149 for (;;) {
150 wait(waitTime);
151 if (!inuse_) {
152 inuse_ = true;
153 return true;
154 }
155 else {
156 waitTime = msecs - (System.currentTimeMillis() - start);
157 if (waitTime <= 0)
158 return false;
159 }
160 }
161 }
162 catch (InterruptedException ex) {
163 notify();
164 throw ex;
165 }
166 }
167 }
168 }
169
170 }
171