KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jdt > internal > debug > ui > monitors > JavaMonitorThread


1 /*******************************************************************************
2  * Copyright (c) 2004, 2005 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11 package org.eclipse.jdt.internal.debug.ui.monitors;
12
13 import java.util.ArrayList JavaDoc;
14 import java.util.Iterator JavaDoc;
15 import java.util.List JavaDoc;
16
17 import org.eclipse.core.runtime.PlatformObject;
18 import org.eclipse.debug.core.DebugEvent;
19 import org.eclipse.debug.core.DebugException;
20 import org.eclipse.debug.core.DebugPlugin;
21 import org.eclipse.debug.core.ILaunch;
22 import org.eclipse.debug.core.model.IDebugTarget;
23 import org.eclipse.debug.core.model.IThread;
24 import org.eclipse.jdt.debug.core.IJavaObject;
25 import org.eclipse.jdt.debug.core.IJavaThread;
26
27 import com.sun.jdi.IncompatibleThreadStateException;
28
29 /**
30  * Represent a Java thread in the threads and monitors model.
31  */

32 public class JavaMonitorThread extends PlatformObject {
33     
34     /**
35      * The underlying thread.
36      */

37     private IJavaThread fThread;
38
39     private IThread fOriginalThread;
40     
41     /**
42      * The monitor this thread is waiting for.
43      */

44     private JavaMonitor fContendedMonitor;
45     /**
46      * The monitors owned by this thread.
47      */

48     private JavaMonitor[] fOwnedMonitors= new JavaMonitor[0];
49     /**
50      * Indicate if this thread is currently part of a deadlock.
51      */

52     private boolean fIsInDeadlock;
53     /**
54      * Indicate that the information for this thread need to be update, it
55      * may have changed.
56      */

57     private boolean fToUpdate= true;
58     
59     /**
60      * List of JavaOwningThread and JavaWaitingThread associated with this thread.
61      */

62     private List JavaDoc fElements= new ArrayList JavaDoc();
63
64     /**
65      * JavaWaitingThread object used to return the JavaOwnedMonitor for this
66      * thread.
67      */

68     private JavaWaitingThread fBaseWaitingThread;
69     /**
70      * JavaOwningThread object uset to return the JavaWaitingMonitor for this
71      * thread.
72      */

73     private JavaOwningThread fBaseOwningThread;
74
75     public JavaMonitorThread(IJavaThread underlyingThread, IThread originalThread) {
76         fThread= underlyingThread;
77         fOriginalThread= originalThread;
78     }
79     
80     public IJavaThread getThread() {
81         return fThread;
82     }
83     
84     public IThread getOriginalThread() {
85         return fOriginalThread;
86     }
87     
88     protected void setOriginalThread(IThread originalThread) {
89         fOriginalThread= originalThread;
90     }
91
92     /**
93      * @see org.eclipse.debug.core.model.IDebugElement#getModelIdentifier()
94      */

95     public String JavaDoc getModelIdentifier() {
96         return fThread.getModelIdentifier();
97     }
98
99     /**
100      * @see org.eclipse.debug.core.model.IDebugElement#getDebugTarget()
101      */

102     public IDebugTarget getDebugTarget() {
103         return fThread.getDebugTarget();
104     }
105
106     /**
107      * @see org.eclipse.debug.core.model.IDebugElement#getLaunch()
108      */

109     public ILaunch getLaunch() {
110         return fThread.getLaunch();
111     }
112     
113     /**
114      * @see org.eclipse.debug.core.model.ISuspendResume#isSuspended()
115      */

116     public boolean isSuspended() {
117         return fThread.isSuspended();
118     }
119     
120     /**
121      * Returns the contended monitor to be used as a child
122      * of the underlying thread in the debug launch view.
123      */

124     public JavaContendedMonitor getContendedMonitor() {
125         if (fBaseOwningThread == null) {
126             fBaseOwningThread= new JavaOwningThread(this, null);
127         }
128         return fBaseOwningThread.getContendedMonitor();
129     }
130
131     /**
132      * Returns the owned monitors to be used as children
133      * of the underlying thread in the debug launch view.
134      */

135     public JavaOwnedMonitor[] getOwnedMonitors() {
136         if (fBaseWaitingThread == null) {
137             fBaseWaitingThread= new JavaWaitingThread(this, null);
138         }
139         return fBaseWaitingThread.getOwnedMonitors();
140     }
141     
142     /**
143      * Returns the monitor this thread is waiting for.
144      */

145     protected JavaMonitor getContendedMonitor0() {
146         if (fToUpdate) {
147             update();
148         }
149         return fContendedMonitor;
150     }
151     
152     /**
153      * Returns the monitors owned by this thread.
154      */

155     protected JavaMonitor[] getOwnedMonitors0() {
156         if (fToUpdate) {
157             update();
158         }
159         return fOwnedMonitors;
160     }
161     
162     /**
163      * Update the information for this thread.
164      * @return <code>true</code> if the contended monitor or
165      * the owned monitors changed.
166      */

167     private boolean update() {
168         boolean changed= false;
169         synchronized(this) {
170             if (!fToUpdate) {
171                 return false;
172             }
173             try {
174                 // update the contended monitor
175
IJavaObject contendedMonitor= fThread.getContendedMonitor();
176                 if (contendedMonitor == null) {
177                     changed= fContendedMonitor != null;
178                     fContendedMonitor= null;
179                 } else {
180                     changed= fContendedMonitor == null || !contendedMonitor.equals(fContendedMonitor.getMonitor());
181                     fContendedMonitor= ThreadMonitorManager.getDefault().getJavaMonitor(contendedMonitor);
182                 }
183                 // update the owned monitors
184
IJavaObject[] ownedMonitors= fThread.getOwnedMonitors();
185                 if (ownedMonitors == null || ownedMonitors.length == 0) {
186                     // no owned monitor, not much to do
187
changed= fOwnedMonitors != null && fOwnedMonitors.length != 0;
188                     fOwnedMonitors= new JavaMonitor[0];
189                 } else {
190                     JavaMonitor[] tmp= new JavaMonitor[ownedMonitors.length];
191                     ThreadMonitorManager threadMonitorManager= ThreadMonitorManager.getDefault();
192                     if (changed || fOwnedMonitors.length != ownedMonitors.length) {
193                         // if we know it changed, we can just create the new list.
194
for (int i= 0; i < ownedMonitors.length; i++) {
195                             tmp[i]= threadMonitorManager.getJavaMonitor(ownedMonitors[i]);
196                         }
197                         changed= true;
198                     } else {
199                         // we need to check in the new list contains the same monitors as the
200
// previous list
201
int sameMonitor= 0;
202                         for (int i= 0; i < ownedMonitors.length; i++) {
203                             for (int j= 0; j < fOwnedMonitors.length; j++) {
204                                 if (ownedMonitors[i].equals(fOwnedMonitors[i].getMonitor())) {
205                                     sameMonitor++;
206                                     break;
207                                 }
208                             }
209                             tmp[i]= threadMonitorManager.getJavaMonitor(ownedMonitors[i]);
210                         }
211                         changed= sameMonitor != ownedMonitors.length;
212                     }
213                     fOwnedMonitors= tmp;
214                 }
215             } catch (DebugException e) {
216                 Throwable JavaDoc cause= e.getStatus().getException();
217                 if (!(cause instanceof IncompatibleThreadStateException)) {
218                     // IncompatibleThreadStateException are expected from Sun VMs
219
// if the thread is not suspended.
220
// For all other exceptions, null the values.
221
fContendedMonitor= null;
222                     changed= fOwnedMonitors != null && fOwnedMonitors.length != 0;
223                     fOwnedMonitors= new JavaMonitor[0];
224                 }
225             } finally {
226                 fToUpdate= false;
227             }
228         }
229         if (changed) {
230             fireChangeEvent(DebugEvent.CONTENT);
231         }
232         return changed;
233     }
234     
235     /**
236      * send a change event for theJavaWaitingThread and JavaOwningThread
237      * associated with this thread
238      */

239     private void fireChangeEvent(int detail) {
240         Object JavaDoc[] elements= fElements.toArray();
241         List JavaDoc changedElement= new ArrayList JavaDoc();
242         if (fOriginalThread != null) {
243             changedElement.add(fOriginalThread);
244         }
245         for (int i= 0; i < elements.length; i++) {
246             Object JavaDoc element= elements[i];
247             // the two 'base' elements are not part of the hierarchy, they are
248
// used to get the children of the Thread.
249
if (element != fBaseOwningThread && element != fBaseWaitingThread) {
250                 changedElement.add(element);
251             }
252         }
253         DebugEvent[] changeEvents= new DebugEvent[changedElement.size()];
254         int i= 0;
255         for (Iterator JavaDoc iter= changedElement.iterator(); iter.hasNext();) {
256             changeEvents[i++]= new DebugEvent(iter.next(), DebugEvent.CHANGE, detail);
257         }
258         DebugPlugin.getDefault().fireDebugEventSet(changeEvents);
259     }
260
261     public synchronized void setToUpdate() {
262         if (!fToUpdate) {
263             fToUpdate= true;
264             if (fContendedMonitor != null) {
265                 fContendedMonitor.setToUpdate();
266             }
267             if (fOwnedMonitors != null) {
268                 for (int i= 0; i < fOwnedMonitors.length; i++) {
269                     fOwnedMonitors[i].setToUpdate();
270                 }
271             }
272         }
273     }
274     
275     protected void addElement(JavaOwningThread thread) {
276         fElements.add(thread);
277     }
278     
279     protected void addElement(JavaWaitingThread thread) {
280         fElements.add(thread);
281     }
282     
283     public void refresh() {
284         if (fToUpdate && !update()) {
285             if (fContendedMonitor != null) {
286                 fContendedMonitor.refresh();
287             }
288             for (int i= 0; i < fOwnedMonitors.length; i++) {
289                 fOwnedMonitors[i].refresh();
290             }
291         }
292     }
293     
294     /**
295      * Indicate if this thread is currently part of a deadlock
296      */

297     public boolean isInDeadlock() {
298         return fIsInDeadlock;
299     }
300     /**
301      * Set this thread as being part of a deadlock.
302      */

303     public void setInDeadlock(boolean isInDeadlock) {
304         boolean oldValue= fIsInDeadlock;
305         fIsInDeadlock = isInDeadlock;
306         if (oldValue != isInDeadlock) {
307             fireChangeEvent(DebugEvent.STATE);
308         }
309     }
310 }
311
Popular Tags