001: /*
002: * The contents of this file are subject to the Sapient Public License
003: * Version 1.0 (the "License"); you may not use this file except in compliance
004: * with the License. You may obtain a copy of the License at
005: * http://carbon.sf.net/License.html.
006: *
007: * Software distributed under the License is distributed on an "AS IS" basis,
008: * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
009: * the specific language governing rights and limitations under the License.
010: *
011: * The Original Code is The Carbon Component Framework.
012: *
013: * The Initial Developer of the Original Code is Sapient Corporation
014: *
015: * Copyright (C) 2003 Sapient Corporation. All Rights Reserved.
016: */
017:
018: package org.sape.carbon.core.util.thread;
019:
020: /*
021: Originally written by Doug Lea and released into the public domain.
022: This may be used for any purposes whatsoever without acknowledgment.
023: Thanks for the assistance and support of Sun Microsystems Labs,
024: and everyone contributing, testing, and using this code.
025:
026: History:
027: Date Who What
028: 11 Jun1998 dl Create public version
029: 5 Aug1998 dl Added some convenient time constants
030: */
031:
032: /**
033: * Main interface for locks, gates, and conditions.
034: * <p>
035: * Sync objects isolate waiting and notification for particular
036: * logical states, resource availability, events, and the like that are
037: * shared across multiple threads. Use of Syncs sometimes
038: * (but by no means always) adds flexibility and efficiency
039: * compared to the use of plain java monitor methods
040: * and locking, and are sometimes (but by no means always)
041: * simpler to program with.
042: * <p>
043: *
044: * Most Syncs are intended to be used primarily (although
045: * not exclusively) in before/after constructions such as:
046: * <pre>
047: * class X {
048: * Sync gate;
049: * // ...
050: *
051: * public void m() {
052: * try {
053: * gate.acquire(); // block until condition holds
054: * try {
055: * // ... method body
056: * }
057: * finally {
058: * gate.release()
059: * }
060: * }
061: * catch (InterruptedException ex) {
062: * // ... evasive action
063: * }
064: * }
065: *
066: * public void m2(Sync cond) { // use supplied condition
067: * try {
068: * if (cond.attempt(10)) { // try the condition for 10 ms
069: * try {
070: * // ... method body
071: * }
072: * finally {
073: * cond.release()
074: * }
075: * }
076: * }
077: * catch (InterruptedException ex) {
078: * // ... evasive action
079: * }
080: * }
081: * }
082: * </pre>
083: * Syncs may be used in somewhat tedious but more flexible replacements
084: * for built-in Java synchronized blocks. For example:
085: * <pre>
086: * class HandSynched {
087: * private double state_ = 0.0;
088: * private final Sync lock; // use lock type supplied in constructor
089: * public HandSynched(Sync l) { lock = l; }
090: *
091: * public void changeState(double d) {
092: * try {
093: * lock.acquire();
094: * try { state_ = updateFunction(d); }
095: * finally { lock.release(); }
096: * }
097: * catch(InterruptedException ex) { }
098: * }
099: *
100: * public double getState() {
101: * double d = 0.0;
102: * try {
103: * lock.acquire();
104: * try { d = accessFunction(state_); }
105: * finally { lock.release(); }
106: * }
107: * catch(InterruptedException ex){}
108: * return d;
109: * }
110: * private double updateFunction(double d) { ... }
111: * private double accessFunction(double d) { ... }
112: * }
113: * </pre>
114: * If you have a lot of such methods, and they take a common
115: * form, you can standardize this using wrappers. Some of these
116: * wrappers are standardized in LockedExecutor, but you can make others.
117: * For example:
118: * <pre>
119: * class HandSynchedV2 {
120: * private double state_ = 0.0;
121: * private final Sync lock; // use lock type supplied in constructor
122: * public HandSynchedV2(Sync l) { lock = l; }
123: *
124: * protected void runSafely(Runnable r) {
125: * try {
126: * lock.acquire();
127: * try { r.run(); }
128: * finally { lock.release(); }
129: * }
130: * catch (InterruptedException ex) { // propagate without throwing
131: * Thread.currentThread().interrupt();
132: * }
133: * }
134: *
135: * public void changeState(double d) {
136: * runSafely(new Runnable() {
137: * public void run() { state_ = updateFunction(d); }
138: * });
139: * }
140: * // ...
141: * }
142: * </pre>
143: * <p>
144: * One reason to bother with such constructions is to use deadlock-
145: * avoiding back-offs when dealing with locks involving multiple objects.
146: * For example, here is a Cell class that uses attempt to back-off
147: * and retry if two Cells are trying to swap values with each other
148: * at the same time.
149: * <pre>
150: * class Cell {
151: * long value;
152: * Sync lock = ... // some sync implementation class
153: * void swapValue(Cell other) {
154: * for (;;) {
155: * try {
156: * lock.acquire();
157: * try {
158: * if (other.lock.attempt(100)) {
159: * try {
160: * long t = value;
161: * value = other.value;
162: * other.value = t;
163: * return;
164: * }
165: * finally { other.lock.release(); }
166: * }
167: * }
168: * finally { lock.release(); }
169: * }
170: * catch (InterruptedException ex) { return; }
171: * }
172: * }
173: * }
174: *</pre>
175: * <p>
176: * Here is an even fancier version, that uses lock re-ordering
177: * upon conflict:
178: * <pre>
179: * class Cell {
180: * long value;
181: * Sync lock = ...;
182: * private static boolean trySwap(Cell a, Cell b) {
183: * a.lock.acquire();
184: * try {
185: * if (!b.lock.attempt(0))
186: * return false;
187: * try {
188: * long t = a.value;
189: * a.value = b.value;
190: * b.value = t;
191: * return true;
192: * }
193: * finally { other.lock.release(); }
194: * }
195: * finally { lock.release(); }
196: * return false;
197: * }
198: *
199: * void swapValue(Cell other) {
200: * try {
201: * while (!trySwap(this, other) &&
202: * !tryswap(other, this))
203: * Thread.sleep(1);
204: * }
205: * catch (InterruptedException ex) { return; }
206: * }
207: *}
208: *</pre>
209: * <p>
210: * Interruptions are in general handled as early as possible.
211: * Normally, InterruptionExceptions are thrown
212: * in acquire and attempt(msec) if interruption
213: * is detected upon entry to the method, as well as in any
214: * later context surrounding waits.
215: * However, interruption status is ignored in release();
216: * <p>
217: * Timed versions of attempt report failure via return value.
218: * If so desired, you can transform such constructions to use exception
219: * throws via
220: * <pre>
221: * if (!c.attempt(timeval)) throw new TimeoutException(timeval);
222: * </pre>
223: * <p>
224: * The TimoutSync wrapper class can be used to automate such usages.
225: * <p>
226: * All time values are expressed in milliseconds as longs, which have a maximum
227: * value of Long.MAX_VALUE, or almost 300,000 centuries. It is not
228: * known whether JVMs actually deal correctly with such extreme values.
229: * For convenience, some useful time values are defined as static constants.
230: * <p>
231: * All implementations of the three Sync methods guarantee to
232: * somehow employ Java <code>synchronized</code> methods or blocks,
233: * and so entail the memory operations described in JLS
234: * chapter 17 which ensure that variables are loaded and flushed
235: * within before/after constructions.
236: * <p>
237: * Syncs may also be used in spinlock constructions. Although
238: * it is normally best to just use acquire(), various forms
239: * of busy waits can be implemented. For a simple example
240: * (but one that would probably never be preferable to using acquire()):
241: * <pre>
242: * class X {
243: * Sync lock = ...
244: * void spinUntilAcquired() throws InterruptedException {
245: * // Two phase.
246: * // First spin without pausing.
247: * int purespins = 10;
248: * for (int i = 0; i < purespins; ++i) {
249: * if (lock.attempt(0))
250: * return true;
251: * }
252: * // Second phase - use timed waits
253: * long waitTime = 1; // 1 millisecond
254: * for (;;) {
255: * if (lock.attempt(waitTime))
256: * return true;
257: * else
258: * waitTime = waitTime * 3 / 2 + 1; // increase 50%
259: * }
260: * }
261: * }
262: * </pre>
263: * <p>
264: * In addition pure synchronization control, Syncs
265: * may be useful in any context requiring before/after methods.
266: * For example, you can use an ObservableSync
267: * (perhaps as part of a LayeredSync) in order to obtain callbacks
268: * before and after each method invocation for a given class.
269: * <p>
270:
271: * <p>[<a href="http://gee.cs.oswego.edu/dl/classes/EDU/oswego/cs/dl/util/concurrent/intro.html"> Introduction to this package. </a>]
272: *
273: * @since carbon 2.0
274: * @author Doug Lea
275: * @version $Revision: 1.3 $($Author: dvoet $ / $Date: 2003/05/05 21:21:24 $)
276: **/
277: public interface Sync {
278:
279: /**
280: * Wait (possibly forever) until successful passage.
281: * Fail only upon interuption. Interruptions always result in
282: * `clean' failures. On failure, you can be sure that it has not
283: * been acquired, and that no
284: * corresponding release should be performed. Conversely,
285: * a normal return guarantees that the acquire was successful.
286: **/
287:
288: public void acquire() throws InterruptedException;
289:
290: /**
291: * Wait at most msecs to pass; report whether passed.
292: * <p>
293: * The method has best-effort semantics:
294: * The msecs bound cannot
295: * be guaranteed to be a precise upper bound on wait time in Java.
296: * Implementations generally can only attempt to return as soon as possible
297: * after the specified bound. Also, timers in Java do not stop during garbage
298: * collection, so timeouts can occur just because a GC intervened.
299: * So, msecs arguments should be used in
300: * a coarse-grained manner. Further,
301: * implementations cannot always guarantee that this method
302: * will return at all without blocking indefinitely when used in
303: * unintended ways. For example, deadlocks may be encountered
304: * when called in an unintended context.
305: * <p>
306: * @param msecs the number of milleseconds to wait.
307: * An argument less than or equal to zero means not to wait at all.
308: * However, this may still require
309: * access to a synchronization lock, which can impose unbounded
310: * delay if there is a lot of contention among threads.
311: * @return true if acquired
312: **/
313:
314: public boolean attempt(long msecs) throws InterruptedException;
315:
316: /**
317: * Potentially enable others to pass.
318: * <p>
319: * Because release does not raise exceptions,
320: * it can be used in `finally' clauses without requiring extra
321: * embedded try/catch blocks. But keep in mind that
322: * as with any java method, implementations may
323: * still throw unchecked exceptions such as Error or NullPointerException
324: * when faced with uncontinuable errors. However, these should normally
325: * only be caught by higher-level error handlers.
326: **/
327:
328: public void release();
329:
330: /** One second, in milliseconds; convenient as a time-out value **/
331: public static final long ONE_SECOND = 1000;
332:
333: /** One minute, in milliseconds; convenient as a time-out value **/
334: public static final long ONE_MINUTE = 60 * ONE_SECOND;
335:
336: /** One hour, in milliseconds; convenient as a time-out value **/
337: public static final long ONE_HOUR = 60 * ONE_MINUTE;
338:
339: /** One day, in milliseconds; convenient as a time-out value **/
340: public static final long ONE_DAY = 24 * ONE_HOUR;
341:
342: /** One week, in milliseconds; convenient as a time-out value **/
343: public static final long ONE_WEEK = 7 * ONE_DAY;
344:
345: /** One year in milliseconds; convenient as a time-out value **/
346: // Not that it matters, but there is some variation across
347: // standard sources about value at msec precision.
348: // The value used is the same as in java.util.GregorianCalendar
349: public static final long ONE_YEAR = (long) (365.2425 * ONE_DAY);
350:
351: /** One century in milliseconds; convenient as a time-out value **/
352: public static final long ONE_CENTURY = 100 * ONE_YEAR;
353:
354: }
|