mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-04-29 19:45:01 +02:00
Bug 392095 The Traditional Memory Renderer does not work properly with the TCF Memory Block.
This is an initial solution which is made up of 2 parts 1.) Changed the lower-level renderer to filter based on memory block as well as debug target. 2.) Changed the parent render to become a listener for model changed events which are translated in to direct calls to the renderer to update the displayed values.
This commit is contained in:
parent
c06097a586
commit
60ff7da7a4
1 changed files with 52 additions and 100 deletions
|
@ -13,7 +13,6 @@ package org.eclipse.cdt.debug.ui.memory.traditional;
|
|||
|
||||
import java.lang.reflect.Method;
|
||||
import java.math.BigInteger;
|
||||
import java.util.HashMap;
|
||||
|
||||
import org.eclipse.cdt.debug.core.model.provisional.IMemoryRenderingViewportProvider;
|
||||
import org.eclipse.core.commands.AbstractHandler;
|
||||
|
@ -23,9 +22,7 @@ import org.eclipse.core.commands.ExecutionException;
|
|||
import org.eclipse.core.runtime.IProgressMonitor;
|
||||
import org.eclipse.core.runtime.IStatus;
|
||||
import org.eclipse.core.runtime.Status;
|
||||
import org.eclipse.debug.core.DebugEvent;
|
||||
import org.eclipse.debug.core.DebugException;
|
||||
import org.eclipse.debug.core.DebugPlugin;
|
||||
import org.eclipse.debug.core.model.IMemoryBlock;
|
||||
import org.eclipse.debug.core.model.IMemoryBlockExtension;
|
||||
import org.eclipse.debug.core.model.MemoryByte;
|
||||
|
@ -201,77 +198,43 @@ public class TraditionalRendering extends AbstractMemoryRendering implements IRe
|
|||
* @see org.eclipse.debug.internal.ui.viewers.model.provisional.IModelChangedListener#modelChanged(org.eclipse.debug.internal.ui.viewers.model.provisional.IModelDelta, org.eclipse.debug.internal.ui.viewers.model.provisional.IModelProxy)
|
||||
*/
|
||||
public void modelChanged(IModelDelta delta, IModelProxy proxy)
|
||||
{
|
||||
/*
|
||||
* The event model in the traditional renderer is written to expect a suspend first
|
||||
* which will cause it to save its current data set away in an archive. Then when
|
||||
* the state change comes through it will compare and refresh showing a difference.
|
||||
*/
|
||||
int flags = delta.getFlags();
|
||||
if ( ( flags & IModelDelta.STATE ) != 0 ) {
|
||||
DebugEvent debugEvent = new DebugEvent(delta.getElement(), DebugEvent.SUSPEND, DebugEvent.CONTENT);
|
||||
DebugPlugin.getDefault().fireDebugEventSet(new DebugEvent[] { debugEvent });
|
||||
}
|
||||
{
|
||||
/*
|
||||
* The event model in the traditional renderer is written to expect a suspend first
|
||||
* which will cause it to save its current data set away in an archive. Then when
|
||||
* the state change comes through it will compare and refresh showing a difference.
|
||||
*/
|
||||
int flags = delta.getFlags();
|
||||
if ( ( flags & IModelDelta.STATE ) != 0 ) {
|
||||
fRendering.handleSuspend(false);
|
||||
}
|
||||
|
||||
DebugEvent debugEvent = new DebugEvent(delta.getElement(), DebugEvent.CHANGE, DebugEvent.CONTENT);
|
||||
DebugPlugin.getDefault().fireDebugEventSet(new DebugEvent[] { debugEvent });
|
||||
}
|
||||
fRendering.handleChange();
|
||||
}
|
||||
|
||||
/*
|
||||
* These hashes make sure we do not create a separate model proxy for the same memory block. If
|
||||
* we did then we would get duplicate state changes which would hide the actual changes since
|
||||
* the renderer would be notified of state change too many times and wipe out the difference
|
||||
* calculation it does. If we create multiple renderers against the same memory block we will
|
||||
* use the same Model Proxy for all of them. So we need to keep a count to know when the last
|
||||
* renderer has been torn down and we can freeup the proxy for that memory block. These stores
|
||||
* are always manipulate and tested on the UI dispatch thread for data integrity.
|
||||
* We use the model proxy which is supplied by the TCF implementation to provide the knowledge of memory
|
||||
* change notifications. The older backends ( the reference model, Wind River Systems Inc. ) are written
|
||||
* to generate the Debug Model events. TCF follows the "ModelDelta/IModelProxy" implementation that the
|
||||
* platform renderers use. So this implementation acts as a shim. If the older Debug Events come in then
|
||||
* fine. If the newer model deltas come in fine also.
|
||||
*/
|
||||
private static HashMap<IMemoryBlock,IModelProxy> proxies = new HashMap<IMemoryBlock,IModelProxy>(); // MemoryBlock --> Proxy
|
||||
private static HashMap<IMemoryBlock,Integer> proxies_cnt = new HashMap<IMemoryBlock,Integer>(); // MemoryBlock --> count
|
||||
private IModelProxy fModel;
|
||||
|
||||
@Override
|
||||
public void dispose()
|
||||
public void dispose()
|
||||
{
|
||||
/*
|
||||
* We use the UI dispatch thread to protect the proxy information. Even though I believe the
|
||||
* dispose routine is always called in the UI dispatch thread. I am going to make sure.
|
||||
*/
|
||||
/*
|
||||
* We use the UI dispatch thread to protect the proxy information. Even though I believe the
|
||||
* dispose routine is always called in the UI dispatch thread. I am going to make sure.
|
||||
*/
|
||||
Display.getDefault().asyncExec(new Runnable() {
|
||||
public void run() {
|
||||
IMemoryBlock block = getMemoryBlock();
|
||||
|
||||
/*
|
||||
* See if we already know about this block and already have a proxy for it.
|
||||
*/
|
||||
if ( proxies_cnt.containsKey( block ) ) {
|
||||
Integer cur_cnt = proxies_cnt.get( block );
|
||||
cur_cnt -- ;
|
||||
|
||||
/*
|
||||
* If the count is zero this is the last render associated with this block.
|
||||
* We can clean out this block/proxy.
|
||||
*/
|
||||
if ( cur_cnt == 0 ) {
|
||||
|
||||
proxies_cnt.remove( block );
|
||||
IModelProxy proxy = proxies.remove( block );
|
||||
|
||||
/*
|
||||
* Before disposal make sure we take down the listener so we do not get
|
||||
* any phantom notifications.
|
||||
*/
|
||||
proxy.removeModelChangedListener(TraditionalRendering.this);
|
||||
proxy.dispose();
|
||||
|
||||
}
|
||||
else {
|
||||
/*
|
||||
* Not the last so just put back the reduced count.
|
||||
*/
|
||||
proxies_cnt.put( block, cur_cnt );
|
||||
}
|
||||
}
|
||||
}});
|
||||
public void run() {
|
||||
if ( fModel != null ) {
|
||||
fModel.removeModelChangedListener(TraditionalRendering.this);
|
||||
fModel.dispose();
|
||||
}
|
||||
}});
|
||||
|
||||
if(this.fRendering != null)
|
||||
this.fRendering.dispose();
|
||||
|
@ -279,45 +242,34 @@ public class TraditionalRendering extends AbstractMemoryRendering implements IRe
|
|||
super.dispose();
|
||||
}
|
||||
|
||||
// private IModelProxy fModel;
|
||||
@Override
|
||||
public void init(final IMemoryRenderingContainer container, final IMemoryBlock block)
|
||||
{
|
||||
super.init(container, block);
|
||||
|
||||
/*
|
||||
* Working with the model proxy must be done on the UI dispatch thread.
|
||||
*/
|
||||
if ( block instanceof IModelProxyFactory ) {
|
||||
Display.getDefault().asyncExec(new Runnable() {
|
||||
public void run() {
|
||||
|
||||
if ( proxies.containsKey( block ) ) {
|
||||
/*
|
||||
* Increment the count and reuse the proxy again.
|
||||
*/
|
||||
proxies_cnt.put( block, proxies_cnt.get( block ) + 1 );
|
||||
}
|
||||
else {
|
||||
/*
|
||||
* We need to create a new proxy. First generate an acceptable Presentation Context.
|
||||
*/
|
||||
IMemoryRenderingSite site = container.getMemoryRenderingSite();
|
||||
MemoryViewPresentationContext context = new MemoryViewPresentationContext(site, container, TraditionalRendering.this);
|
||||
/*
|
||||
* The asynchronous model assumes we have an asynchronous viewer that has an IPresentationContext
|
||||
* to represent it. The Platform memory subsystem provides a way to create one without a viewewr.
|
||||
*/
|
||||
IMemoryRenderingSite site = container.getMemoryRenderingSite();
|
||||
MemoryViewPresentationContext context = new MemoryViewPresentationContext(site, container, TraditionalRendering.this);
|
||||
|
||||
/*
|
||||
* Get a new proxy and perform the initialization sequence so we are known the
|
||||
* the model provider.
|
||||
*/
|
||||
IModelProxyFactory factory = (IModelProxyFactory) block;
|
||||
IModelProxy proxy = factory.createModelProxy(block, context);
|
||||
proxy.installed(null);
|
||||
proxy.addModelChangedListener(TraditionalRendering.this);
|
||||
/*
|
||||
* Get a new proxy and perform the initialization sequence so we are known the
|
||||
* the model provider.
|
||||
*/
|
||||
IModelProxyFactory factory = (IModelProxyFactory) block;
|
||||
fModel = factory.createModelProxy(block, context);
|
||||
fModel.installed(null);
|
||||
fModel.addModelChangedListener(TraditionalRendering.this);
|
||||
|
||||
/*
|
||||
* Now note this block/proxy so we can reuse it later if more renderers are create
|
||||
* with the same block.
|
||||
*/
|
||||
proxies.put( block , proxy );
|
||||
proxies_cnt.put( block, new Integer(1) );
|
||||
}
|
||||
}});
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue