update to latest jsr166

This commit is contained in:
Shay Banon 2013-07-10 13:09:04 -07:00
parent abf2268574
commit fe6fb7135b
11 changed files with 5838 additions and 5923 deletions

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -8,18 +8,19 @@ package jsr166e;
/**
* A {@link ForkJoinTask} with a completion action performed when
* triggered and there are no remaining pending
* actions. CountedCompleters are in general more robust in the
* triggered and there are no remaining pending actions.
* CountedCompleters are in general more robust in the
* presence of subtask stalls and blockage than are other forms of
* ForkJoinTasks, but are less intuitive to program. Uses of
* CountedCompleter are similar to those of other completion based
* components (such as {@link java.nio.channels.CompletionHandler})
* except that multiple <em>pending</em> completions may be necessary
* to trigger the {@link #onCompletion} action, not just one. Unless
* initialized otherwise, the {@link #getPendingCount pending count}
* starts at zero, but may be (atomically) changed using methods
* {@link #setPendingCount}, {@link #addToPendingCount}, and {@link
* #compareAndSetPendingCount}. Upon invocation of {@link
* to trigger the completion action {@link #onCompletion(CountedCompleter)},
* not just one.
* Unless initialized otherwise, the {@linkplain #getPendingCount pending
* count} starts at zero, but may be (atomically) changed using
* methods {@link #setPendingCount}, {@link #addToPendingCount}, and
* {@link #compareAndSetPendingCount}. Upon invocation of {@link
* #tryComplete}, if the pending action count is nonzero, it is
* decremented; otherwise, the completion action is performed, and if
* this completer itself has a completer, the process is continued
@ -40,9 +41,10 @@ package jsr166e;
* <p>A concrete CountedCompleter class must define method {@link
* #compute}, that should in most cases (as illustrated below), invoke
* {@code tryComplete()} once before returning. The class may also
* optionally override method {@link #onCompletion} to perform an
* action upon normal completion, and method {@link
* #onExceptionalCompletion} to perform an action upon any exception.
* optionally override method {@link #onCompletion(CountedCompleter)}
* to perform an action upon normal completion, and method
* {@link #onExceptionalCompletion(Throwable, CountedCompleter)} to
* perform an action upon any exception.
*
* <p>CountedCompleters most often do not bear results, in which case
* they are normally declared as {@code CountedCompleter<Void>}, and
@ -63,13 +65,14 @@ package jsr166e;
* only as an internal helper for other computations, so its own task
* status (as reported in methods such as {@link ForkJoinTask#isDone})
* is arbitrary; this status changes only upon explicit invocations of
* {@link #complete}, {@link ForkJoinTask#cancel}, {@link
* ForkJoinTask#completeExceptionally} or upon exceptional completion
* of method {@code compute}. Upon any exceptional completion, the
* exception may be relayed to a task's completer (and its completer,
* and so on), if one exists and it has not otherwise already
* completed. Similarly, cancelling an internal CountedCompleter has
* only a local effect on that completer, so is not often useful.
* {@link #complete}, {@link ForkJoinTask#cancel},
* {@link ForkJoinTask#completeExceptionally(Throwable)} or upon
* exceptional completion of method {@code compute}. Upon any
* exceptional completion, the exception may be relayed to a task's
* completer (and its completer, and so on), if one exists and it has
* not otherwise already completed. Similarly, cancelling an internal
* CountedCompleter has only a local effect on that completer, so is
* not often useful.
*
* <p><b>Sample Usages.</b>
*
@ -96,8 +99,8 @@ package jsr166e;
* improve load balancing. In the recursive case, the second of each
* pair of subtasks to finish triggers completion of its parent
* (because no result combination is performed, the default no-op
* implementation of method {@code onCompletion} is not overridden). A
* static utility method sets up the base task and invokes it
* implementation of method {@code onCompletion} is not overridden).
* A static utility method sets up the base task and invokes it
* (here, implicitly using the {@link ForkJoinPool#commonPool()}).
*
* <pre> {@code
@ -152,12 +155,11 @@ package jsr166e;
* }
* }</pre>
*
* As a further improvement, notice that the left task need not even
* exist. Instead of creating a new one, we can iterate using the
* original task, and add a pending count for each fork. Additionally,
* because no task in this tree implements an {@link #onCompletion}
* method, {@code tryComplete()} can be replaced with {@link
* #propagateCompletion}.
* As a further improvement, notice that the left task need not even exist.
* Instead of creating a new one, we can iterate using the original task,
* and add a pending count for each fork. Additionally, because no task
* in this tree implements an {@link #onCompletion(CountedCompleter)} method,
* {@code tryComplete()} can be replaced with {@link #propagateCompletion}.
*
* <pre> {@code
* class ForEach<E> ...
@ -235,7 +237,7 @@ package jsr166e;
*
* <p><b>Recording subtasks.</b> CountedCompleter tasks that combine
* results of multiple subtasks usually need to access these results
* in method {@link #onCompletion}. As illustrated in the following
* in method {@link #onCompletion(CountedCompleter)}. As illustrated in the following
* class (that performs a simplified form of map-reduce where mappings
* and reductions are all of type {@code E}), one way to do this in
* divide and conquer designs is to have each subtask record its
@ -336,7 +338,7 @@ package jsr166e;
* while (h - l >= 2) {
* int mid = (l + h) >>> 1;
* addToPendingCount(1);
* (forks = new MapReducer(this, array, mapper, reducer, mid, h, forks)).fork;
* (forks = new MapReducer(this, array, mapper, reducer, mid, h, forks)).fork();
* h = mid;
* }
* if (h > l)
@ -357,7 +359,7 @@ package jsr166e;
*
* <p><b>Triggers.</b> Some CountedCompleters are themselves never
* forked, but instead serve as bits of plumbing in other designs;
* including those in which the completion of one of more async tasks
* including those in which the completion of one or more async tasks
* triggers another async task. For example:
*
* <pre> {@code
@ -437,20 +439,21 @@ public abstract class CountedCompleter<T> extends ForkJoinTask<T> {
}
/**
* Performs an action when method {@link #completeExceptionally}
* is invoked or method {@link #compute} throws an exception, and
* this task has not otherwise already completed normally. On
* entry to this method, this task {@link
* ForkJoinTask#isCompletedAbnormally}. The return value of this
* method controls further propagation: If {@code true} and this
* task has a completer, then this completer is also completed
* exceptionally. The default implementation of this method does
* nothing except return {@code true}.
* Performs an action when method {@link
* #completeExceptionally(Throwable)} is invoked or method {@link
* #compute} throws an exception, and this task has not already
* otherwise completed normally. On entry to this method, this task
* {@link ForkJoinTask#isCompletedAbnormally}. The return value
* of this method controls further propagation: If {@code true}
* and this task has a completer that has not completed, then that
* completer is also completed exceptionally, with the same
* exception as this completer. The default implementation of
* this method does nothing except return {@code true}.
*
* @param ex the exception
* @param caller the task invoking this method (which may
* be this task itself)
* @return true if this exception should be propagated to this
* @return {@code true} if this exception should be propagated to this
* task's completer, if one exists
*/
public boolean onExceptionalCompletion(Throwable ex, CountedCompleter<?> caller) {
@ -491,7 +494,7 @@ public abstract class CountedCompleter<T> extends ForkJoinTask<T> {
* @param delta the value to add
*/
public final void addToPendingCount(int delta) {
int c; // note: can replace with intrinsic in jdk8
int c;
do {} while (!U.compareAndSwapInt(this, PENDING, c = pending, c+delta));
}
@ -501,7 +504,7 @@ public abstract class CountedCompleter<T> extends ForkJoinTask<T> {
*
* @param expected the expected value
* @param count the new value
* @return true if successful
* @return {@code true} if successful
*/
public final boolean compareAndSetPendingCount(int expected, int count) {
return U.compareAndSwapInt(this, PENDING, expected, count);
@ -535,9 +538,9 @@ public abstract class CountedCompleter<T> extends ForkJoinTask<T> {
/**
* If the pending count is nonzero, decrements the count;
* otherwise invokes {@link #onCompletion} and then similarly
* tries to complete this task's completer, if one exists,
* else marks this task as complete.
* otherwise invokes {@link #onCompletion(CountedCompleter)}
* and then similarly tries to complete this task's completer,
* if one exists, else marks this task as complete.
*/
public final void tryComplete() {
CountedCompleter<?> a = this, s = a;
@ -556,12 +559,12 @@ public abstract class CountedCompleter<T> extends ForkJoinTask<T> {
/**
* Equivalent to {@link #tryComplete} but does not invoke {@link
* #onCompletion} along the completion path: If the pending count
* is nonzero, decrements the count; otherwise, similarly tries to
* complete this task's completer, if one exists, else marks this
* task as complete. This method may be useful in cases where
* {@code onCompletion} should not, or need not, be invoked for
* each completer in a computation.
* #onCompletion(CountedCompleter)} along the completion path:
* If the pending count is nonzero, decrements the count;
* otherwise, similarly tries to complete this task's completer, if
* one exists, else marks this task as complete. This method may be
* useful in cases where {@code onCompletion} should not, or need
* not, be invoked for each completer in a computation.
*/
public final void propagateCompletion() {
CountedCompleter<?> a = this, s = a;
@ -578,13 +581,15 @@ public abstract class CountedCompleter<T> extends ForkJoinTask<T> {
}
/**
* Regardless of pending count, invokes {@link #onCompletion},
* marks this task as complete and further triggers {@link
* #tryComplete} on this task's completer, if one exists. The
* given rawResult is used as an argument to {@link #setRawResult}
* before invoking {@link #onCompletion} or marking this task as
* complete; its value is meaningful only for classes overriding
* {@code setRawResult}.
* Regardless of pending count, invokes
* {@link #onCompletion(CountedCompleter)}, marks this task as
* complete and further triggers {@link #tryComplete} on this
* task's completer, if one exists. The given rawResult is
* used as an argument to {@link #setRawResult} before invoking
* {@link #onCompletion(CountedCompleter)} or marking this task
* as complete; its value is meaningful only for classes
* overriding {@code setRawResult}. This method does not modify
* the pending count.
*
* <p>This method may be useful when forcing completion as soon as
* any one (versus all) of several subtask results are obtained.
@ -624,8 +629,8 @@ public abstract class CountedCompleter<T> extends ForkJoinTask<T> {
/**
* If this task does not have a completer, invokes {@link
* ForkJoinTask#quietlyComplete} and returns {@code null}. Or, if
* this task's pending count is non-zero, decrements its pending
* count and returns {@code null}. Otherwise, returns the
* the completer's pending count is non-zero, decrements that
* pending count and returns {@code null}. Otherwise, returns the
* completer. This method can be used as part of a completion
* traversal loop for homogeneous task hierarchies:
*
@ -667,8 +672,9 @@ public abstract class CountedCompleter<T> extends ForkJoinTask<T> {
void internalPropagateException(Throwable ex) {
CountedCompleter<?> a = this, s = a;
while (a.onExceptionalCompletion(ex, s) &&
(a = (s = a).completer) != null && a.status >= 0)
a.recordExceptionalCompletion(ex);
(a = (s = a).completer) != null && a.status >= 0 &&
a.recordExceptionalCompletion(ex) == EXCEPTIONAL)
;
}
/**

File diff suppressed because it is too large Load Diff

View File

@ -134,10 +134,9 @@ import java.lang.reflect.Constructor;
* (DAG). Otherwise, executions may encounter a form of deadlock as
* tasks cyclically wait for each other. However, this framework
* supports other methods and techniques (for example the use of
* {@link java.util.concurrent.Phaser}, {@link #helpQuiesce}, and
* {@link #complete}) that
* {@link Phaser}, {@link #helpQuiesce}, and {@link #complete}) that
* may be of use in constructing custom subclasses for problems that
* are not statically structured as DAGs. To support such usages a
* are not statically structured as DAGs. To support such usages, a
* ForkJoinTask may be atomically <em>tagged</em> with a {@code short}
* value using {@link #setForkJoinTaskTag} or {@link
* #compareAndSetForkJoinTaskTag} and checked using {@link
@ -286,25 +285,35 @@ public abstract class ForkJoinTask<V> implements Future<V>, Serializable {
*/
private int externalAwaitDone() {
int s;
ForkJoinPool.externalHelpJoin(this);
boolean interrupted = false;
while ((s = status) >= 0) {
if (U.compareAndSwapInt(this, STATUS, s, s | SIGNAL)) {
synchronized (this) {
if (status >= 0) {
try {
wait();
} catch (InterruptedException ie) {
interrupted = true;
ForkJoinPool cp = ForkJoinPool.common;
if ((s = status) >= 0) {
if (cp != null) {
if (this instanceof CountedCompleter)
s = cp.externalHelpComplete((CountedCompleter<?>)this);
else if (cp.tryExternalUnpush(this))
s = doExec();
}
if (s >= 0 && (s = status) >= 0) {
boolean interrupted = false;
do {
if (U.compareAndSwapInt(this, STATUS, s, s | SIGNAL)) {
synchronized (this) {
if (status >= 0) {
try {
wait();
} catch (InterruptedException ie) {
interrupted = true;
}
}
else
notifyAll();
}
}
else
notifyAll();
}
} while ((s = status) >= 0);
if (interrupted)
Thread.currentThread().interrupt();
}
}
if (interrupted)
Thread.currentThread().interrupt();
return s;
}
@ -313,9 +322,15 @@ public abstract class ForkJoinTask<V> implements Future<V>, Serializable {
*/
private int externalInterruptibleAwaitDone() throws InterruptedException {
int s;
ForkJoinPool cp = ForkJoinPool.common;
if (Thread.interrupted())
throw new InterruptedException();
ForkJoinPool.externalHelpJoin(this);
if ((s = status) >= 0 && cp != null) {
if (this instanceof CountedCompleter)
cp.externalHelpComplete((CountedCompleter<?>)this);
else if (cp.tryExternalUnpush(this))
doExec();
}
while ((s = status) >= 0) {
if (U.compareAndSwapInt(this, STATUS, s, s | SIGNAL)) {
synchronized (this) {
@ -601,14 +616,9 @@ public abstract class ForkJoinTask<V> implements Future<V>, Serializable {
/**
* A version of "sneaky throw" to relay exceptions
*/
static void rethrow(final Throwable ex) {
if (ex != null) {
if (ex instanceof Error)
throw (Error)ex;
if (ex instanceof RuntimeException)
throw (RuntimeException)ex;
static void rethrow(Throwable ex) {
if (ex != null)
ForkJoinTask.<RuntimeException>uncheckedThrow(ex);
}
}
/**
@ -618,8 +628,7 @@ public abstract class ForkJoinTask<V> implements Future<V>, Serializable {
*/
@SuppressWarnings("unchecked") static <T extends Throwable>
void uncheckedThrow(Throwable t) throws T {
if (t != null)
throw (T)t; // rely on vacuous cast
throw (T)t; // rely on vacuous cast
}
/**
@ -830,7 +839,7 @@ public abstract class ForkJoinTask<V> implements Future<V>, Serializable {
* <p>This method is designed to be invoked by <em>other</em>
* tasks. To terminate the current task, you can just return or
* throw an unchecked exception from its computation method, or
* invoke {@link #completeExceptionally}.
* invoke {@link #completeExceptionally(Throwable)}.
*
* @param mayInterruptIfRunning this value has no effect in the
* default implementation because interrupts are not used to
@ -982,6 +991,7 @@ public abstract class ForkJoinTask<V> implements Future<V>, Serializable {
// Messy in part because we measure in nanosecs, but wait in millisecs
int s; long ms;
long ns = unit.toNanos(timeout);
ForkJoinPool cp;
if ((s = status) >= 0 && ns > 0L) {
long deadline = System.nanoTime() + ns;
ForkJoinPool p = null;
@ -993,8 +1003,12 @@ public abstract class ForkJoinTask<V> implements Future<V>, Serializable {
w = wt.workQueue;
p.helpJoinOnce(w, this); // no retries on failure
}
else
ForkJoinPool.externalHelpJoin(this);
else if ((cp = ForkJoinPool.common) != null) {
if (this instanceof CountedCompleter)
cp.externalHelpComplete((CountedCompleter<?>)this);
else if (cp.tryExternalUnpush(this))
doExec();
}
boolean canBlock = false;
boolean interrupted = false;
try {
@ -1002,7 +1016,7 @@ public abstract class ForkJoinTask<V> implements Future<V>, Serializable {
if (w != null && w.qlock < 0)
cancelIgnoringExceptions(this);
else if (!canBlock) {
if (p == null || p.tryCompensate())
if (p == null || p.tryCompensate(p.ctl))
canBlock = true;
}
else {
@ -1143,7 +1157,7 @@ public abstract class ForkJoinTask<V> implements Future<V>, Serializable {
Thread t;
return (((t = Thread.currentThread()) instanceof ForkJoinWorkerThread) ?
((ForkJoinWorkerThread)t).workQueue.tryUnpush(this) :
ForkJoinPool.tryExternalUnpush(this));
ForkJoinPool.common.tryExternalUnpush(this));
}
/**
@ -1312,7 +1326,7 @@ public abstract class ForkJoinTask<V> implements Future<V>, Serializable {
*
* @param e the expected tag value
* @param tag the new tag value
* @return true if successful; i.e., the current value was
* @return {@code true} if successful; i.e., the current value was
* equal to e and is now tag.
* @since 1.8
*/
@ -1364,6 +1378,24 @@ public abstract class ForkJoinTask<V> implements Future<V>, Serializable {
private static final long serialVersionUID = 5232453952276885070L;
}
/**
* Adaptor for Runnables in which failure forces worker exception
*/
static final class RunnableExecuteAction extends ForkJoinTask<Void> {
final Runnable runnable;
RunnableExecuteAction(Runnable runnable) {
if (runnable == null) throw new NullPointerException();
this.runnable = runnable;
}
public final Void getRawResult() { return null; }
public final void setRawResult(Void v) { }
public final boolean exec() { runnable.run(); return true; }
void internalPropagateException(Throwable ex) {
rethrow(ex); // rethrow outside exec() catches.
}
private static final long serialVersionUID = 5232453952276885070L;
}
/**
* Adaptor for Callables
*/

View File

@ -6,6 +6,7 @@
package jsr166e;
/**
* A thread managed by a {@link ForkJoinPool}, which executes
* {@link ForkJoinTask}s.
@ -14,8 +15,8 @@ package jsr166e;
* scheduling or execution. However, you can override initialization
* and termination methods surrounding the main task processing loop.
* If you do create such a subclass, you will also need to supply a
* custom {@link ForkJoinPool.ForkJoinWorkerThreadFactory} to use it
* in a {@code ForkJoinPool}.
* custom {@link ForkJoinPool.ForkJoinWorkerThreadFactory} to
* {@linkplain ForkJoinPool#ForkJoinPool use it} in a {@code ForkJoinPool}.
*
* @since 1.7
* @author Doug Lea
@ -60,16 +61,17 @@ public class ForkJoinWorkerThread extends Thread {
}
/**
* Returns the index number of this thread in its pool. The
* returned value ranges from zero to the maximum number of
* threads (minus one) that have ever been created in the pool.
* This method may be useful for applications that track status or
* collect results per-worker rather than per-task.
* Returns the unique index number of this thread in its pool.
* The returned value ranges from zero to the maximum number of
* threads (minus one) that may exist in the pool, and does not
* change during the lifetime of the thread. This method may be
* useful for applications that track status or collect results
* per-worker-thread rather than per-task.
*
* @return the index number
*/
public int getPoolIndex() {
return workQueue.poolIndex;
return workQueue.poolIndex >>> 1; // ignore odd/even tag bit
}
/**

View File

@ -5,10 +5,8 @@
*/
package jsr166e;
import jsr166y.ThreadLocalRandom;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReadWriteLock;
@ -120,34 +118,17 @@ import java.util.concurrent.locks.LockSupport;
* }
* }
*
* double distanceFromOriginV1() { // A read-only method
* long stamp;
* if ((stamp = sl.tryOptimisticRead()) != 0L) { // optimistic
* double currentX = x;
* double currentY = y;
* if (sl.validate(stamp))
* return Math.sqrt(currentX * currentX + currentY * currentY);
* }
* stamp = sl.readLock(); // fall back to read lock
* try {
* double currentX = x;
* double currentY = y;
* return Math.sqrt(currentX * currentX + currentY * currentY);
* } finally {
* sl.unlockRead(stamp);
* }
* }
*
* double distanceFromOriginV2() { // combines code paths
* double currentX = 0.0, currentY = 0.0;
* for (long stamp = sl.tryOptimisticRead(); ; stamp = sl.readLock()) {
* try {
* currentX = x;
* currentY = y;
* } finally {
* if (sl.tryConvertToOptimisticRead(stamp) != 0L) // unlock or validate
* break;
* }
* double distanceFromOrigin() { // A read-only method
* long stamp = sl.tryOptimisticRead();
* double currentX = x, currentY = y;
* if (!sl.validate(stamp)) {
* stamp = sl.readLock();
* try {
* currentX = x;
* currentY = y;
* } finally {
* sl.unlockRead(stamp);
* }
* }
* return Math.sqrt(currentX * currentX + currentY * currentY);
* }
@ -359,6 +340,8 @@ public class StampedLock implements java.io.Serializable {
* Behavior under timeout and interruption matches that specified
* for method {@link Lock#tryLock(long,TimeUnit)}.
*
* @param time the maximum time to wait for the lock
* @param unit the time unit of the {@code time} argument
* @return a stamp that can be used to unlock or convert mode,
* or zero if the lock is not available
* @throws InterruptedException if the current thread is interrupted
@ -438,6 +421,8 @@ public class StampedLock implements java.io.Serializable {
* Behavior under timeout and interruption matches that specified
* for method {@link Lock#tryLock(long,TimeUnit)}.
*
* @param time the maximum time to wait for the lock
* @param unit the time unit of the {@code time} argument
* @return a stamp that can be used to unlock or convert mode,
* or zero if the lock is not available
* @throws InterruptedException if the current thread is interrupted
@ -503,7 +488,8 @@ public class StampedLock implements java.io.Serializable {
* obtained from {@link #tryOptimisticRead} or a locking method
* for this lock has no defined effect or result.
*
* @return true if the lock has not been exclusively acquired
* @param stamp a stamp
* @return {@code true} if the lock has not been exclusively acquired
* since issuance of the given stamp; else false
*/
public boolean validate(long stamp) {
@ -716,7 +702,7 @@ public class StampedLock implements java.io.Serializable {
* stamp value. This method may be useful for recovery after
* errors.
*
* @return true if the lock was held, else false
* @return {@code true} if the lock was held, else false
*/
public boolean tryUnlockWrite() {
long s; WNode h;
@ -734,7 +720,7 @@ public class StampedLock implements java.io.Serializable {
* requiring a stamp value. This method may be useful for recovery
* after errors.
*
* @return true if the read lock was held, else false
* @return {@code true} if the read lock was held, else false
*/
public boolean tryUnlockRead() {
long s, m; WNode h;
@ -752,30 +738,66 @@ public class StampedLock implements java.io.Serializable {
return false;
}
// status monitoring methods
/**
* Returns true if the lock is currently held exclusively.
* Returns combined state-held and overflow read count for given
* state s.
*/
private int getReadLockCount(long s) {
long readers;
if ((readers = s & RBITS) >= RFULL)
readers = RFULL + readerOverflow;
return (int) readers;
}
/**
* Returns {@code true} if the lock is currently held exclusively.
*
* @return true if the lock is currently held exclusively
* @return {@code true} if the lock is currently held exclusively
*/
public boolean isWriteLocked() {
return (state & WBIT) != 0L;
}
/**
* Returns true if the lock is currently held non-exclusively.
* Returns {@code true} if the lock is currently held non-exclusively.
*
* @return true if the lock is currently held non-exclusively
* @return {@code true} if the lock is currently held non-exclusively
*/
public boolean isReadLocked() {
return (state & RBITS) != 0L;
}
private void readObject(java.io.ObjectInputStream s)
throws java.io.IOException, ClassNotFoundException {
s.defaultReadObject();
state = ORIGIN; // reset to unlocked state
/**
* Queries the number of read locks held for this lock. This
* method is designed for use in monitoring system state, not for
* synchronization control.
* @return the number of read locks held
*/
public int getReadLockCount() {
return getReadLockCount(state);
}
/**
* Returns a string identifying this lock, as well as its lock
* state. The state, in brackets, includes the String {@code
* "Unlocked"} or the String {@code "Write-locked"} or the String
* {@code "Read-locks:"} followed by the current number of
* read-locks held.
*
* @return a string identifying this lock, as well as its lock state
*/
public String toString() {
long s = state;
return super.toString() +
((s & ABITS) == 0L ? "[Unlocked]" :
(s & WBIT) != 0L ? "[Write-locked]" :
"[Read-locks:" + getReadLockCount(s) + "]");
}
// views
/**
* Returns a plain {@link Lock} view of this StampedLock in which
* the {@link Lock#lock} method is mapped to {@link #readLock},
@ -890,6 +912,12 @@ public class StampedLock implements java.io.Serializable {
}
}
private void readObject(java.io.ObjectInputStream s)
throws java.io.IOException, ClassNotFoundException {
s.defaultReadObject();
state = ORIGIN; // reset to unlocked state
}
// internals
/**
@ -901,7 +929,7 @@ public class StampedLock implements java.io.Serializable {
* @return new stamp on success, else zero
*/
private long tryIncReaderOverflow(long s) {
// assert (s & ABITS) >= RFULL
// assert (s & ABITS) >= RFULL;
if ((s & ABITS) == RFULL) {
if (U.compareAndSwapLong(this, STATE, s, s | RBITS)) {
++readerOverflow;
@ -922,7 +950,7 @@ public class StampedLock implements java.io.Serializable {
* @return new stamp on success, else zero
*/
private long tryDecReaderOverflow(long s) {
// assert (s & ABITS) >= RFULL
// assert (s & ABITS) >= RFULL;
if ((s & ABITS) == RFULL) {
if (U.compareAndSwapLong(this, STATE, s, s | RBITS)) {
int r; long next;
@ -1044,11 +1072,14 @@ public class StampedLock implements java.io.Serializable {
time = 0L;
else if ((time = deadline - System.nanoTime()) <= 0L)
return cancelWaiter(node, node, false);
node.thread = Thread.currentThread();
Thread wt = Thread.currentThread();
U.putObject(wt, PARKBLOCKER, this); // emulate LockSupport.park
node.thread = wt;
if (node.prev == p && p.status == WAITING && // recheck
(p != whead || (state & ABITS) != 0L))
U.park(false, time);
node.thread = null;
U.putObject(wt, PARKBLOCKER, null);
if (interruptible && Thread.interrupted())
return cancelWaiter(node, node, true);
}
@ -1113,8 +1144,6 @@ public class StampedLock implements java.io.Serializable {
node.cowait = p.cowait, node)) {
node.thread = Thread.currentThread();
for (long time;;) {
if (interruptible && Thread.interrupted())
return cancelWaiter(node, p, true);
if (deadline == 0L)
time = 0L;
else if ((time = deadline - System.nanoTime()) <= 0L)
@ -1126,9 +1155,14 @@ public class StampedLock implements java.io.Serializable {
node.thread = null;
break;
}
Thread wt = Thread.currentThread();
U.putObject(wt, PARKBLOCKER, this);
if (node.thread == null) // must recheck
break;
U.park(false, time);
U.putObject(wt, PARKBLOCKER, null);
if (interruptible && Thread.interrupted())
return cancelWaiter(node, p, true);
}
group = p;
}
@ -1184,11 +1218,14 @@ public class StampedLock implements java.io.Serializable {
time = 0L;
else if ((time = deadline - System.nanoTime()) <= 0L)
return cancelWaiter(node, node, false);
node.thread = Thread.currentThread();
Thread wt = Thread.currentThread();
U.putObject(wt, PARKBLOCKER, this);
node.thread = wt;
if (node.prev == p && p.status == WAITING &&
(p != whead || (state & ABITS) != WBIT))
U.park(false, time);
node.thread = null;
U.putObject(wt, PARKBLOCKER, null);
if (interruptible && Thread.interrupted())
return cancelWaiter(node, node, true);
}
@ -1289,6 +1326,7 @@ public class StampedLock implements java.io.Serializable {
private static final long WNEXT;
private static final long WSTATUS;
private static final long WCOWAIT;
private static final long PARKBLOCKER;
static {
try {
@ -1307,6 +1345,9 @@ public class StampedLock implements java.io.Serializable {
(wk.getDeclaredField("next"));
WCOWAIT = U.objectFieldOffset
(wk.getDeclaredField("cowait"));
Class<?> tk = Thread.class;
PARKBLOCKER = U.objectFieldOffset
(tk.getDeclaredField("parkBlocker"));
} catch (Exception e) {
throw new Error(e);

View File

@ -19,7 +19,7 @@ import static java.lang.Double.longBitsToDouble;
* this class does extend {@code Number} to allow uniform access by
* tools and utilities that deal with numerically-based classes.
*
* <p><a name="bitEquals">This class compares primitive {@code double}
* <p id="bitEquals">This class compares primitive {@code double}
* values in methods such as {@link #compareAndSet} by comparing their
* bitwise representation using {@link Double#doubleToRawLongBits},
* which differs from both the primitive double {@code ==} operator
@ -29,7 +29,7 @@ import static java.lang.Double.longBitsToDouble;
* long xBits = Double.doubleToRawLongBits(x);
* long yBits = Double.doubleToRawLongBits(y);
* return xBits == yBits;
* }}</pre></a>
* }}</pre>
*
* @see jsr166e.DoubleAdder
* @see jsr166e.DoubleMaxUpdater
@ -123,11 +123,10 @@ public class AtomicDouble extends Number implements java.io.Serializable {
* if the current value is <a href="#bitEquals">bitwise equal</a>
* to the expected value.
*
* <p>May <a
* <p><a
* href="http://download.oracle.com/javase/7/docs/api/java/util/concurrent/atomic/package-summary.html#Spurious">
* fail spuriously</a>
* and does not provide ordering guarantees, so is only rarely an
* appropriate alternative to {@code compareAndSet}.
* May fail spuriously and does not provide ordering guarantees</a>,
* so is only rarely an appropriate alternative to {@code compareAndSet}.
*
* @param expect the expected value
* @param update the new value

View File

@ -14,7 +14,7 @@ import static java.lang.Double.longBitsToDouble;
* See the {@link java.util.concurrent.atomic} package specification
* for description of the properties of atomic variables.
*
* <p><a name="bitEquals">This class compares primitive {@code double}
* <p id="bitEquals">This class compares primitive {@code double}
* values in methods such as {@link #compareAndSet} by comparing their
* bitwise representation using {@link Double#doubleToRawLongBits},
* which differs from both the primitive double {@code ==} operator
@ -24,7 +24,7 @@ import static java.lang.Double.longBitsToDouble;
* long xBits = Double.doubleToRawLongBits(x);
* long yBits = Double.doubleToRawLongBits(y);
* return xBits == yBits;
* }}</pre></a>
* }}</pre>
*
* @author Doug Lea
* @author Martin Buchholz
@ -162,11 +162,10 @@ public class AtomicDoubleArray implements java.io.Serializable {
* if the current value is <a href="#bitEquals">bitwise equal</a>
* to the expected value.
*
* <p>May <a
* <p><a
* href="http://download.oracle.com/javase/7/docs/api/java/util/concurrent/atomic/package-summary.html#Spurious">
* fail spuriously</a>
* and does not provide ordering guarantees, so is only rarely an
* appropriate alternative to {@code compareAndSet}.
* May fail spuriously and does not provide ordering guarantees</a>,
* so is only rarely an appropriate alternative to {@code compareAndSet}.
*
* @param i the index
* @param expect the expected value

View File

@ -1,9 +0,0 @@
/*
* Written by Doug Lea with assistance from members of JCP JSR-166
* Expert Group and released to the public domain, as explained at
* http://creativecommons.org/publicdomain/zero/1.0/
*/
// Built on 2013-02-21
package jsr166e;

View File

@ -26,5 +26,5 @@
* are those that directly implement this algorithmic design pattern.
*/
// Built on 2013-02-21
// Built on 2013-07-10
package jsr166y;