Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/com/sun/tools/jdi/EventQueueImpl.java
38920 views
/*1* Copyright (c) 1998, 2006, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package com.sun.tools.jdi;2627import com.sun.jdi.*;28import com.sun.jdi.event.EventQueue;29import com.sun.jdi.event.EventSet;3031import java.util.*;3233public class EventQueueImpl extends MirrorImpl implements EventQueue {3435/*36* Note this is not a synchronized list. Iteration/update should be37* protected through the 'this' monitor.38*/39LinkedList<EventSet> eventSets = new LinkedList<EventSet>();4041TargetVM target;42boolean closed = false;4344EventQueueImpl(VirtualMachine vm, TargetVM target) {45super(vm);46this.target = target;47target.addEventQueue(this);48}4950/*51* Override superclass back to default equality52*/53public boolean equals(Object obj) {54return this == obj;55}5657public int hashCode() {58return System.identityHashCode(this);59}6061synchronized void enqueue(EventSet eventSet) {62eventSets.add(eventSet);63notifyAll();64}6566synchronized int size() {67return eventSets.size();68}6970synchronized void close() {71if (!closed) {72closed = true; // OK for this the be first since synchronized7374// place VMDisconnectEvent into queue75enqueue(new EventSetImpl(vm,76(byte)JDWP.EventKind.VM_DISCONNECTED));77}78}7980public EventSet remove() throws InterruptedException {81return remove(0);82}8384/**85* Filter out events not for user's eyes.86* Then filter out empty sets.87*/88public EventSet remove(long timeout) throws InterruptedException {89if (timeout < 0) {90throw new IllegalArgumentException("Timeout cannot be negative");91}9293EventSet eventSet;94while (true) {95EventSetImpl fullEventSet = removeUnfiltered(timeout);96if (fullEventSet == null) {97eventSet = null; // timeout98break;99}100/*101* Remove events from the event set for which102* there is no corresponding enabled request (103* this includes our internally requested events.)104* This never returns null105*/106eventSet = fullEventSet.userFilter();107if (!eventSet.isEmpty()) {108break;109}110}111112if ((eventSet != null) && (eventSet.suspendPolicy() == JDWP.SuspendPolicy.ALL)) {113vm.notifySuspend();114}115116return eventSet;117}118119EventSet removeInternal() throws InterruptedException {120EventSet eventSet;121do {122// Waiting forever, so removeUnfiltered() is never null123eventSet = removeUnfiltered(0).internalFilter();124} while (eventSet == null || eventSet.isEmpty());125126/*127* Currently, no internal events are requested with a suspend128* policy other than none, so we don't check for notifySuspend()129* here. If this changes in the future, there is much130* infrastructure that needs to be updated.131*/132133return eventSet;134}135136private TimerThread startTimerThread(long timeout) {137TimerThread thread = new TimerThread(timeout);138thread.setDaemon(true);139thread.start();140return thread;141}142143private boolean shouldWait(TimerThread timerThread) {144return !closed && eventSets.isEmpty() &&145((timerThread == null) ? true : !timerThread.timedOut());146}147148private EventSetImpl removeUnfiltered(long timeout)149throws InterruptedException {150EventSetImpl eventSet = null;151152/*153* Make sure the VM has completed initialization before154* trying to build events.155*/156vm.waitInitCompletion();157158synchronized(this) {159if (!eventSets.isEmpty()) {160/*161* If there's already something there, no need162* for anything elaborate.163*/164eventSet = (EventSetImpl)eventSets.removeFirst();165} else {166/*167* If a timeout was specified, create a thread to168* notify this one when a timeout169* occurs. We can't use the timed version of wait()170* because it is possible for multiple enqueue() calls171* before we see something in the eventSet queue172* (this is possible when multiple threads call173* remove() concurrently -- not a great idea, but174* it should be supported). Even if enqueue() did a175* notify() instead of notifyAll() we are not able to176* use a timed wait because there's no way to distinguish177* a timeout from a notify. That limitation implies a178* possible race condition between a timed out thread179* and a notified thread.180*/181TimerThread timerThread = null;182try {183if (timeout > 0) {184timerThread = startTimerThread(timeout);185}186187while (shouldWait(timerThread)) {188this.wait();189}190} finally {191if ((timerThread != null) && !timerThread.timedOut()) {192timerThread.interrupt();193}194}195196if (eventSets.isEmpty()) {197if (closed) {198throw new VMDisconnectedException();199}200} else {201eventSet = (EventSetImpl)eventSets.removeFirst();202}203}204}205206// The build is synchronized on the event set, don't hold207// the queue lock.208if (eventSet != null) {209target.notifyDequeueEventSet();210eventSet.build();211}212return eventSet;213}214215private class TimerThread extends Thread {216private boolean timedOut = false;217private long timeout;218219TimerThread(long timeout) {220super(vm.threadGroupForJDI(), "JDI Event Queue Timer");221this.timeout = timeout;222}223224boolean timedOut() {225return timedOut;226}227228public void run() {229try {230Thread.sleep(timeout);231EventQueueImpl queue = EventQueueImpl.this;232synchronized(queue) {233timedOut = true;234queue.notifyAll();235}236} catch (InterruptedException e) {237// Exit without notifying238}239}240}241}242243244