Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/solaris/demo/jni/Poller/LinkedQueue.java
32287 views
/*1* Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.2*3* Redistribution and use in source and binary forms, with or without4* modification, are permitted provided that the following conditions5* are met:6*7* - Redistributions of source code must retain the above copyright8* notice, this list of conditions and the following disclaimer.9*10* - Redistributions in binary form must reproduce the above copyright11* notice, this list of conditions and the following disclaimer in the12* documentation and/or other materials provided with the distribution.13*14* - Neither the name of Oracle nor the names of its15* contributors may be used to endorse or promote products derived16* from this software without specific prior written permission.17*18* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS19* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,20* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR21* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR22* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,23* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,24* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR25* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF26* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING27* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS28* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.29*/3031/*32* This source code is provided to illustrate the usage of a given feature33* or technique and has been deliberately simplified. Additional steps34* required for a production-quality application, such as security checks,35* input validation and proper error handling, might not be present in36* this sample code.37*/383940/*41File: SLQ.java42Originally: LinkedQueue.java4344Originally written by Doug Lea and released into the public domain.45This may be used for any purposes whatsoever without acknowledgment.46Thanks for the assistance and support of Sun Microsystems Labs,47and everyone contributing, testing, and using this code.4849History:50Date Who What5111Jun1998 dl Create public version5225aug1998 dl added peek5310dec1998 dl added isEmpty5410jun1999 bc modified for isolated use55*/5657// Original was in package EDU.oswego.cs.dl.util.concurrent;5859/**60* A linked list based channel implementation,61* adapted from the TwoLockQueue class from CPJ.62* The algorithm avoids contention between puts63* and takes when the queue is not empty.64* Normally a put and a take can proceed simultaneously.65* (Although it does not allow multiple concurrent puts or takes.)66* This class tends to perform more efficently than67* other Channel implementations in producer/consumer68* applications.69* <p>[<a href="http://gee.cs.oswego.edu/dl/classes/EDU/oswego/cs/dl/util/concurrent/intro.html"> Introduction to this package. </a>]70**/7172public class LinkedQueue {737475/**76* Dummy header node of list. The first actual node, if it exists, is always77* at head_.next. After each take, the old first node becomes the head.78**/79protected LinkedNode head_;80protected int count_;81/**82* Helper monitor for managing access to last node, in case it is also first.83* last_ and waitingForTake_ ONLY used with synch on appendMonitor_84**/85protected final Object lastMonitor_ = new Object();8687/**88* The last node of list. Put() appends to list, so modifies last_89**/90protected LinkedNode last_;9192/**93* The number of threads waiting for a take.94* Notifications are provided in put only if greater than zero.95* The bookkeeping is worth it here since in reasonably balanced96* usages, the notifications will hardly ever be necessary, so97* the call overhead to notify can be eliminated.98**/99protected int waitingForTake_ = 0;100101public LinkedQueue() {102head_ = new LinkedNode(null);103last_ = head_;104count_ = 0;105}106107/** Main mechanics for put/offer **/108protected void insert(Object x) {109synchronized(lastMonitor_) {110LinkedNode p = new LinkedNode(x);111last_.next = p;112last_ = p;113count_++;114if (count_ > 1000 && (count_ % 1000 == 0))115System.out.println("In Queue : " + count_);116if (waitingForTake_ > 0)117lastMonitor_.notify();118}119}120121/** Main mechanics for take/poll **/122protected synchronized Object extract() {123Object x = null;124LinkedNode first = head_.next;125if (first != null) {126x = first.value;127first.value = null;128head_ = first;129count_ --;130}131return x;132}133134135public void put(Object x) throws InterruptedException {136if (x == null) throw new IllegalArgumentException();137if (Thread.interrupted()) throw new InterruptedException();138insert(x);139}140141public boolean offer(Object x, long msecs) throws InterruptedException {142if (x == null) throw new IllegalArgumentException();143if (Thread.interrupted()) throw new InterruptedException();144insert(x);145return true;146}147148public Object take() throws InterruptedException {149if (Thread.interrupted()) throw new InterruptedException();150// try to extract. If fail, then enter wait-based retry loop151Object x = extract();152if (x != null)153return x;154else {155synchronized(lastMonitor_) {156try {157++waitingForTake_;158for (;;) {159x = extract();160if (x != null) {161--waitingForTake_;162return x;163}164else {165lastMonitor_.wait();166}167}168}169catch(InterruptedException ex) {170--waitingForTake_;171lastMonitor_.notify();172throw ex;173}174}175}176}177178public synchronized Object peek() {179LinkedNode first = head_.next;180if (first != null)181return first.value;182else183return null;184}185186187public synchronized boolean isEmpty() {188return head_.next == null;189}190191public Object poll(long msecs) throws InterruptedException {192if (Thread.interrupted()) throw new InterruptedException();193Object x = extract();194if (x != null)195return x;196else {197synchronized(lastMonitor_) {198try {199long waitTime = msecs;200long start = (msecs <= 0)? 0 : System.currentTimeMillis();201++waitingForTake_;202for (;;) {203x = extract();204if (x != null || waitTime <= 0) {205--waitingForTake_;206return x;207}208else {209lastMonitor_.wait(waitTime);210waitTime = msecs - (System.currentTimeMillis() - start);211}212}213}214catch(InterruptedException ex) {215--waitingForTake_;216lastMonitor_.notify();217throw ex;218}219}220}221}222223class LinkedNode {224Object value;225LinkedNode next = null;226LinkedNode(Object x) { value = x; }227LinkedNode(Object x, LinkedNode n) { value = x; next = n; }228}229}230231232