History

My first initial commit with all of mine experimental changes.

Dmitry Kabak (userdima committed 13 years ago

Commit d37b88d1 parent 3f5b46618352 files · +2598093 −-8690Browse files

Showing the changes to java/pkg/com/sun/tools/jdi/EventQueueImpl.java (1 of 18352 files). Show all

Unified · Split

java/pkg/com/sun/tools/jdi/EventQueueImpl.java+242−0
@@ -0,0 +1,242 @@
1+/*
2+ * Copyright (c) 1998, 2006, Oracle and/or its affiliates. All rights reserved.
3+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+ *
5+ * This code is free software; you can redistribute it and/or modify it
6+ * under the terms of the GNU General Public License version 2 only, as
7+ * published by the Free Software Foundation. Oracle designates this
8+ * particular file as subject to the "Classpath" exception as provided
9+ * by Oracle in the LICENSE file that accompanied this code.
10+ *
11+ * This code is distributed in the hope that it will be useful, but WITHOUT
12+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+ * version 2 for more details (a copy is included in the LICENSE file that
15+ * accompanied this code).
16+ *
17+ * You should have received a copy of the GNU General Public License version
18+ * 2 along with this work; if not, write to the Free Software Foundation,
19+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+ *
21+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+ * or visit www.oracle.com if you need additional information or have any
23+ * questions.
24+ */
25+
26+package com.sun.tools.jdi;
27+
28+import com.sun.jdi.*;
29+import com.sun.jdi.event.EventQueue;
30+import com.sun.jdi.event.EventSet;
31+
32+import java.util.*;
33+
34+public class EventQueueImpl extends MirrorImpl implements EventQueue {
35+
36+ /*
37+ * Note this is not a synchronized list. Iteration/update should be
38+ * protected through the 'this' monitor.
39+ */
40+ LinkedList<EventSet> eventSets = new LinkedList<EventSet>();
41+
42+ TargetVM target;
43+ boolean closed = false;
44+
45+ EventQueueImpl(VirtualMachine vm, TargetVM target) {
46+ super(vm);
47+ this.target = target;
48+ target.addEventQueue(this);
49+ }
50+
51+ /*
52+ * Override superclass back to default equality
53+ */
54+ public boolean equals(Object obj) {
55+ return this == obj;
56+ }
57+
58+ public int hashCode() {
59+ return System.identityHashCode(this);
60+ }
61+
62+ synchronized void enqueue(EventSet eventSet) {
63+ eventSets.add(eventSet);
64+ notifyAll();
65+ }
66+
67+ synchronized int size() {
68+ return eventSets.size();
69+ }
70+
71+ synchronized void close() {
72+ if (!closed) {
73+ closed = true; // OK for this the be first since synchronized
74+
75+ // place VMDisconnectEvent into queue
76+ enqueue(new EventSetImpl(vm,
77+ (byte)JDWP.EventKind.VM_DISCONNECTED));
78+ }
79+ }
80+
81+ public EventSet remove() throws InterruptedException {
82+ return remove(0);
83+ }
84+
85+ /**
86+ * Filter out events not for user's eyes.
87+ * Then filter out empty sets.
88+ */
89+ public EventSet remove(long timeout) throws InterruptedException {
90+ if (timeout < 0) {
91+ throw new IllegalArgumentException("Timeout cannot be negative");
92+ }
93+
94+ EventSet eventSet;
95+ while (true) {
96+ EventSetImpl fullEventSet = removeUnfiltered(timeout);
97+ if (fullEventSet == null) {
98+ eventSet = null; // timeout
99+ break;
100+ }
101+ /*
102+ * Remove events from the event set for which
103+ * there is no corresponding enabled request (
104+ * this includes our internally requested events.)
105+ * This never returns null
106+ */
107+ eventSet = fullEventSet.userFilter();
108+ if (!eventSet.isEmpty()) {
109+ break;
110+ }
111+ }
112+
113+ if ((eventSet != null) && (eventSet.suspendPolicy() == JDWP.SuspendPolicy.ALL)) {
114+ vm.notifySuspend();
115+ }
116+
117+ return eventSet;
118+ }
119+
120+ EventSet removeInternal() throws InterruptedException {
121+ EventSet eventSet;
122+ do {
123+ // Waiting forever, so removeUnfiltered() is never null
124+ eventSet = removeUnfiltered(0).internalFilter();
125+ } while (eventSet == null || eventSet.isEmpty());
126+
127+ /*
128+ * Currently, no internal events are requested with a suspend
129+ * policy other than none, so we don't check for notifySuspend()
130+ * here. If this changes in the future, there is much
131+ * infrastructure that needs to be updated.
132+ */
133+
134+ return eventSet;
135+ }
136+
137+ private TimerThread startTimerThread(long timeout) {
138+ TimerThread thread = new TimerThread(timeout);
139+ thread.setDaemon(true);
140+ thread.start();
141+ return thread;
142+ }
143+
144+ private boolean shouldWait(TimerThread timerThread) {
145+ return !closed && eventSets.isEmpty() &&
146+ ((timerThread == null) ? true : !timerThread.timedOut());
147+ }
148+
149+ private EventSetImpl removeUnfiltered(long timeout)
150+ throws InterruptedException {
151+ EventSetImpl eventSet = null;
152+
153+ /*
154+ * Make sure the VM has completed initialization before
155+ * trying to build events.
156+ */
157+ vm.waitInitCompletion();
158+
159+ synchronized(this) {
160+ if (!eventSets.isEmpty()) {
161+ /*
162+ * If there's already something there, no need
163+ * for anything elaborate.
164+ */
165+ eventSet = (EventSetImpl)eventSets.removeFirst();
166+ } else {
167+ /*
168+ * If a timeout was specified, create a thread to
169+ * notify this one when a timeout
170+ * occurs. We can't use the timed version of wait()
171+ * because it is possible for multiple enqueue() calls
172+ * before we see something in the eventSet queue
173+ * (this is possible when multiple threads call
174+ * remove() concurrently -- not a great idea, but
175+ * it should be supported). Even if enqueue() did a
176+ * notify() instead of notifyAll() we are not able to
177+ * use a timed wait because there's no way to distinguish
178+ * a timeout from a notify. That limitation implies a
179+ * possible race condition between a timed out thread
180+ * and a notified thread.
181+ */
182+ TimerThread timerThread = null;
183+ try {
184+ if (timeout > 0) {
185+ timerThread = startTimerThread(timeout);
186+ }
187+
188+ while (shouldWait(timerThread)) {
189+ this.wait();
190+ }
191+ } finally {
192+ if ((timerThread != null) && !timerThread.timedOut()) {
193+ timerThread.interrupt();
194+ }
195+ }
196+
197+ if (eventSets.isEmpty()) {
198+ if (closed) {
199+ throw new VMDisconnectedException();
200+ }
201+ } else {
202+ eventSet = (EventSetImpl)eventSets.removeFirst();
203+ }
204+ }
205+ }
206+
207+ // The build is synchronized on the event set, don't hold
208+ // the queue lock.
209+ if (eventSet != null) {
210+ target.notifyDequeueEventSet();
211+ eventSet.build();
212+ }
213+ return eventSet;
214+ }
215+
216+ private class TimerThread extends Thread {
217+ private boolean timedOut = false;
218+ private long timeout;
219+
220+ TimerThread(long timeout) {
221+ super(vm.threadGroupForJDI(), "JDI Event Queue Timer");
222+ this.timeout = timeout;
223+ }
224+
225+ boolean timedOut() {
226+ return timedOut;
227+ }
228+
229+ public void run() {
230+ try {
231+ Thread.sleep(timeout);
232+ EventQueueImpl queue = EventQueueImpl.this;
233+ synchronized(queue) {
234+ timedOut = true;
235+ queue.notifyAll();
236+ }
237+ } catch (InterruptedException e) {
238+ // Exit without notifying
239+ }
240+ }
241+ }
242+}