下面列出了java.lang.invoke.VarHandle#acquireFence ( ) 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
/**
* Returns an index node with key strictly less than given key.
* Also unlinks indexes to deleted nodes found along the way.
* Callers rely on this side-effect of clearing indices to deleted
* nodes.
*
* @param key if nonnull the key
* @return a predecessor node of key, or null if uninitialized or null key
*/
private Node<K,V> findPredecessor(Object key, Comparator<? super K> cmp) {
Index<K,V> q;
VarHandle.acquireFence();
if ((q = head) == null || key == null)
return null;
else {
for (Index<K,V> r, d;;) {
while ((r = q.right) != null) {
Node<K,V> p; K k;
if ((p = r.node) == null || (k = p.key) == null ||
p.val == null) // unlink index to deleted node
RIGHT.compareAndSet(q, r, r.right);
else if (cpr(cmp, key, k) > 0)
q = r;
else
break;
}
if ((d = q.down) != null)
q = d;
else
return q.node;
}
}
}
SubMapIter() {
VarHandle.acquireFence();
Comparator<? super K> cmp = m.comparator;
for (;;) {
next = isDescending ? hiNode(cmp) : loNode(cmp);
if (next == null)
break;
V x = next.val;
if (x != null) {
if (! inBounds(next.key, cmp))
next = null;
else
nextValue = x;
break;
}
}
}
/**
* Provides a more accurate estimate of whether this queue has
* any tasks than does queueSize, by checking whether a
* near-empty queue has at least one unclaimed task.
*/
final boolean isEmpty() {
ForkJoinTask<?>[] a; int n, cap, b;
VarHandle.acquireFence(); // needed by external callers
return ((n = (b = base) - top) >= 0 || // possibly one task
(n == -1 && ((a = array) == null ||
(cap = a.length) == 0 ||
a[(cap - 1) & b] == null)));
}
/**
* Returns an estimate of the number of worker threads that are
* not blocked waiting to join tasks or for other managed
* synchronization. This method may overestimate the
* number of running threads.
*
* @return the number of worker threads
*/
public int getRunningThreadCount() {
WorkQueue[] ws; WorkQueue w;
VarHandle.acquireFence();
int rc = 0;
if ((ws = workQueues) != null) {
for (int i = 1; i < ws.length; i += 2) {
if ((w = ws[i]) != null && w.isApparentlyUnblocked())
++rc;
}
}
return rc;
}
/**
* Returns an estimate of the total number of tasks currently held
* in queues by worker threads (but not including tasks submitted
* to the pool that have not begun executing). This value is only
* an approximation, obtained by iterating across all threads in
* the pool. This method may be useful for tuning task
* granularities.
*
* @return the number of queued tasks
*/
public long getQueuedTaskCount() {
WorkQueue[] ws; WorkQueue w;
VarHandle.acquireFence();
int count = 0;
if ((ws = workQueues) != null) {
for (int i = 1; i < ws.length; i += 2) {
if ((w = ws[i]) != null)
count += w.queueSize();
}
}
return count;
}
/**
* Returns an estimate of the number of tasks submitted to this
* pool that have not yet begun executing. This method may take
* time proportional to the number of submissions.
*
* @return the number of queued submissions
*/
public int getQueuedSubmissionCount() {
WorkQueue[] ws; WorkQueue w;
VarHandle.acquireFence();
int count = 0;
if ((ws = workQueues) != null) {
for (int i = 0; i < ws.length; i += 2) {
if ((w = ws[i]) != null)
count += w.queueSize();
}
}
return count;
}
/**
* Returns {@code true} if there are any tasks submitted to this
* pool that have not yet begun executing.
*
* @return {@code true} if there are any queued submissions
*/
public boolean hasQueuedSubmissions() {
WorkQueue[] ws; WorkQueue w;
VarHandle.acquireFence();
if ((ws = workQueues) != null) {
for (int i = 0; i < ws.length; i += 2) {
if ((w = ws[i]) != null && !w.isEmpty())
return true;
}
}
return false;
}
/**
* Removes all of the mappings from this map.
*/
public void clear() {
Index<K,V> h, r, d; Node<K,V> b;
VarHandle.acquireFence();
while ((h = head) != null) {
if ((r = h.right) != null) // remove indices
RIGHT.compareAndSet(h, r, null);
else if ((d = h.down) != null) // remove levels
HEAD.compareAndSet(this, h, d);
else {
long count = 0L;
if ((b = h.node) != null) { // remove nodes
Node<K,V> n; V v;
while ((n = b.next) != null) {
if ((v = n.val) != null &&
VAL.compareAndSet(n, v, null)) {
--count;
v = null;
}
if (v == null)
unlinkNode(b, n);
}
}
if (count != 0L)
addCount(count);
else
break;
}
}
}
final KeySpliterator<K,V> keySpliterator() {
Index<K,V> h; Node<K,V> n; long est;
VarHandle.acquireFence();
if ((h = head) == null) {
n = null;
est = 0L;
}
else {
n = h.node;
est = getAdderCount();
}
return new KeySpliterator<K,V>(comparator, h, n, null, est);
}
final ValueSpliterator<K,V> valueSpliterator() {
Index<K,V> h; Node<K,V> n; long est;
VarHandle.acquireFence();
if ((h = head) == null) {
n = null;
est = 0L;
}
else {
n = h.node;
est = getAdderCount();
}
return new ValueSpliterator<K,V>(comparator, h, n, null, est);
}
final EntrySpliterator<K,V> entrySpliterator() {
Index<K,V> h; Node<K,V> n; long est;
VarHandle.acquireFence();
if ((h = head) == null) {
n = null;
est = 0L;
}
else {
n = h.node;
est = getAdderCount();
}
return new EntrySpliterator<K,V>(comparator, h, n, null, est);
}
/**
* If the lock state matches the given stamp then, atomically, if the stamp
* represents holding a lock, releases it and returns an
* observation stamp. Or, if an optimistic read, returns it if
* validated. This method returns zero in all other cases, and so
* may be useful as a form of "tryUnlock".
*
* @param stamp a stamp
* @return a valid optimistic read stamp, or zero on failure
*/
public long tryConvertToOptimisticRead(long stamp) {
long a, m, s, next; WNode h;
VarHandle.acquireFence();
while (((s = state) & SBITS) == (stamp & SBITS)) {
if ((a = stamp & ABITS) >= WBIT) {
// write stamp
if (s != stamp)
break;
return unlockWriteInternal(s);
}
else if (a == 0L)
// already an optimistic read stamp
return stamp;
else if ((m = s & ABITS) == 0L) // invalid read stamp
break;
else if (m < RFULL) {
if (casState(s, next = s - RUNIT)) {
if (m == RUNIT && (h = whead) != null && h.status != 0)
release(h);
return next & SBITS;
}
}
else if ((next = tryDecReaderOverflow(s)) != 0L)
return next & SBITS;
}
return 0L;
}
/**
* Removes all available unexecuted submitted and forked tasks
* from scheduling queues and adds them to the given collection,
* without altering their execution status. These may include
* artificially generated or wrapped tasks. This method is
* designed to be invoked only when the pool is known to be
* quiescent. Invocations at other times may not remove all
* tasks. A failure encountered while attempting to add elements
* to collection {@code c} may result in elements being in
* neither, either or both collections when the associated
* exception is thrown. The behavior of this operation is
* undefined if the specified collection is modified while the
* operation is in progress.
*
* @param c the collection to transfer elements into
* @return the number of elements transferred
*/
protected int drainTasksTo(Collection<? super ForkJoinTask<?>> c) {
WorkQueue[] ws; WorkQueue w; ForkJoinTask<?> t;
VarHandle.acquireFence();
int count = 0;
if ((ws = workQueues) != null) {
for (int i = 0; i < ws.length; ++i) {
if ((w = ws[i]) != null) {
while ((t = w.poll()) != null) {
c.add(t);
++count;
}
}
}
}
return count;
}
/**
* Returns the header for base node list, or null if uninitialized
*/
final Node<K,V> baseHead() {
Index<K,V> h;
VarHandle.acquireFence();
return ((h = head) == null) ? null : h.node;
}
/**
* Specialized version of find to get last valid node.
* @return last node or null if empty
*/
final Node<K,V> findLast() {
outer: for (;;) {
Index<K,V> q; Node<K,V> b;
VarHandle.acquireFence();
if ((q = head) == null)
break;
for (Index<K,V> r, d;;) {
while ((r = q.right) != null) {
Node<K,V> p;
if ((p = r.node) == null || p.val == null)
RIGHT.compareAndSet(q, r, r.right);
else
q = r;
}
if ((d = q.down) != null)
q = d;
else {
b = q.node;
break;
}
}
if (b != null) {
for (;;) {
Node<K,V> n;
if ((n = b.next) == null) {
if (b.key == null) // empty
break outer;
else
return b;
}
else if (n.key == null)
break;
else if (n.val == null)
unlinkNode(b, n);
else
b = n;
}
}
}
return null;
}
/**
* Removes last entry; returns its snapshot.
* Specialized variant of doRemove.
* @return null if empty, else snapshot of last entry
*/
private Map.Entry<K,V> doRemoveLastEntry() {
outer: for (;;) {
Index<K,V> q; Node<K,V> b;
VarHandle.acquireFence();
if ((q = head) == null)
break;
for (;;) {
Index<K,V> d, r; Node<K,V> p;
while ((r = q.right) != null) {
if ((p = r.node) == null || p.val == null)
RIGHT.compareAndSet(q, r, r.right);
else if (p.next != null)
q = r; // continue only if a successor
else
break;
}
if ((d = q.down) != null)
q = d;
else {
b = q.node;
break;
}
}
if (b != null) {
for (;;) {
Node<K,V> n; K k; V v;
if ((n = b.next) == null) {
if (b.key == null) // empty
break outer;
else
break; // retry
}
else if ((k = n.key) == null)
break;
else if ((v = n.val) == null)
unlinkNode(b, n);
else if (n.next != null)
b = n;
else if (VAL.compareAndSet(n, v, null)) {
unlinkNode(b, n);
tryReduceLevel();
findPredecessor(k, comparator); // clean index
addCount(-1L);
return new AbstractMap.SimpleImmutableEntry<K,V>(k, v);
}
}
}
}
return null;
}
/**
* Returns true if the lock has not been exclusively acquired
* since issuance of the given stamp. Always returns false if the
* stamp is zero. Always returns true if the stamp represents a
* currently held lock. Invoking this method with a value not
* obtained from {@link #tryOptimisticRead} or a locking method
* for this lock has no defined effect or result.
*
* @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) {
VarHandle.acquireFence();
return (stamp & SBITS) == (state & SBITS);
}