< prev index next >

src/java.base/share/classes/java/util/concurrent/locks/AbstractQueuedLongSynchronizer.java

Print this page

        

*** 41,50 **** --- 41,52 ---- import java.util.Collection; import java.util.Date; import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.AbstractQueuedSynchronizer.Node; + import jdk.internal.misc.Strands; + /** * A version of {@link AbstractQueuedSynchronizer} in * which synchronization state is maintained as a {@code long}. * This class has exactly the same structure, properties, and methods * as {@code AbstractQueuedSynchronizer} with the exception
*** 191,201 **** * * @param node the node */ private void setHead(Node node) { head = node; ! node.thread = null; node.prev = null; } /** * Wakes up node's successor, if one exists. --- 193,203 ---- * * @param node the node */ private void setHead(Node node) { head = node; ! node.strand = null; node.prev = null; } /** * Wakes up node's successor, if one exists.
*** 224,234 **** for (Node p = tail; p != node && p != null; p = p.prev) if (p.waitStatus <= 0) s = p; } if (s != null) ! LockSupport.unpark(s.thread); } /** * Release action for shared mode -- signals successor and ensures * propagation. (Note: For exclusive mode, release just amounts --- 226,236 ---- for (Node p = tail; p != node && p != null; p = p.prev) if (p.waitStatus <= 0) s = p; } if (s != null) ! LockSupport.unpark(s.strand); } /** * Release action for shared mode -- signals successor and ensures * propagation. (Note: For exclusive mode, release just amounts
*** 309,319 **** private void cancelAcquire(Node node) { // Ignore if node doesn't exist if (node == null) return; ! node.thread = null; // Skip cancelled predecessors Node pred = node.prev; while (pred.waitStatus > 0) node.prev = pred = pred.prev; --- 311,321 ---- private void cancelAcquire(Node node) { // Ignore if node doesn't exist if (node == null) return; ! node.strand = null; // Skip cancelled predecessors Node pred = node.prev; while (pred.waitStatus > 0) node.prev = pred = pred.prev;
*** 338,348 **** // so it will get one. Otherwise wake it up to propagate. int ws; if (pred != head && ((ws = pred.waitStatus) == Node.SIGNAL || (ws <= 0 && pred.compareAndSetWaitStatus(ws, Node.SIGNAL))) && ! pred.thread != null) { Node next = node.next; if (next != null && next.waitStatus <= 0) pred.compareAndSetNext(predNext, next); } else { unparkSuccessor(node); --- 340,350 ---- // so it will get one. Otherwise wake it up to propagate. int ws; if (pred != head && ((ws = pred.waitStatus) == Node.SIGNAL || (ws <= 0 && pred.compareAndSetWaitStatus(ws, Node.SIGNAL))) && ! pred.strand != null) { Node next = node.next; if (next != null && next.waitStatus <= 0) pred.compareAndSetNext(predNext, next); } else { unparkSuccessor(node);
*** 947,994 **** * @return the first (longest-waiting) thread in the queue, or * {@code null} if no threads are currently queued */ public final Thread getFirstQueuedThread() { // handle only fast path, else relay ! return (head == tail) ? null : fullGetFirstQueuedThread(); } /** ! * Version of getFirstQueuedThread called when fastpath fails. */ ! private Thread fullGetFirstQueuedThread() { /* * The first node is normally head.next. Try to get its * thread field, ensuring consistent reads: If thread * field is nulled out or s.prev is no longer head, then * some other thread(s) concurrently performed setHead in * between some of our reads. We try this twice before * resorting to traversal. */ Node h, s; ! Thread st; if (((h = head) != null && (s = h.next) != null && ! s.prev == head && (st = s.thread) != null) || ((h = head) != null && (s = h.next) != null && ! s.prev == head && (st = s.thread) != null)) return st; /* * Head's next field might not have been set yet, or may have * been unset after setHead. So we must check to see if tail * is actually first node. If not, we continue on, safely * traversing from tail back to head to find first, * guaranteeing termination. */ ! Thread firstThread = null; for (Node p = tail; p != null && p != head; p = p.prev) { ! Thread t = p.thread; ! if (t != null) ! firstThread = t; } ! return firstThread; } /** * Returns true if the given thread is currently queued. * --- 949,996 ---- * @return the first (longest-waiting) thread in the queue, or * {@code null} if no threads are currently queued */ public final Thread getFirstQueuedThread() { // handle only fast path, else relay ! return (head == tail) ? null : (Thread) fullGetFirstQueuedStrand(); } /** ! * Version of getFirstQueuedStrand called when fastpath fails. */ ! private Object fullGetFirstQueuedStrand() { /* * The first node is normally head.next. Try to get its * thread field, ensuring consistent reads: If thread * field is nulled out or s.prev is no longer head, then * some other thread(s) concurrently performed setHead in * between some of our reads. We try this twice before * resorting to traversal. */ Node h, s; ! Object st; if (((h = head) != null && (s = h.next) != null && ! s.prev == head && (st = s.strand) != null) || ((h = head) != null && (s = h.next) != null && ! s.prev == head && (st = s.strand) != null)) return st; /* * Head's next field might not have been set yet, or may have * been unset after setHead. So we must check to see if tail * is actually first node. If not, we continue on, safely * traversing from tail back to head to find first, * guaranteeing termination. */ ! Object firstStrand = null; for (Node p = tail; p != null && p != head; p = p.prev) { ! Object strand = p.strand; ! if (strand != null) ! firstStrand = strand; } ! return firstStrand; } /** * Returns true if the given thread is currently queued. *
*** 1001,1011 **** */ public final boolean isQueued(Thread thread) { if (thread == null) throw new NullPointerException(); for (Node p = tail; p != null; p = p.prev) ! if (p.thread == thread) return true; return false; } /** --- 1003,1013 ---- */ public final boolean isQueued(Thread thread) { if (thread == null) throw new NullPointerException(); for (Node p = tail; p != null; p = p.prev) ! if (p.strand == thread) return true; return false; } /**
*** 1020,1030 **** final boolean apparentlyFirstQueuedIsExclusive() { Node h, s; return (h = head) != null && (s = h.next) != null && !s.isShared() && ! s.thread != null; } /** * Queries whether any threads have been waiting to acquire longer * than the current thread. --- 1022,1032 ---- final boolean apparentlyFirstQueuedIsExclusive() { Node h, s; return (h = head) != null && (s = h.next) != null && !s.isShared() && ! s.strand != null; } /** * Queries whether any threads have been waiting to acquire longer * than the current thread.
*** 1076,1086 **** for (Node p = tail; p != h && p != null; p = p.prev) { if (p.waitStatus <= 0) s = p; } } ! if (s != null && s.thread != Thread.currentThread()) return true; } return false; } --- 1078,1088 ---- for (Node p = tail; p != h && p != null; p = p.prev) { if (p.waitStatus <= 0) s = p; } } ! if (s != null && s.strand != Strands.currentStrand()) return true; } return false; }
*** 1096,1106 **** * @return the estimated number of threads waiting to acquire */ public final int getQueueLength() { int n = 0; for (Node p = tail; p != null; p = p.prev) { ! if (p.thread != null) ++n; } return n; } --- 1098,1108 ---- * @return the estimated number of threads waiting to acquire */ public final int getQueueLength() { int n = 0; for (Node p = tail; p != null; p = p.prev) { ! if (p.strand != null) ++n; } return n; }
*** 1116,1128 **** * @return the collection of threads */ public final Collection<Thread> getQueuedThreads() { ArrayList<Thread> list = new ArrayList<>(); for (Node p = tail; p != null; p = p.prev) { ! Thread t = p.thread; ! if (t != null) ! list.add(t); } return list; } /** --- 1118,1130 ---- * @return the collection of threads */ public final Collection<Thread> getQueuedThreads() { ArrayList<Thread> list = new ArrayList<>(); for (Node p = tail; p != null; p = p.prev) { ! Object s = p.strand; ! if (s instanceof Thread) ! list.add((Thread)s); } return list; } /**
*** 1135,1147 **** */ public final Collection<Thread> getExclusiveQueuedThreads() { ArrayList<Thread> list = new ArrayList<>(); for (Node p = tail; p != null; p = p.prev) { if (!p.isShared()) { ! Thread t = p.thread; ! if (t != null) ! list.add(t); } } return list; } --- 1137,1149 ---- */ public final Collection<Thread> getExclusiveQueuedThreads() { ArrayList<Thread> list = new ArrayList<>(); for (Node p = tail; p != null; p = p.prev) { if (!p.isShared()) { ! Object s = p.strand; ! if (s instanceof Thread) ! list.add((Thread)s); } } return list; }
*** 1155,1167 **** */ public final Collection<Thread> getSharedQueuedThreads() { ArrayList<Thread> list = new ArrayList<>(); for (Node p = tail; p != null; p = p.prev) { if (p.isShared()) { ! Thread t = p.thread; ! if (t != null) ! list.add(t); } } return list; } --- 1157,1169 ---- */ public final Collection<Thread> getSharedQueuedThreads() { ArrayList<Thread> list = new ArrayList<>(); for (Node p = tail; p != null; p = p.prev) { if (p.isShared()) { ! Object s = p.strand; ! if (s instanceof Thread) ! list.add((Thread)s); } } return list; }
*** 1244,1254 **** * case the waitStatus can be transiently and harmlessly wrong). */ Node p = enq(node); int ws = p.waitStatus; if (ws > 0 || !p.compareAndSetWaitStatus(ws, Node.SIGNAL)) ! LockSupport.unpark(node.thread); return true; } /** * Transfers node, if necessary, to sync queue after a cancelled wait. --- 1246,1256 ---- * case the waitStatus can be transiently and harmlessly wrong). */ Node p = enq(node); int ws = p.waitStatus; if (ws > 0 || !p.compareAndSetWaitStatus(ws, Node.SIGNAL)) ! LockSupport.unpark(node.strand); return true; } /** * Transfers node, if necessary, to sync queue after a cancelled wait.
*** 1807,1819 **** if (!isHeldExclusively()) throw new IllegalMonitorStateException(); ArrayList<Thread> list = new ArrayList<>(); for (Node w = firstWaiter; w != null; w = w.nextWaiter) { if (w.waitStatus == Node.CONDITION) { ! Thread t = w.thread; ! if (t != null) ! list.add(t); } } return list; } } --- 1809,1821 ---- if (!isHeldExclusively()) throw new IllegalMonitorStateException(); ArrayList<Thread> list = new ArrayList<>(); for (Node w = firstWaiter; w != null; w = w.nextWaiter) { if (w.waitStatus == Node.CONDITION) { ! Object s = w.strand; ! if (s instanceof Thread) ! list.add((Thread)s); } } return list; } }
< prev index next >