PageRenderTime 24ms CodeModel.GetById 15ms RepoModel.GetById 1ms app.codeStats 0ms

/projects/eclipse_SDK-3.7.1/plugins/org.eclipse.debug.ui.source_3.7.101.v20110817_r371/org/eclipse/debug/internal/ui/viewers/update/ThreadEventHandler.java

https://gitlab.com/essere.lab.public/qualitas.class-corpus
Java | 357 lines | 252 code | 31 blank | 74 comment | 50 complexity | ec4ef4eb9c57d836ef033f7478c17b9f MD5 | raw file
  1. /*******************************************************************************
  2. * Copyright (c) 2005, 2009 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. import java.util.HashMap;
  13. import java.util.LinkedHashSet;
  14. import java.util.Map;
  15. import java.util.Set;
  16. import org.eclipse.debug.core.DebugEvent;
  17. import org.eclipse.debug.core.DebugException;
  18. import org.eclipse.debug.core.DebugPlugin;
  19. import org.eclipse.debug.core.ILaunch;
  20. import org.eclipse.debug.core.ILaunchManager;
  21. import org.eclipse.debug.core.model.IDebugTarget;
  22. import org.eclipse.debug.core.model.IStackFrame;
  23. import org.eclipse.debug.core.model.IThread;
  24. import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelDelta;
  25. import org.eclipse.debug.internal.ui.viewers.model.provisional.ModelDelta;
  26. import org.eclipse.debug.internal.ui.viewers.provisional.AbstractModelProxy;
  27. /**
  28. * @since 3.2
  29. */
  30. public class ThreadEventHandler extends DebugEventHandler {
  31. /**
  32. * Queue of suspended threads to choose from when needing
  33. * to select a thread when another is resumed. Threads
  34. * are added in the order they suspend.
  35. */
  36. private Set fThreadQueue = new LinkedHashSet();
  37. /**
  38. * Map of previous TOS per thread
  39. */
  40. private Map fLastTopFrame = new HashMap();
  41. /**
  42. * Constructs and event handler for a threads in the given viewer.
  43. *
  44. * @param viewer
  45. */
  46. public ThreadEventHandler(AbstractModelProxy proxy) {
  47. super(proxy);
  48. }
  49. /* (non-Javadoc)
  50. * @see org.eclipse.debug.internal.ui.viewers.update.DebugEventHandler#dispose()
  51. */
  52. public synchronized void dispose() {
  53. fLastTopFrame.clear();
  54. fThreadQueue.clear();
  55. super.dispose();
  56. }
  57. protected void handleSuspend(DebugEvent event) {
  58. IThread thread = (IThread) event.getSource();
  59. if (event.isEvaluation()) {
  60. ModelDelta delta = buildRootDelta();
  61. ModelDelta node = addPathToThread(delta, thread);
  62. node = node.addNode(thread, IModelDelta.NO_CHANGE);
  63. try {
  64. IStackFrame frame = thread.getTopStackFrame();
  65. if (frame != null) {
  66. int flag = IModelDelta.NO_CHANGE;
  67. if (event.getDetail() == DebugEvent.EVALUATION) {
  68. // explicit evaluations can change content
  69. flag = flag | IModelDelta.CONTENT;
  70. } else if (event.getDetail() == DebugEvent.EVALUATION_IMPLICIT) {
  71. // implicit evaluations can change state
  72. flag = flag | IModelDelta.STATE;
  73. }
  74. node.addNode(frame, flag);
  75. fireDelta(delta);
  76. }
  77. } catch (DebugException e) {
  78. }
  79. } else {
  80. queueSuspendedThread(event);
  81. int extras = IModelDelta.STATE;
  82. switch (event.getDetail()) {
  83. case DebugEvent.BREAKPOINT:
  84. // on breakpoint also position thread to be top element
  85. extras = IModelDelta.EXPAND | IModelDelta.REVEAL;
  86. break;
  87. case DebugEvent.CLIENT_REQUEST:
  88. extras = IModelDelta.EXPAND;
  89. break;
  90. }
  91. fireDeltaUpdatingSelectedFrame(thread, IModelDelta.NO_CHANGE | extras, event);
  92. }
  93. }
  94. private boolean isEqual(Object o1, Object o2) {
  95. if (o1 == o2) {
  96. return true;
  97. }
  98. if (o1 == null) {
  99. return false;
  100. }
  101. return o1.equals(o2);
  102. }
  103. protected void handleResume(DebugEvent event) {
  104. IThread thread = removeSuspendedThread(event);
  105. fireDeltaAndClearTopFrame(thread, IModelDelta.STATE | IModelDelta.CONTENT | IModelDelta.SELECT);
  106. thread = getNextSuspendedThread();
  107. if (thread != null) {
  108. fireDeltaUpdatingSelectedFrame(thread, IModelDelta.NO_CHANGE | IModelDelta.REVEAL, event);
  109. }
  110. }
  111. protected void handleCreate(DebugEvent event) {
  112. fireDeltaAndClearTopFrame((IThread) event.getSource(), IModelDelta.ADDED | IModelDelta.STATE);
  113. }
  114. protected void handleTerminate(DebugEvent event) {
  115. IThread thread = (IThread) event.getSource();
  116. IDebugTarget target = thread.getDebugTarget();
  117. // ignore thread termination if target is terminated/disconnected
  118. if (!(target.isTerminated() || target.isDisconnected())) {
  119. fireDeltaAndClearTopFrame(thread, IModelDelta.REMOVED);
  120. }
  121. }
  122. protected void handleChange(DebugEvent event) {
  123. if (event.getDetail() == DebugEvent.STATE) {
  124. fireDeltaUpdatingThread((IThread) event.getSource(), IModelDelta.STATE);
  125. } else {
  126. fireDeltaUpdatingThread((IThread) event.getSource(), IModelDelta.CONTENT);
  127. }
  128. }
  129. protected void handleLateSuspend(DebugEvent suspend, DebugEvent resume) {
  130. IThread thread = queueSuspendedThread(suspend);
  131. if (suspend.isEvaluation() && suspend.getDetail() == DebugEvent.EVALUATION_IMPLICIT) {
  132. // late implicit evaluation - update thread and frame
  133. ModelDelta delta = buildRootDelta();
  134. ModelDelta node = addPathToThread(delta, thread);
  135. node = node.addNode(thread, IModelDelta.STATE);
  136. try {
  137. IStackFrame frame = thread.getTopStackFrame();
  138. if (frame != null) {
  139. node.addNode(frame, IModelDelta.STATE);
  140. fireDelta(delta);
  141. }
  142. } catch (DebugException e) {
  143. }
  144. } else {
  145. fireDeltaUpdatingSelectedFrame(thread, IModelDelta.STATE | IModelDelta.EXPAND, suspend);
  146. }
  147. }
  148. protected void handleSuspendTimeout(DebugEvent event) {
  149. IThread thread = removeSuspendedThread(event);
  150. // don't collapse thread when waiting for long step or evaluation to complete
  151. fireDeltaUpdatingThread(thread, IModelDelta.STATE);
  152. }
  153. protected ModelDelta buildRootDelta() {
  154. return new ModelDelta(getLaunchManager(), IModelDelta.NO_CHANGE);
  155. }
  156. /**
  157. * Returns the launch manager.
  158. *
  159. * @return the launch manager
  160. */
  161. protected ILaunchManager getLaunchManager() {
  162. return DebugPlugin.getDefault().getLaunchManager();
  163. }
  164. /**
  165. * Adds nodes into the delta up to but not including the given thread.
  166. *
  167. * @param delta root delta for the view (includes viewer input)
  168. * @param thread thread for which path is requested
  169. * @return
  170. */
  171. protected ModelDelta addPathToThread(ModelDelta delta, IThread thread) {
  172. ILaunch launch = thread.getLaunch();
  173. Object[] children = launch.getChildren();
  174. delta = delta.addNode(launch, indexOf(getLaunchManager().getLaunches(), launch), IModelDelta.NO_CHANGE, children.length);
  175. IDebugTarget debugTarget = thread.getDebugTarget();
  176. int numThreads = -1;
  177. try {
  178. numThreads = debugTarget.getThreads().length;
  179. } catch (DebugException e) {
  180. }
  181. return delta.addNode(debugTarget, indexOf(children, debugTarget), IModelDelta.NO_CHANGE, numThreads);
  182. }
  183. private void fireDeltaAndClearTopFrame(IThread thread, int flags) {
  184. ModelDelta delta = buildRootDelta();
  185. ModelDelta node = addPathToThread(delta, thread);
  186. node.addNode(thread, indexOf(thread), flags);
  187. synchronized (this) {
  188. fLastTopFrame.remove(thread);
  189. }
  190. fireDelta(delta);
  191. }
  192. private void fireDeltaUpdatingSelectedFrame(IThread thread, int flags, DebugEvent event) {
  193. ModelDelta delta = buildRootDelta();
  194. ModelDelta node = addPathToThread(delta, thread);
  195. IStackFrame prev = null;
  196. synchronized (this) {
  197. prev = (IStackFrame) fLastTopFrame.get(thread);
  198. }
  199. IStackFrame frame = null;
  200. try {
  201. Object frameToSelect = event.getData();
  202. if (frameToSelect == null || !(frameToSelect instanceof IStackFrame)) {
  203. frame = thread.getTopStackFrame();
  204. } else {
  205. frame = (IStackFrame)frameToSelect;
  206. }
  207. } catch (DebugException e) {
  208. }
  209. int threadIndex = indexOf(thread);
  210. int childCount = childCount(thread);
  211. if (isEqual(frame, prev)) {
  212. if (frame == null) {
  213. if (thread.isSuspended()) {
  214. // no frames, but suspended - update & select
  215. node = node.addNode(thread, threadIndex, flags | IModelDelta.STATE | IModelDelta.SELECT, childCount);
  216. }
  217. } else {
  218. node = node.addNode(thread, threadIndex, flags, childCount);
  219. }
  220. } else {
  221. if (event.getDetail() == DebugEvent.STEP_END) {
  222. if (prev == null) {
  223. // see bug 166602 - expand the thread if this is a step end with no previous top frame
  224. flags = flags | IModelDelta.EXPAND;
  225. } else if (frame == null) {
  226. // there was a previous frame and current is null on a step: transient state
  227. return;
  228. }
  229. }
  230. node = node.addNode(thread, threadIndex, flags | IModelDelta.CONTENT, childCount);
  231. }
  232. if (frame != null) {
  233. node.addNode(frame, indexOf(frame), IModelDelta.STATE | IModelDelta.SELECT, childCount(frame));
  234. }
  235. synchronized (this) {
  236. if (!isDisposed()) {
  237. fLastTopFrame.put(thread, frame);
  238. }
  239. }
  240. fireDelta(delta);
  241. }
  242. /**
  243. * Returns the index of the given thread, relative to its parent in the view.
  244. *
  245. * @param thread thread
  246. * @return index of the thread, relative to its parent
  247. */
  248. protected int indexOf(IThread thread) {
  249. try {
  250. return indexOf(thread.getDebugTarget().getThreads(), thread);
  251. } catch (DebugException e) {
  252. }
  253. return -1;
  254. }
  255. /**
  256. * Returns the index of the given frame, relative to its parent in the view.
  257. *
  258. * @param frame stack frame
  259. * @return index of the frame, relative to its thread
  260. */
  261. protected int indexOf(IStackFrame frame) {
  262. try {
  263. return indexOf(frame.getThread().getStackFrames(), frame);
  264. } catch (DebugException e) {
  265. return -1;
  266. }
  267. }
  268. /**
  269. * Returns the number of children the given thread has in the view.
  270. *
  271. * @param thread thread
  272. * @return number of children
  273. */
  274. protected int childCount(IThread thread) {
  275. try {
  276. return thread.getStackFrames().length;
  277. } catch (DebugException e) {
  278. }
  279. return -1;
  280. }
  281. /**
  282. * Returns the number of children the given frame has in the view.
  283. *
  284. * @param frame frame
  285. * @return child count
  286. */
  287. protected int childCount(IStackFrame frame) {
  288. return 0;
  289. }
  290. private void fireDeltaUpdatingThread(IThread thread, int flags) {
  291. ModelDelta delta = buildRootDelta();
  292. ModelDelta node = addPathToThread(delta, thread);
  293. node = node.addNode(thread, flags);
  294. fireDelta(delta);
  295. }
  296. protected boolean handlesEvent(DebugEvent event) {
  297. return event.getSource() instanceof IThread;
  298. }
  299. protected synchronized IThread queueSuspendedThread(DebugEvent event) {
  300. IThread thread = (IThread) event.getSource();
  301. if (!isDisposed()) {
  302. fThreadQueue.add(thread);
  303. }
  304. return thread;
  305. }
  306. protected synchronized IThread removeSuspendedThread(DebugEvent event) {
  307. IThread thread = (IThread)event.getSource();
  308. fThreadQueue.remove(thread);
  309. return thread;
  310. }
  311. protected synchronized IThread queueSuspendedThread(IThread thread) {
  312. if (!isDisposed()) {
  313. fThreadQueue.add(thread);
  314. }
  315. return thread;
  316. }
  317. protected synchronized void removeQueuedThread(IThread thread) {
  318. fThreadQueue.remove(thread);
  319. }
  320. protected synchronized IThread getNextSuspendedThread() {
  321. if (!fThreadQueue.isEmpty()) {
  322. return (IThread) fThreadQueue.iterator().next();
  323. }
  324. return null;
  325. }
  326. }