2 * Copyright 2000-2009 JetBrains s.r.o.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
16 package com
.intellij
.debugger
.engine
;
18 import com
.intellij
.Patches
;
19 import com
.intellij
.debugger
.DebuggerBundle
;
20 import com
.intellij
.debugger
.engine
.evaluation
.EvaluateException
;
21 import com
.intellij
.debugger
.engine
.evaluation
.EvaluationContextImpl
;
22 import com
.intellij
.debugger
.engine
.events
.SuspendContextCommandImpl
;
23 import com
.intellij
.debugger
.jdi
.StackFrameProxyImpl
;
24 import com
.intellij
.debugger
.jdi
.ThreadReferenceProxyImpl
;
25 import com
.intellij
.openapi
.diagnostic
.Logger
;
26 import com
.intellij
.util
.containers
.HashSet
;
27 import com
.sun
.jdi
.ObjectReference
;
28 import com
.sun
.jdi
.ThreadReference
;
29 import com
.sun
.jdi
.event
.EventSet
;
30 import com
.sun
.jdi
.request
.EventRequest
;
31 import org
.jetbrains
.annotations
.NotNull
;
34 import java
.util
.concurrent
.ConcurrentLinkedQueue
;
39 public abstract class SuspendContextImpl
implements SuspendContext
{
40 private static final Logger LOG
= Logger
.getInstance("#com.intellij.debugger.engine.SuspendContextImpl");
42 private final DebugProcessImpl myDebugProcess
;
43 private final int mySuspendPolicy
;
45 private ThreadReferenceProxyImpl myThread
;
46 boolean myIsVotedForResume
= true;
48 protected int myVotesToVote
;
49 protected Set
<ThreadReferenceProxyImpl
> myResumedThreads
;
51 private final EventSet myEventSet
;
52 private volatile boolean myIsResumed
;
54 public ConcurrentLinkedQueue
<SuspendContextCommandImpl
> myPostponedCommands
= new ConcurrentLinkedQueue
<SuspendContextCommandImpl
>();
55 public volatile boolean myInProgress
;
56 private final HashSet
<ObjectReference
> myKeptReferences
= new HashSet
<ObjectReference
>();
57 private EvaluationContextImpl myEvaluationContext
= null;
59 SuspendContextImpl(@NotNull DebugProcessImpl debugProcess
, int suspendPolicy
, int eventVotes
, EventSet set
) {
60 myDebugProcess
= debugProcess
;
61 mySuspendPolicy
= suspendPolicy
;
62 myVotesToVote
= eventVotes
;
66 public void setThread(ThreadReference thread
) {
68 ThreadReferenceProxyImpl threadProxy
= myDebugProcess
.getVirtualMachineProxy().getThreadReferenceProxy(thread
);
69 LOG
.assertTrue(myThread
== null || myThread
== threadProxy
);
70 myThread
= threadProxy
;
73 protected abstract void resumeImpl();
75 protected void resume(){
77 DebuggerManagerThreadImpl
.assertIsManagerThread();
79 if (!Patches
.IBM_JDK_DISABLE_COLLECTION_BUG
) {
80 for (ObjectReference objectReference
: myKeptReferences
) {
82 objectReference
.enableCollection();
84 catch (UnsupportedOperationException e
) {
85 // ignore: some J2ME implementations does not provide this operation
88 myKeptReferences
.clear();
91 for(SuspendContextCommandImpl cmd
= myPostponedCommands
.poll(); cmd
!= null; cmd
= myPostponedCommands
.poll()) {
92 cmd
.notifyCancelled();
102 private void assertNotResumed() {
104 if (myDebugProcess
.isAttached()) {
105 LOG
.assertTrue(false, "Cannot access SuspendContext. SuspendContext is resumed.");
111 public EventSet
getEventSet() {
116 public DebugProcessImpl
getDebugProcess() {
118 return myDebugProcess
;
121 public StackFrameProxyImpl
getFrameProxy() {
124 return myThread
!= null && myThread
.frameCount() > 0 ? myThread
.frame(0) : null;
126 catch (EvaluateException e
) {
131 public ThreadReferenceProxyImpl
getThread() {
135 public int getSuspendPolicy() {
137 return mySuspendPolicy
;
140 public void doNotResumeHack() {
142 myVotesToVote
= 1000000000;
145 public boolean isExplicitlyResumed(ThreadReferenceProxyImpl thread
) {
146 return myResumedThreads
!= null ? myResumedThreads
.contains(thread
) : false;
149 public boolean suspends(ThreadReferenceProxyImpl thread
) {
154 switch(getSuspendPolicy()) {
155 case EventRequest
.SUSPEND_ALL
:
156 return !isExplicitlyResumed(thread
);
157 case EventRequest
.SUSPEND_EVENT_THREAD
:
158 return thread
== getThread();
163 public boolean isEvaluating() {
165 return myEvaluationContext
!= null;
168 public EvaluationContextImpl
getEvaluationContext() {
169 return myEvaluationContext
;
172 public boolean isResumed() {
176 public void setIsEvaluating(EvaluationContextImpl evaluationContext
) {
178 myEvaluationContext
= evaluationContext
;
181 public String
toString() {
182 if (myEventSet
!= null) {
183 return myEventSet
.toString();
185 return myThread
!= null ? myThread
.toString() : DebuggerBundle
.message("string.null.context");
188 public void keep(ObjectReference reference
) {
189 if (!Patches
.IBM_JDK_DISABLE_COLLECTION_BUG
) {
190 final boolean added
= myKeptReferences
.add(reference
);
193 reference
.disableCollection();
195 catch (UnsupportedOperationException e
) {
196 // ignore: some J2ME implementations does not provide this operation
202 public void postponeCommand(final SuspendContextCommandImpl command
) {
204 myPostponedCommands
.add(command
);
207 command
.notifyCancelled();
211 public SuspendContextCommandImpl
pollPostponedCommand() {
212 return myPostponedCommands
.poll();