KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > debug > internal > ui > viewers > update > ThreadEventHandler


1 /*******************************************************************************
2  * Copyright (c) 2005, 2007 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.debug.internal.ui.viewers.update;
12
13 import java.util.HashMap JavaDoc;
14 import java.util.LinkedHashSet JavaDoc;
15 import java.util.Map JavaDoc;
16 import java.util.Set JavaDoc;
17
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.ILaunchManager;
23 import org.eclipse.debug.core.model.IDebugTarget;
24 import org.eclipse.debug.core.model.IStackFrame;
25 import org.eclipse.debug.core.model.IThread;
26 import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelDelta;
27 import org.eclipse.debug.internal.ui.viewers.model.provisional.ModelDelta;
28 import org.eclipse.debug.internal.ui.viewers.provisional.AbstractModelProxy;
29
30 /**
31  * @since 3.2
32  */

33 public class ThreadEventHandler extends DebugEventHandler {
34     
35     /**
36      * Queue of suspended threads to choose from when needing
37      * to select a thread when another is resumed. Threads
38      * are added in the order they suspend.
39      */

40     private Set JavaDoc fThreadQueue = new LinkedHashSet JavaDoc();
41     
42     /**
43      * Map of previous TOS per thread
44      */

45     private Map JavaDoc fLastTopFrame = new HashMap JavaDoc();
46     /**
47      * Constructs and event handler for a threads in the given viewer.
48      *
49      * @param viewer
50      */

51     public ThreadEventHandler(AbstractModelProxy proxy) {
52         super(proxy);
53     }
54
55     /* (non-Javadoc)
56      * @see org.eclipse.debug.internal.ui.viewers.update.DebugEventHandler#dispose()
57      */

58     public synchronized void dispose() {
59         fLastTopFrame.clear();
60         fThreadQueue.clear();
61         super.dispose();
62     }
63
64     protected void handleSuspend(DebugEvent event) {
65         IThread thread = (IThread) event.getSource();
66         if (event.isEvaluation()) {
67             ModelDelta delta = buildRootDelta();
68             ModelDelta node = addPathToThread(delta, thread);
69             node = node.addNode(thread, IModelDelta.NO_CHANGE);
70             try {
71                 IStackFrame frame = thread.getTopStackFrame();
72                 if (frame != null) {
73                     int flag = IModelDelta.NO_CHANGE;
74                     if (event.getDetail() == DebugEvent.EVALUATION) {
75                         // explicit evaluations can change content
76
flag = flag | IModelDelta.CONTENT;
77                     } else if (event.getDetail() == DebugEvent.EVALUATION_IMPLICIT) {
78                         // implicit evaluations can change state
79
flag = flag | IModelDelta.STATE;
80                     }
81                     node.addNode(frame, flag);
82                     fireDelta(delta);
83                 }
84             } catch (DebugException e) {
85             }
86         } else {
87             queueSuspendedThread(event);
88             int extras = IModelDelta.STATE;
89             if (event.getDetail() == DebugEvent.BREAKPOINT | event.getDetail() == DebugEvent.CLIENT_REQUEST) {
90                 extras = IModelDelta.EXPAND;
91             }
92             fireDeltaUpdatingTopFrame(thread, IModelDelta.NO_CHANGE | extras, event);
93         }
94     }
95     
96     private boolean isEqual(Object JavaDoc o1, Object JavaDoc o2) {
97         if (o1 == o2) {
98             return true;
99         }
100         if (o1 == null) {
101             return false;
102         }
103         return o1.equals(o2);
104     }
105
106     protected void handleResume(DebugEvent event) {
107         IThread thread = removeSuspendedThread(event);
108         fireDeltaAndClearTopFrame(thread, IModelDelta.STATE | IModelDelta.CONTENT | IModelDelta.SELECT);
109         thread = getNextSuspendedThread();
110         if (thread != null) {
111             fireDeltaUpdatingTopFrame(thread, IModelDelta.NO_CHANGE, event);
112         }
113     }
114
115     protected void handleCreate(DebugEvent event) {
116         fireDeltaAndClearTopFrame((IThread) event.getSource(), IModelDelta.ADDED | IModelDelta.STATE);
117     }
118
119     protected void handleTerminate(DebugEvent event) {
120         IThread thread = (IThread) event.getSource();
121         IDebugTarget target = thread.getDebugTarget();
122         // ignore thread termination if target is terminated/disconnected
123
if (!(target.isTerminated() || target.isDisconnected())) {
124             fireDeltaAndClearTopFrame(thread, IModelDelta.REMOVED);
125         }
126     }
127
128     protected void handleChange(DebugEvent event) {
129         if (event.getDetail() == DebugEvent.STATE) {
130             fireDeltaUpdatingThread((IThread) event.getSource(), IModelDelta.STATE);
131         } else {
132             fireDeltaUpdatingThread((IThread) event.getSource(), IModelDelta.CONTENT);
133         }
134     }
135
136     protected void handleLateSuspend(DebugEvent suspend, DebugEvent resume) {
137         IThread thread = queueSuspendedThread(suspend);
138         if (suspend.isEvaluation() && suspend.getDetail() == DebugEvent.EVALUATION_IMPLICIT) {
139             // late implicit evaluation - update thread and frame
140
ModelDelta delta = buildRootDelta();
141             ModelDelta node = addPathToThread(delta, thread);
142             node = node.addNode(thread, IModelDelta.STATE);
143             try {
144                 IStackFrame frame = thread.getTopStackFrame();
145                 if (frame != null) {
146                     node.addNode(frame, IModelDelta.STATE);
147                     fireDelta(delta);
148                 }
149             } catch (DebugException e) {
150             }
151         } else {
152             fireDeltaUpdatingTopFrame(thread, IModelDelta.CONTENT | IModelDelta.EXPAND, resume);
153         }
154     }
155
156     protected void handleSuspendTimeout(DebugEvent event) {
157         IThread thread = removeSuspendedThread(event);
158         // don't collapse thread when waiting for long step or evaluation to complete
159
fireDeltaUpdatingThread(thread, IModelDelta.STATE);
160     }
161     
162     protected ModelDelta buildRootDelta() {
163         return new ModelDelta(getLaunchManager(), IModelDelta.NO_CHANGE);
164     }
165
166     /**
167      * Returns the launch manager.
168      *
169      * @return the launch manager
170      */

171     protected ILaunchManager getLaunchManager() {
172         return DebugPlugin.getDefault().getLaunchManager();
173     }
174     
175     /**
176      * Adds nodes into the delta up to but not including the given thread.
177      *
178      * @param delta root delta for the view (includes viewer input)
179      * @param thread thread for which path is requested
180      * @return
181      */

182     protected ModelDelta addPathToThread(ModelDelta delta, IThread thread) {
183         ILaunch launch = thread.getLaunch();
184         Object JavaDoc[] children = launch.getChildren();
185         delta = delta.addNode(launch, indexOf(getLaunchManager().getLaunches(), launch), IModelDelta.NO_CHANGE, children.length);
186         IDebugTarget debugTarget = thread.getDebugTarget();
187         int numThreads = -1;
188         try {
189             numThreads = debugTarget.getThreads().length;
190         } catch (DebugException e) {
191         }
192         return delta.addNode(debugTarget, indexOf(children, debugTarget), IModelDelta.NO_CHANGE, numThreads);
193     }
194
195     private void fireDeltaAndClearTopFrame(IThread thread, int flags) {
196         ModelDelta delta = buildRootDelta();
197         ModelDelta node = addPathToThread(delta, thread);
198         node.addNode(thread, flags);
199         synchronized (this) {
200             fLastTopFrame.remove(thread);
201         }
202         fireDelta(delta);
203     }
204     
205     private void fireDeltaUpdatingTopFrame(IThread thread, int flags, DebugEvent event) {
206         ModelDelta delta = buildRootDelta();
207         ModelDelta node = addPathToThread(delta, thread);
208         IStackFrame prev = null;
209         synchronized (this) {
210              prev = (IStackFrame) fLastTopFrame.get(thread);
211         }
212         IStackFrame frame = null;
213         try {
214              frame = thread.getTopStackFrame();
215         } catch (DebugException e) {
216         }
217         int threadIndex = indexOf(thread);
218         int childCount = childCount(thread);
219         if (isEqual(frame, prev)) {
220             if (frame == null) {
221                 if (thread.isSuspended()) {
222                     // no frames, but suspended - update & select
223
node = node.addNode(thread, threadIndex, flags | IModelDelta.STATE | IModelDelta.SELECT, childCount);
224                 }
225             } else {
226                 node = node.addNode(thread, threadIndex, flags, childCount);
227             }
228         } else {
229             if (prev == null && event.getDetail() == DebugEvent.STEP_END) {
230                 // see bug 166602 - expand the thread if this is a step end with no previous top frame
231
flags = flags | IModelDelta.EXPAND;
232             }
233             node = node.addNode(thread, threadIndex, flags | IModelDelta.CONTENT, childCount);
234         }
235         if (frame != null) {
236             node.addNode(frame, indexOf(frame), IModelDelta.STATE | IModelDelta.SELECT, childCount(frame));
237         }
238         synchronized (this) {
239             if (!isDisposed()) {
240                 fLastTopFrame.put(thread, frame);
241             }
242         }
243         fireDelta(delta);
244     }
245     
246     /**
247      * Returns the index of the given thread, relative to its parent in the view.
248      *
249      * @param thread thread
250      * @return index of the thread, relative to its parent
251      */

252     protected int indexOf(IThread thread) {
253         try {
254             return indexOf(thread.getDebugTarget().getThreads(), thread);
255         } catch (DebugException e) {
256         }
257         return -1;
258     }
259     
260     /**
261      * Returns the index of the given frame, relative to its parent in the view.
262      *
263      * @param frame frame
264      * @return index of the frame, relative to its thread
265      */

266     protected int indexOf(IStackFrame frame) {
267         return 0;
268     }
269     
270     /**
271      * Returns the number of children the given thread has in the view.
272      *
273      * @param thread thread
274      * @return number of children
275      */

276     protected int childCount(IThread thread) {
277         try {
278             return thread.getStackFrames().length;
279         } catch (DebugException e) {
280         }
281         return -1;
282     }
283     
284     /**
285      * Returns the number of children the given frame has in the view.
286      *
287      * @param frame frame
288      * @return child count
289      */

290     protected int childCount(IStackFrame frame) {
291         return 0;
292     }
293     
294     private void fireDeltaUpdatingThread(IThread thread, int flags) {
295         ModelDelta delta = buildRootDelta();
296         ModelDelta node = addPathToThread(delta, thread);
297         node = node.addNode(thread, flags);
298         fireDelta(delta);
299     }
300     
301     protected boolean handlesEvent(DebugEvent event) {
302         return event.getSource() instanceof IThread;
303     }
304     
305     protected synchronized IThread queueSuspendedThread(DebugEvent event) {
306         IThread thread = (IThread) event.getSource();
307         if (!isDisposed()) {
308             fThreadQueue.add(thread);
309         }
310         return thread;
311     }
312     
313     protected synchronized IThread removeSuspendedThread(DebugEvent event) {
314         IThread thread = (IThread)event.getSource();
315         fThreadQueue.remove(thread);
316         return thread;
317     }
318     
319     protected synchronized IThread queueSuspendedThread(IThread thread) {
320         if (!isDisposed()) {
321             fThreadQueue.add(thread);
322         }
323         return thread;
324     }
325     
326     protected synchronized void removeQueuedThread(IThread thread) {
327         fThreadQueue.remove(thread);
328     }
329     
330     protected synchronized IThread getNextSuspendedThread() {
331         if (!fThreadQueue.isEmpty()) {
332             return (IThread) fThreadQueue.iterator().next();
333         }
334         return null;
335     }
336
337 }
338
Popular Tags