/*******************************************************************************
 * Copyright (c) 2008, 2015 Monta Vista and others.
 *
 * This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *     Monta Vista - initial API and implementation
 *     Ericsson    - Modified for handling of multiple execution contexts
 *     Ericsson    - Major updates for GDB/MI implementation
 *     Ericsson    - Major re-factoring to deal with children
 *     Axel Mueller - Bug 306555 - Add support for cast to type / view as array (IExpressions2)
 *     Jens Elmenthaler (Verigy) - Added Full GDB pretty-printing support (bug 302121)
 *     Axel Mueller - Workaround for GDB bug where -var-info-path-expression gives invalid result (Bug 320277)
 *     Anton Gorenkov - DSF-GDB should properly handle variable type change (based on RTTI) (Bug 376901)
 *     Anders Dahlberg (Ericsson)  - Need additional API to extend support for memory spaces (Bug 431627)
 *     Alvaro Sanchez-Leon (Ericsson)  - Need additional API to extend support for memory spaces (Bug 431627)
 *     Martin Schreiber - Bug 435606 - write unsigned variables (UINT32 and UINT64) in the binary format
 *     Vladimir Prus (Mentor Graphics) - add MIVariableObject.getRawFields
 *******************************************************************************/
package org.eclipse.cdt.dsf.mi.service;

import java.math.BigInteger;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import org.eclipse.cdt.dsf.concurrent.CountingRequestMonitor;
import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
import org.eclipse.cdt.dsf.concurrent.IDsfStatusConstants;
import org.eclipse.cdt.dsf.concurrent.RequestMonitor;
import org.eclipse.cdt.dsf.datamodel.DMContexts;
import org.eclipse.cdt.dsf.debug.service.IExpressions;
import org.eclipse.cdt.dsf.debug.service.IExpressions.IExpressionDMContext;
import org.eclipse.cdt.dsf.debug.service.IExpressions.IIndexedPartitionDMContext;
import org.eclipse.cdt.dsf.debug.service.IExpressions2.ICastedExpressionDMContext;
import org.eclipse.cdt.dsf.debug.service.IFormattedValues;
import org.eclipse.cdt.dsf.debug.service.IFormattedValues.FormattedValueDMContext;
import org.eclipse.cdt.dsf.debug.service.IFormattedValues.FormattedValueDMData;
import org.eclipse.cdt.dsf.debug.service.IMemory.IMemoryChangedEvent;
import org.eclipse.cdt.dsf.debug.service.IRunControl;
import org.eclipse.cdt.dsf.debug.service.IRunControl.IExecutionDMContext;
import org.eclipse.cdt.dsf.debug.service.IStack;
import org.eclipse.cdt.dsf.debug.service.IStack.IFrameDMContext;
import org.eclipse.cdt.dsf.debug.service.command.ICommand;
import org.eclipse.cdt.dsf.debug.service.command.ICommandControl;
import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService.ICommandControlDMContext;
import org.eclipse.cdt.dsf.debug.service.command.ICommandListener;
import org.eclipse.cdt.dsf.debug.service.command.ICommandResult;
import org.eclipse.cdt.dsf.debug.service.command.ICommandToken;
import org.eclipse.cdt.dsf.debug.service.command.IEventListener;
import org.eclipse.cdt.dsf.gdb.GDBTypeParser;
import org.eclipse.cdt.dsf.gdb.GDBTypeParser.GDBType;
import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin;
import org.eclipse.cdt.dsf.gdb.service.IGDBTraceControl.ITraceRecordSelectedChangedDMEvent;
import org.eclipse.cdt.dsf.mi.service.MIExpressions.ExpressionInfo;
import org.eclipse.cdt.dsf.mi.service.MIExpressions.MIExpressionDMC;
import org.eclipse.cdt.dsf.mi.service.command.CommandFactory;
import org.eclipse.cdt.dsf.mi.service.command.commands.ExprMetaGetAttributes;
import org.eclipse.cdt.dsf.mi.service.command.commands.ExprMetaGetChildCount;
import org.eclipse.cdt.dsf.mi.service.command.commands.ExprMetaGetChildren;
import org.eclipse.cdt.dsf.mi.service.command.commands.ExprMetaGetValue;
import org.eclipse.cdt.dsf.mi.service.command.commands.ExprMetaGetVar;
import org.eclipse.cdt.dsf.mi.service.command.commands.MIDataEvaluateExpression;
import org.eclipse.cdt.dsf.mi.service.command.output.ExprMetaGetAttributesInfo;
import org.eclipse.cdt.dsf.mi.service.command.output.ExprMetaGetChildCountInfo;
import org.eclipse.cdt.dsf.mi.service.command.output.ExprMetaGetChildrenInfo;
import org.eclipse.cdt.dsf.mi.service.command.output.ExprMetaGetValueInfo;
import org.eclipse.cdt.dsf.mi.service.command.output.ExprMetaGetVarInfo;
import org.eclipse.cdt.dsf.mi.service.command.output.MIDataEvaluateExpressionInfo;
import org.eclipse.cdt.dsf.mi.service.command.output.MIDisplayHint;
import org.eclipse.cdt.dsf.mi.service.command.output.MIDisplayHint.GdbDisplayHint;
import org.eclipse.cdt.dsf.mi.service.command.output.MIInfo;
import org.eclipse.cdt.dsf.mi.service.command.output.MITuple;
import org.eclipse.cdt.dsf.mi.service.command.output.MIVar;
import org.eclipse.cdt.dsf.mi.service.command.output.MIVarAssignInfo;
import org.eclipse.cdt.dsf.mi.service.command.output.MIVarChange;
import org.eclipse.cdt.dsf.mi.service.command.output.MIVarCreateInfo;
import org.eclipse.cdt.dsf.mi.service.command.output.MIVarDeleteInfo;
import org.eclipse.cdt.dsf.mi.service.command.output.MIVarEvaluateExpressionInfo;
import org.eclipse.cdt.dsf.mi.service.command.output.MIVarInfoPathExpressionInfo;
import org.eclipse.cdt.dsf.mi.service.command.output.MIVarListChildrenInfo;
import org.eclipse.cdt.dsf.mi.service.command.output.MIVarSetFormatInfo;
import org.eclipse.cdt.dsf.mi.service.command.output.MIVarShowAttributesInfo;
import org.eclipse.cdt.dsf.mi.service.command.output.MIVarUpdateInfo;
import org.eclipse.cdt.dsf.service.DsfServiceEventHandler;
import org.eclipse.cdt.dsf.service.DsfServicesTracker;
import org.eclipse.cdt.dsf.service.DsfSession;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;

/**
 * Manages a list of variable objects as created through GDB/MI commands.
 *
 * This class is passed expression-meta-commands which have their own cache.
 * Therefore, we don't use the standard MICommandCache in this class.
 * In fact, we can't even use it, because many variableObject MI commands,
 * should not be cached as they alter the state of the back-end.
 *
 * Design details:
 * ==============
 *
 * GDB variable object information
 * -------------------------------
 * o Variable objects are recursively hierarchical, where children can be created through
 *   the parent.
 * o A varObject created with -var-create is a ROOT
 * o A varObject created with -var-list-children, is not a root
 * o Only varObject with no children or varObjects that are pointers can change values
 *   and therefore
 *   those objects can be used with -var-assign
 * o After a program stops, a varObject must be 'updated' before used
 * o Only root varObject can be updated with -var-update, which will trigger all
 *   of the root's descendants to be updated.
 * o Once updated, a varObject need not be updated until the program resumes again;
 *   this is true even after -var-assign is used (because it does an implicit -var-update)
 * o -var-update will return the list of all modifiable descendants of the udpated root which
 *   have changed
 * o -var-update will indicate if a root is out-of-scope (which implies that all
 *   its descendants are out-of-scope)
 * o if a varObject is out-of-scope, another varObject may be valid for the same
 *   expression as the out-of-scope varObject
 * o deleting a varObject will delete all its descendants, therefore, it is only
 *   necessary to delete roots
 *
 *
 * Class details
 * -------------
 * - We have an MIVariableObject class which represents a variable object in GDB
 *
 * - MIVariableObject includes a buffered value for each allowed format.
 *
 * - We have an MIRootVariableObject class inheriting from MIVariableObject to describe
 *   root varObjects created with -var-create.  Objects created with -var-list-children
 *   are MIVariableObjects only.  The root class will keep track of if the root object
 *   needs to be updated, if the root object is out-of-scope, and of a list of all
 *   modifiable descendants of this root.  The list of modifiable descendants is
 *   accessed using the gdb-given name to allow quick updates from the -var-update
 *   result (see below.)
 *
 * - we do not use -var-list-children for arrays, but create them manually
 *
 * - when the program stops, we should mark all roots as needing to be updated.
 * To achieve this efficiently, we have a dedicated list of roots that are updated.
 * When the program stops, we go through this list, remove each element and mark it
 * as needing to be updated.
 *
 * - when a varObject is accessed, if its root must be updated, the var-update
 * command shall be used.  The result of that command will indicate all
 * modifiable descendants that have changed.  We also use --all-values with -var-update
 * to get the new value (in the current format) for each modified descendant.  Using the list of modifiable
 * descendants of the root, we can quickly update the changed ones to invalidate their buffered
 * values and store the new current format value.
 *
 * - all values of non-modifiable varObjects (except arrays) will be set to {...}
 * without going to the back-end
 *
 * - requesting the value of an array varObject will trigger the creation of a new
 * varObject for the array's address.  Note that we must still use a variable
 * object and not the command -data-evaluate-expression, because we still need to get
 * the array address in multiple formats.
 *
 * - we keep an LRU (Least Recently Used) structure of all variable objects.  This LRU
 * will be bounded to a maximum allowed number of variable objects.  Whenever we get an
 * object from the LRU cleanup will be done if the maximum size has been reached.
 * The LRU will not delete a parent varObject until all its children are deleted; this is
 * achieved by touching each of the parents of an object whenever that object is put or get
 *
 * - It may happen that when accessing a varObject we find its root to be
 * out-of-scope.  The expression for which we are trying to access a varObject
 * could still be valid, and therefore we should try to create a new varObject for
 * that expression.  This can happen for example if two methods use the same name
 * for a variable. In the case when we find that a varObject is out-of-scope (when
 * its root is out-of-scope) the following should be done:
 *  - replace the varObject in the LRU with a newly created one in GDB
 *  - if the old object was a root, delete it in GDB.
 *
 * - In GDB, -var-update will only report a change if -var-evaluate-expression has
 *   changed -- in the current format--.  This means that situations like
 *    double z = 1.2;
 *    z = 1.4;
 *   Will not report a change if the format is anything else than natural.
 *   This is because 1.2 and 1.4 are both printed as 1, 0x1, etc
 *   Since we cache the values of every format, we must know if the value has
 *   change in -any- format, not just the current one.
 *   To solve this, we always keep the display format of variable objects (and their
 *   children) to the natural format; we believe that if the value changes in any
 *   format, it guarantees that it will change in the natural format.
 *   The simplest way to do this is that whenever we change the format
 *   of a variable object, we immediately set it back to natural with a second
 *   var-set-format command.
 *   Note that versions of GDB after 6.7 will allows to issue -var-evaluate-expression
 *   with a specified format, therefore allowing us to never use -var-set-format, and
 *   consequently, to easily keep the display format of all variable objects to natural.
 *
 * Notes on Dynamic Variable Objects (varobj)
 * ------------------------------------------
 *   - with version 7.0, gdb support so-called pretty printers.
 *
 *   - pretty printers are registered for certain types
 *
 *   - if there is a pretty printer registered for the type of a variable,
 *     the pretty printer provides the value and the children of that variable
 *
 *   - a varobj whose value and/or children are provided by a pretty printer,
 *     are referred to as dynamic variable objects
 *
 *   - dynamic varobjs change the game: it's not wise to ask it about all its
 *     children, not even the number of children it has. The reason is that
 *     in order to find out about the number of children the pretty printer
 *     must fetch all the children from the inferiors memory. If the variable
 *     is not yet initialized, the set of children are random, and thus might
 *     be huge. Even worse, there are data structures where fetching all
 *     children may result in an endless loop. The Eclipse debugger then hangs.
 *
 *   - In order to avoid this, we will always fetch up to a certain maximum
 *     number of children. Furthermore, it is possible to find out whether there
 *     are more children available. In the UI, all the currently fetched
 *     children are available. In addition, if there are more children
 *     available, a special node will be appended to indicate that there is
 *     more the user could fetch.
 *
 *   - Dynamic varobjs can change their value, as leaf varobjs can do.
 *     Especially, children can be added or removed during an update.
 *
 *   - There is no expression for children of dynamic varobjs (at least not
 *     yet, http://sourceware.org/bugzilla/show_bug.cgi?id=10252 would fix that).
 *     The reason -var-info-path-expression returns garbage for children of
 *     dynamic varobjs.
 *
 *   - Because of this, the variable of an expression that is a child of
 *     a dynamic varobj cannot be created again using -var-create, once
 *     the LRU cache has deleted it. Instead, we track the parent and index
 *     within this parent for each non-root variable, and later use
 *       -var-list-children parent indexInParent (indexInParent + 1)
 *     in order to create the MI variable anew.
 *
 *   - The fetching of children for dynamic varobjs becomes a bit more complicated.
 *     For the traditional varobjs, once children where requested, all children
 *     were fetched. For dynamic varobjs, we can no longer fetch all children.
 *     Instead, the client will provide a maximum number of children that
 *     is to be fetched. Every time the child count or children are requested,
 *     we must check whether there are additional children to be fetched,
 *     because the limit might have extended.
 *     Fetching additional children can only be done by one request monitor at a time.
 *     The serialization of the request monitors is done in getChildren by
 *     ensuring that fetchChildren is called for one request monitor at a time.
 *     fetchChildren in turn checks whether enough children are fetched, and
 *     if not, fetches the additional children.
 */
public class MIVariableManager implements ICommandControl {

	/**
	 * Stores the information about children of a variable object.
	 *
	 * @since 4.0
	 */
	protected static class ChildrenInfo {
		private final ExpressionInfo[] children;
		private final boolean hasMore;

		public ChildrenInfo(ExpressionInfo[] children, boolean hasMore) {
			this.children = children;
			this.hasMore = hasMore;
		}

		/**
		 * @return The currently fetched children. Ask {@link #hasMore()} in
		 *         order to find out whether there are more to fetch.
		 */
		public ExpressionInfo[] getChildren() {
			return children;
		}

		/**
		 * @return true, if there are more than just those returned by
		 *         {@link #getChildren()}.
		 */
		public boolean hasMore() {
			return hasMore;
		}
	}

	/**
	 * Stores the information about the children count of a variable object.
	 *
	 * @since 4.0
	 */
	protected static class ChildrenCountInfo {
		private final int childrenCount;
		private final boolean hasMore;

		public ChildrenCountInfo(int childrenCount, boolean hasMore) {
			this.childrenCount = childrenCount;
			this.hasMore = hasMore;
		}

		/**
		 * The number of children that we currently know of. Ask
		 * {@link #hasMore()} in order to find out whether there is at least one
		 * more.
		 */
		public int getChildrenCount() {
			return childrenCount;
		}

		/**
		 * @return <code>true</code> if there are more children than actually
		 *         returned by {@link #getChildrenCount()}.
		 */
		public boolean hasMore() {
			return hasMore;
		}
	}

	/**
	 * Utility class to track the progress and information of MI variable objects
	 */
	public class MIVariableObject {

		// Don't use an enumeration to allow subclasses to extend this
		protected static final int STATE_READY = 0;
		protected static final int STATE_UPDATING = 1;
		/** @since 4.0 */
		protected static final int STATE_NOT_CREATED = 10;
		/** @since 4.0 */
		protected static final int STATE_CREATING = 11;
		/** @since 4.0 */
		protected static final int STATE_CREATION_FAILED = 12;

		protected int currentState;

		// This is the lock used when we must run multiple
		// operations at once.  This lock should be independent of the
		// UPDATING state, which is why we don't make it part of the state
		private boolean fLocked = false;

		// This id is the one used to search for this object in our hash-map
		private final VariableObjectId fInternalId;

		/** The raw MI value for this variable object
		 * @since 4.6
		 */
		private MITuple fRaw;

		// This is the name of the variable object, as given by GDB (e.g., var1 or var1.public.x)
		private String fGdbName = null;
		// The current format of this variable object, within GDB
		private String fFormat = IFormattedValues.NATURAL_FORMAT;

		// The full expression that can be used to characterize this object
		// plus some other information that shall live longer than the
		// MIVariableObject.
		private ExpressionInfo fExprInfo;
		private String fType = null;
		private GDBType fGdbType;
		// A hint at the number of children.  This value is obtained
		// from -var-create or -var-list-children.  It may not be right in the case
		// of C++ structures, where GDB has a level of children for private/public/protected.
		private int fNumChildrenHint = 0;
		private Boolean fEditable = null;

		// The current values of the expression for each format. (null if not known yet)
		private Map<String, String> fValueMap = null;

		// A queue of request monitors waiting for this object to be ready
		private LinkedList<RequestMonitor> fOperationsPending;

		// A queue of request monitors that requested an update
		protected LinkedList<DataRequestMonitor<Boolean>> updatesPending;

		/** @since 4.0 */
		protected LinkedList<DataRequestMonitor<ChildrenInfo>> fetchChildrenPending;

		// The children of this variable, if any.
		// Null means we didn't fetch them yet, while an empty array means no children
		private ExpressionInfo[] fChildren = null;
		// we need to keep track of fake children because they are in the LRU and need to be removed in some cases.
		private List<ExpressionInfo> fFakeChildren = new ArrayList<>(3);
		private boolean fHasMore = false;
		private MIDisplayHint fDisplayHint = MIDisplayHint.NONE;

		// The parent of this variable object within GDB.  Null if this object has no parent
		private MIVariableObject fParent = null;

		// The root parent that must be used to issue -var-update.
		// If this object is a root, then the rootToUpdate is itself
		private MIRootVariableObject fRootToUpdate = null;

		protected boolean outOfScope = false;

		private boolean fFetchingChildren = false;

		/**
		 * In case of base class variables that are accessed in a derived class
		 * we cannot trust var-info-path-expression because of a bug in gdb.
		 * We have to use a workaround and apply it to the complete hierarchy of this varObject.
		 * Bug 320277
		 */
		private boolean fHasCastToBaseClassWorkaround = false;

		public MIVariableObject(VariableObjectId id, MIVariableObject parentObj) {
			this(id, parentObj, false);
		}

		/** @since 4.0 */
		public MIVariableObject(VariableObjectId id, MIVariableObject parentObj, boolean needsCreation) {
			currentState = needsCreation ? STATE_NOT_CREATED : STATE_READY;

			fOperationsPending = new LinkedList<>();
			updatesPending = new LinkedList<>();
			fetchChildrenPending = new LinkedList<>();

			fInternalId = id;
			setParent(parentObj);

			// No values are available yet
			fValueMap = new HashMap<>();
			resetValues();
		}

		/** Return the raw fields reported via MI.
		 *
		 * This method can be used to obtain information from debugger that
		 * is too special for a particular debugger or architecture to
		 * be represented as fields or methods in this class.
		 * @since 4.7
		 */
		public MITuple getRawFields() {
			return fRaw;
		}

		public VariableObjectId getInternalId() {
			return fInternalId;
		}

		public String getGdbName() {
			return fGdbName;
		}

		public String getCurrentFormat() {
			return fFormat;
		}

		public MIVariableObject getParent() {
			return fParent;
		}

		public MIRootVariableObject getRootToUpdate() {
			return fRootToUpdate;
		}

		public String getExpression() {
			return fExprInfo.getFullExpr();
		}

		public String getType() {
			return fType;
		}

		/**
		 * @since 4.0
		 */
		public ExpressionInfo getExpressionInfo() {
			return fExprInfo;
		}

		/**
		 * @return <code>true</code> if value and children of this varobj are
		 *         currently provided by a pretty printer.
		 *
		 * @since 4.0
		 */
		public boolean isDynamic() {
			return fExprInfo.isDynamic();
		}

		/**
		 * @return For dynamic varobjs ({@link #isDynamic() returns true}) this
		 *         method returns whether there are children in addition to the
		 *         currently fetched, i.e. whether there are more children than
		 *         {@link #getNumChildrenHint()} returns.
		 *
		 * @since 4.0
		 */
		public boolean hasMore() {
			return fHasMore;
		}

		/**
		 * @since 4.0
		 */
		public MIDisplayHint getDisplayHint() {
			return fDisplayHint;
		}

		/**
		 * @since 4.3
		 */
		public void setDisplayHint(MIDisplayHint displayHint) {
			this.fDisplayHint = displayHint;
		}

		/**
		 * @since 4.0
		 */
		public boolean hasChildren() {
			return (getNumChildrenHint() != 0 || hasMore());
		}

		/** @since 3.0 */
		public GDBType getGDBType() {
			return fGdbType;
		}

		/**
		 * Returns a hint to the number of children.  This hint is often correct,
		 * except when we are dealing with C++ complex structures where
		 * GDB has 'private/public/protected' as children.
		 *
		 * Use <code>isNumChildrenHintTrustworthy()</code> to know if the
		 * hint can be trusted.
		 *
		 * Note that a hint of 0 children can always be trusted, except for
		 * <code>{@link #fHasMore} == true</code>.
		 *
		 * @since 3.0 */
		public int getNumChildrenHint() {
			return fNumChildrenHint;
		}

		/**
		 * Returns whether the number of children hint can be
		 * trusted for this variable object.
		 *
		 * @since 3.0
		 */
		public boolean isNumChildrenHintTrustworthy() {
			// We cannot trust the hint about the number of children when we are
			// dealing with a complex structure that could have the
			// 'protected/public/private' children types.
			// Note that a pointer could have such children, if it points to
			// a complex structure.
			//
			// This is only valid for C++, so we should even check for it using
			// -var-info-expression.  Do we have to use -var-info-expression for each
			// variable object, or can we do it one time only for the whole program?
			// Right now, we always assume we could be using C++
			return ((getNumChildrenHint() == 0 && !hasMore()) || isArray());
		}

		public String getValue(String format) {
			return fValueMap.get(format);
		}

		public ExpressionInfo[] getChildren() {
			return fChildren;
		}

		public boolean isArray() {
			return (getGDBType() == null) ? false : getGDBType().getType() == GDBType.ARRAY;
		}

		public boolean isPointer() {
			return (getGDBType() == null) ? false : getGDBType().getType() == GDBType.POINTER;
		}

		public boolean isMethod() {
			return (getGDBType() == null) ? false : getGDBType().getType() == GDBType.FUNCTION;
		}

		// A complex variable is one with children.  However, it must not be a pointer since a pointer
		// does have children, but is still a 'simple' variable, as it can be modified.
		// A reference can be modified too, because it can be a reference to the base class before initialization
		// and after initialization it can become a reference to the derived class (if gdb shows the value type and
		// children taking into account RTTI ("set print object on")).
		// Note that the numChildrenHint can be trusted when asking if the number of children is 0 or not
		public boolean isComplex() {
			// Since we can't reliably determine whether a variable is complex
			// (see bug 399494), we err on the safe side and assume they are
			// not. In the end we'll end up asking GDB a bit more things, but we
			// should at least get correct results.
			return false;
		}

		/**
		 * @return Whether this varobj can safely be asked for all its children.
		 *
		 * @since 4.0
		 */
		public boolean isSafeToAskForAllChildren() {
			GdbDisplayHint displayHint = getDisplayHint().getGdbDisplayHint();

			// Here we balance usability against a slight risk of instability:
			//
			// Usability: if you have a class/struct-like pretty printer
			// all children are fetched, regardless of any limit. This
			// should be safe from gdb side.
			//
			// Risk: If somebody provides a pretty printer for a collection,
			// but forgets to implement the display_hint method, viewing
			// the collection while it is uninitiliazed may cause gdb
			// to never return.
			//
			// => The risk seams reasonable, so we require a limit only
			//    for collections.
			boolean isDynamicButSafe = (displayHint == GdbDisplayHint.GDB_DISPLAY_HINT_STRING)
					|| (displayHint == GdbDisplayHint.GDB_DISPLAY_HINT_NONE);

			return !isDynamic() || isDynamicButSafe;
		}

		public void setGdbName(String n) {
			fGdbName = n;
		}

		public void setCurrentFormat(String f) {
			fFormat = f;
		}

		/**
		 * @param info
		 * @param typeName
		 * @param num
		 *            If the correspinding MI variable is dynamic, the number of
		 *            children currently fetched by gdb.
		 * @param hasMore
		 *            Whether their are more children to fetch.
		 *
		 * @since 4.0
		 */
		public void setExpressionData(ExpressionInfo info, String typeName, int num, boolean hasMore) {
			fExprInfo = info;
			setType(typeName);
			fNumChildrenHint = num;
			this.fHasMore = hasMore;
		}

		/**
		 * @since 4.1
		 */
		public void setType(String newTypeName) {
			fType = newTypeName;
			fGdbType = getGDBTypeParser().parse(newTypeName);
		}

		public void setValue(String format, String val) {
			fValueMap.put(format, val);
		}

		public void resetValues(String valueInCurrentFormat) {
			resetValues();
			setValue(getCurrentFormat(), valueInCurrentFormat);
		}

		public void resetValues() {
			fValueMap.put(IFormattedValues.NATURAL_FORMAT, null);
			fValueMap.put(IFormattedValues.BINARY_FORMAT, null);
			fValueMap.put(IFormattedValues.HEX_FORMAT, null);
			fValueMap.put(IFormattedValues.OCTAL_FORMAT, null);
			fValueMap.put(IFormattedValues.DECIMAL_FORMAT, null);
		}

		/**
		 * @param c
		 *            The new children, or null in order to force fetching
		 *            children anew.
		 */
		public void setChildren(ExpressionInfo[] c) {
			fChildren = c;
			if (fChildren != null) {
				fNumChildrenHint = fChildren.length;
			}

			if (fChildren != null) {
				for (ExpressionInfo child : fChildren) {
					assert (child != null);
				}
			}
		}

		/**
		 * @param newChildren
		 *
		 * @since 4.0
		 */
		public void addChildren(ExpressionInfo[] newChildren) {
			if (fChildren == null) {
				fChildren = new ExpressionInfo[newChildren.length];
				System.arraycopy(newChildren, 0, fChildren, 0, newChildren.length);
			} else {
				ExpressionInfo[] oldChildren = fChildren;

				fChildren = new ExpressionInfo[fChildren.length + newChildren.length];

				System.arraycopy(oldChildren, 0, fChildren, 0, oldChildren.length);
				System.arraycopy(newChildren, 0, fChildren, oldChildren.length, newChildren.length);
			}

			fNumChildrenHint = fChildren.length;

			for (ExpressionInfo child : fChildren) {
				assert (child != null);
			}
		}

		/**
		 * @param newChildren
		 *
		 * @since 4.0
		 */
		protected void addChildren(ExpressionInfo[][] newChildren) {
			int requiredSize = 0;

			for (ExpressionInfo[] subArray : newChildren) {
				requiredSize += subArray.length;
			}

			ExpressionInfo[] plainChildren = new ExpressionInfo[requiredSize];

			int i = 0;
			for (ExpressionInfo[] subArray : newChildren) {
				System.arraycopy(subArray, 0, plainChildren, i, subArray.length);
				i += subArray.length;
			}

			addChildren(plainChildren);
		}

		/**
		 * @param newNumChildren
		 *
		 * @since 4.0
		 */
		public void shrinkChildrenTo(int newNumChildren) {
			if (fChildren != null) {
				ExpressionInfo[] oldChildren = fChildren;
				for (int i = oldChildren.length - 1; i >= newNumChildren; --i) {
					String childFullExpression = fChildren[i].getFullExpr();

					VariableObjectId childId = new VariableObjectId();
					childId.generateId(childFullExpression, getInternalId());
					lruVariableList.remove(childId);
				}

				fChildren = new ExpressionInfo[newNumChildren];
				System.arraycopy(oldChildren, 0, fChildren, 0, newNumChildren);
			}

			fNumChildrenHint = newNumChildren;
		}

		/**
		 * Removes the specified child from LRU and makes the cleanup on its
		 * children (if any).
		 *
		 * @since 4.3
		 */
		public void cleanupChild(ExpressionInfo child) {
			String childFullExpression = child.getFullExpr();
			VariableObjectId childId = new VariableObjectId();
			childId.generateId(childFullExpression, getInternalId());
			MIVariableObject varobjOfChild = lruVariableList.remove(childId);
			if (varobjOfChild != null) {
				// Remove it from the list of modifiable descendants
				getRootToUpdate().removeModifiableDescendant(varobjOfChild.getGdbName());
				// Remove children recursively
				varobjOfChild.cleanupChildren();
			}
		}

		/**
		 * Removes all the children (real and fake) of the variable object from
		 * LRU cache and from variable object itself. It is used when the type
		 * of variable was changed.
		 *
		 * @since 4.1
		 */
		public void cleanupChildren() {
			fHasMore = false;
			if (fChildren != null) {
				for (ExpressionInfo child : fChildren) {
					cleanupChild(child);
				}
				fChildren = null;
				fNumChildrenHint = 0;
			}
			for (ExpressionInfo fakeChild : fFakeChildren) {
				cleanupChild(fakeChild);
			}
			fFakeChildren.clear();
		}

		public void setParent(MIVariableObject p) {
			fParent = p;
			if (p == null) {
				fRootToUpdate = (this instanceof MIRootVariableObject) ? (MIRootVariableObject) this : null;
			} else {
				fRootToUpdate = p.getRootToUpdate();
			}
		}

		public void executeWhenNotUpdating(RequestMonitor rm) {
			getRootToUpdate().executeWhenNotUpdating(rm);
		}

		private void lock() {
			fLocked = true;
		}

		private void unlock() {
			fLocked = false;

			while (!fOperationsPending.isEmpty()) {
				fOperationsPending.poll().done();
			}
		}

		public boolean isOutOfScope() {
			return outOfScope;
		}

		/**
		 * @param success
		 *
		 * @since 4.0
		 */
		protected void creationCompleted(boolean success) {
			// A creation completed we must be up-to-date, so we
			// can tell any pending monitors that updates are done
			if (success) {
				currentState = STATE_READY;
				while (!updatesPending.isEmpty()) {
					DataRequestMonitor<Boolean> rm = updatesPending.poll();
					// Nothing to be re-created
					rm.setData(false);
					rm.done();
				}
			} else {
				currentState = STATE_CREATION_FAILED;

				// Creation failed, inform anyone waiting.
				while (!updatesPending.isEmpty()) {
					RequestMonitor rm = updatesPending.poll();
					rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, IDsfStatusConstants.INVALID_HANDLE,
							"Unable to create variable object", null)); //$NON-NLS-1$
					rm.done();
				}
			}
		}

		/**
		 * This method updates the variable object.
		 * Updating a variable object is done by updating its root.
		 */
		public void update(final DataRequestMonitor<Boolean> rm) {

			// We check to see if we are already out-of-scope
			// We must do this to avoid the risk of re-creating this object
			// twice, due to race conditions
			if (isOutOfScope()) {
				rm.setData(false);
				rm.done();
			} else if (currentState != STATE_READY) {
				// If we were already updating, we just queue the request monitor
				// until the on-going update finishes.
				updatesPending.add(rm);
			} else {
				currentState = STATE_UPDATING;
				getRootToUpdate().update(new DataRequestMonitor<Boolean>(fSession.getExecutor(), rm) {
					@Override
					protected void handleCompleted() {
						currentState = STATE_READY;

						if (isSuccess()) {
							outOfScope = getRootToUpdate().isOutOfScope();
							// This request monitor is the one that should re-create
							// the variable object if the old one was out-of-scope
							rm.setData(outOfScope);
							rm.done();

							// All the other request monitors must be notified but must
							// not re-create the object, even if it is out-of-scope
							while (!updatesPending.isEmpty()) {
								DataRequestMonitor<Boolean> pendingRm = updatesPending.poll();
								pendingRm.setData(false);
								pendingRm.done();
							}
						} else {
							rm.setStatus(getStatus());
							rm.done();

							while (!updatesPending.isEmpty()) {
								DataRequestMonitor<Boolean> pendingRm = updatesPending.poll();
								pendingRm.setStatus(getStatus());
								pendingRm.done();
							}
						}
					}
				});
			}
		}

		/**
		 * Process an update on this variable object.
		 *
		 * @param update What has changed.
		 *
		 * @since 4.0
		 */
		protected void processChange(final MIVarChange update, final RequestMonitor rm) {

			// Handle the variable type change properly
			if (update.isChanged()) {
				setType(update.getNewType());
				cleanupChildren();
				fEditable = null;
				updateLimit(IMIExpressions.CHILD_COUNT_LIMIT_UNSPECIFIED);
			}

			// These properties of the variable will probably not change,
			// but if they are - we should handle it properly.
			setDisplayHint(update.getDisplayHint());
			fExprInfo.setDynamic(update.isDynamic());

			MIVar[] newChildren = update.getNewChildren();

			// children == null means fetchChildren will happen later, so
			// don't try to create a sparsely filled children array here.
			final boolean addNewChildren = (fChildren != null);

			final ExpressionInfo[] addedChildren = (addNewChildren && (newChildren != null))
					? new ExpressionInfo[newChildren.length]
					: null;

			final CountingRequestMonitor countingRm = new CountingRequestMonitor(fSession.getExecutor(), rm) {

				@Override
				protected void handleCompleted() {

					if (!isSuccess()) {
						rm.setStatus(getStatus());
					} else {
						if (update.numChildrenChanged()) {
							if (fChildren != null) {
								// Remove those children that don't exist any longer.
								if (fChildren.length > update.getNewNumChildren()) {
									shrinkChildrenTo(update.getNewNumChildren());
								}
							} else {
								// Just update the child count.
								fNumChildrenHint = update.getNewNumChildren();
							}

							// Add the new children.
							if ((addedChildren != null) && (addedChildren.length != 0)) {
								addChildren(addedChildren);
							}
						}

						assert ((fChildren == null) || (fChildren.length == fNumChildrenHint));

						fHasMore = update.hasMore();

						// If there was no -var-list-children yet for a varobj,
						// the new children will not be reported by -var-update.
						// Set the children to null such that the next time children
						// are requested, they will be fetched.
						if (hasMore() && (fNumChildrenHint == 0)) {
							setChildren(null);
						}

						resetValues(update.getValue());
					}
					rm.done();
				}
			};

			// Process all the child MIVariableObjects.
			int pendingVariableCreationCount = 0;
			if (newChildren != null && newChildren.length != 0) {
				int i = update.getNewNumChildren() - newChildren.length;
				int arrayPosition = 0;

				for (final MIVar newChild : newChildren) {

					// As long as http://sourceware.org/bugzilla/show_bug.cgi?id=10252
					// is not fixed, it doesn't make sense to use
					// -var-info-path-expression. New children can only
					// be added during the update, if we are a child of a
					// dynamic varobj, and in this case -var-info-path-expression
					// won't work.
					final String childFullExpression = buildChildExpression(getExpression(), newChild.getExp());

					// Now try to see if we already have this variable
					// object in our Map
					// Since our map names use the expression, and not the
					// GDB given
					// name, we must determine the correct map name from the
					// varName
					final VariableObjectId childId = new VariableObjectId();
					childId.generateId(childFullExpression, getInternalId());
					MIVariableObject childVar = lruVariableList.get(childId);

					if (childVar != null) {
						if ((childVar.currentState == STATE_CREATING) || (childVar.currentState == STATE_NOT_CREATED)) {

							// We must wait until the child MIVariableObject is fully created.
							// This might succeed, or fail. If it succeeds, we can reuse it as
							// a child, otherwise we create a new MIVariableObject for the
							// varobj just provided by gdb.

							++pendingVariableCreationCount;

							final int insertPosition = arrayPosition;
							final MIVariableObject monitoredVar = childVar;
							final int indexInParent = i;

							// varobj is not fully created so add RequestMonitor to pending queue
							childVar.updatesPending
									.add(new DataRequestMonitor<Boolean>(fSession.getExecutor(), countingRm) {

										@Override
										protected void handleCompleted() {
											if (isSuccess()) {
												if (addNewChildren && addedChildren != null) {
													addedChildren[insertPosition] = monitoredVar.fExprInfo;
												}
											} else {
												// Create a fresh MIVariableObject for this child, using
												// the new varobj provided by gdb.
												MIVariableObject newVar = createChild(childId, childFullExpression,
														indexInParent, newChild);
												if (addNewChildren && addedChildren != null) {
													addedChildren[insertPosition] = newVar.fExprInfo;
												}
											}

											countingRm.done();
										}

									});

						} else if (childVar.currentState == STATE_CREATION_FAILED) {
							// There has been an attempt the create a MIRootVariableObject for a full
							// expression representing a child of a dynamic varobj. Such an attempt
							// always fails. But here we can now create it (see below).
							childVar = null;
						}
						// Note that we must check the root to know if it is out-of-scope.
						// We cannot check the child as it has not be updated and its
						// outOfScope variable is not updated either.
						else if (childVar.getRootToUpdate().isOutOfScope()) {
							childVar.deleteInGdb();
							childVar = null;
						}
					}

					// Note: we don't need to check for fake children (public, protected, private) here.
					// We enter this code only if the children are provided by a pretty printer and
					// they don't return such children.

					if (childVar == null) {
						// Create a fresh MIVariableObject for this child, using
						// the new varobj provided by -var-update.
						childVar = createChild(childId, childFullExpression, i, newChild);
						if (addNewChildren && addedChildren != null) {
							addedChildren[arrayPosition] = childVar.fExprInfo;
						}
					}

					++i;
					++arrayPosition;
				}
			}

			countingRm.setDoneCount(pendingVariableCreationCount);
		}

		/**
		 * Variable objects need not be deleted unless they are root.
		 * This method is specialized in the MIRootVariableObject class.
		 */
		public void deleteInGdb() {
		}

		/**
		 * This method returns the value of the variable object attributes by
		 * using -var-show-attributes.
		 * Currently, the only attribute available is 'editable'.
		 *
		 * @param rm
		 *            The data request monitor that will hold the value returned
		 */
		private void getAttributes(final DataRequestMonitor<Boolean> rm) {
			if (fEditable != null) {
				rm.setData(fEditable);
				rm.done();
			} else if (isComplex()) {
				fEditable = false;
				rm.setData(fEditable);
				rm.done();
			} else {
				fCommandControl.queueCommand(
						fCommandFactory.createMIVarShowAttributes(getRootToUpdate().getControlDMContext(),
								getGdbName()),
						new DataRequestMonitor<MIVarShowAttributesInfo>(fSession.getExecutor(), rm) {
							@Override
							protected void handleSuccess() {
								fEditable = getData().isEditable();

								rm.setData(fEditable);
								rm.done();
							}
						});
			}
		}

		/**
		 * This method returns the value of the variable object.
		 * This operation translates to multiple MI commands which affect the state of the
		 * variable object in the back-end; therefore, we must make sure the object is not
		 * locked doing another operation, and we must lock the object once it is our turn
		 * to use it.
		 *
		 * @param dmc
		 *            The context containing the format to be used for the evaluation
		 * @param rm
		 *            The data request monitor that will hold the value returned
		 * @since 4.3
		 */
		protected void getValue(final FormattedValueDMContext dmc, final DataRequestMonitor<FormattedValueDMData> rm) {

			// We might already know the value
			String value = getValue(dmc.getFormatID());
			if (value != null) {
				rm.setData(new FormattedValueDMData(value));
				rm.done();
				return;
			}

			// If we are dealing with an array, in which case, we want to get the address of it.
			// When dealing with a complex value, we want to query the back-end to correctly
			// address the case of a typedefed pointer (see bug 293832).
			if (isArray()) {
				// Figure out the address
				IExpressionDMContext exprCxt = DMContexts.getAncestorOfType(dmc, IExpressionDMContext.class);
				IExpressionDMContext addrCxt = fExpressionService.createExpression(exprCxt,
						"&(" + exprCxt.getExpression() + ")"); //$NON-NLS-1$//$NON-NLS-2$

				final FormattedValueDMContext formatCxt = new FormattedValueDMContext(fSession.getId(), addrCxt,
						dmc.getFormatID());

				getVariable(addrCxt, new DataRequestMonitor<MIVariableObject>(fSession.getExecutor(), rm) {
					@Override
					protected void handleSuccess() {
						getData().getValue(formatCxt, rm);

					}
				});
				return;
			}

			if (fLocked) {
				fOperationsPending.add(new RequestMonitor(fSession.getExecutor(), rm) {
					@Override
					protected void handleSuccess() {
						getValue(dmc, rm);
					}
				});
			} else {
				lock();

				// If the format is already the one set for this variable object,
				// we don't need to set it again
				if (dmc.getFormatID().equals(getCurrentFormat())) {
					evaluate(rm);
				} else {
					// We must first set the new format and then evaluate the variable
					fCommandControl.queueCommand(
							fCommandFactory.createMIVarSetFormat(getRootToUpdate().getControlDMContext(), getGdbName(),
									dmc.getFormatID()),
							new DataRequestMonitor<MIVarSetFormatInfo>(fSession.getExecutor(), rm) {
								@Override
								protected void handleCompleted() {
									if (isSuccess()) {
										setCurrentFormat(dmc.getFormatID());

										// If set-format returned the value, no need to evaluate
										// This is only valid after GDB 6.7
										if (getData().getValue() != null) {
											setValue(dmc.getFormatID(), getData().getValue());
											rm.setData(new FormattedValueDMData(getData().getValue()));
											rm.done();

											// Unlock is done within this method
											resetFormatToNatural();
										} else {
											evaluate(rm);
										}
									} else {
										rm.setStatus(getStatus());
										rm.done();

										unlock();
									}
								}
							});
				}
			}
		}

		/**
		 * This method evaluates a variable object
		 */
		private void evaluate(final DataRequestMonitor<FormattedValueDMData> rm) {
			fCommandControl.queueCommand(
					fCommandFactory.createMIVarEvaluateExpression(getRootToUpdate().getControlDMContext(),
							getGdbName()),
					new DataRequestMonitor<MIVarEvaluateExpressionInfo>(fSession.getExecutor(), rm) {
						@Override
						protected void handleCompleted() {
							if (isSuccess()) {
								setValue(getCurrentFormat(), getData().getValue());
								rm.setData(new FormattedValueDMData(getData().getValue()));
								rm.done();
							} else {
								rm.setStatus(getStatus());
								rm.done();
							}

							// Unlock is done within this method
							resetFormatToNatural();
						}
					});
		}

		// In GDB, var-update will only report a change if -var-evaluate-expression has
		// changed -- in the current format--.  This means that situations like
		// double z = 1.2;
		// z = 1.4;
		// Will not report a change if the format is anything else than natural.
		// This is because 1.2 and 1.4 are both printed as 1, 0x1, etc
		// Since we cache the values of every format, we must know if -any- format has
		// changed, not just the current one.
		// To solve this, we always do an update in the natural format; I am not aware
		// of any case where the natural format would stay the same, but another format
		// would change.  However, since a var-update update all children as well,
		// we must make sure these children are also in the natural format
		// The simplest way to do this is that whenever we change the format
		// of a variable object, we immediately set it back to natural with a second
		// var-set-format command.
		private void resetFormatToNatural() {
			if (!getCurrentFormat().equals(IFormattedValues.NATURAL_FORMAT)) {
				fCommandControl.queueCommand(
						fCommandFactory.createMIVarSetFormat(getRootToUpdate().getControlDMContext(), getGdbName(),
								IFormattedValues.NATURAL_FORMAT),
						new DataRequestMonitor<MIVarSetFormatInfo>(fSession.getExecutor(), null) {
							@Override
							protected void handleCompleted() {
								if (isSuccess()) {
									setCurrentFormat(IFormattedValues.NATURAL_FORMAT);
								}
								unlock();
							}
						});
			} else {
				unlock();
			}
		}

		/**
		 * This method returns the list of children of the variable object
		 * passed as a parameter.
		 *
		 * @param exprDmc
		 *
		 * @param clientNumChildrenLimit
		 *            If the current limit for the given expression is smaller,
		 *            this limit will be applied.
		 * @param rm
		 *            The data request monitor that will hold the children
		 *            returned
		 */
		private void getChildren(final IExpressionDMContext exprDmc, final int clientNumChildrenLimit,
				final DataRequestMonitor<ChildrenInfo> rm) {

			if (fFetchingChildren) {
				// Only one request monitor can fetch children at a time.
				fetchChildrenPending.add(new DataRequestMonitor<ChildrenInfo>(fSession.getExecutor(), rm) {

					@Override
					protected void handleSuccess() {
						ChildrenInfo info = getData();
						int numChildren = info.getChildren().length;
						if (!info.hasMore() || numChildren >= clientNumChildrenLimit) {
							// No need to fetch further children.
							rm.setData(getData());
							rm.done();
						} else {
							// Need to retry.
							getChildren(exprDmc, clientNumChildrenLimit, rm);
						}
					}

				});
			} else {

				fFetchingChildren = true;

				fetchChildren(exprDmc, clientNumChildrenLimit,
						new DataRequestMonitor<ChildrenInfo>(fSession.getExecutor(), rm) {

							@Override
							protected void handleCompleted() {
								fFetchingChildren = false;

								if (isSuccess()) {
									rm.setData(getData());
									rm.done();

									while (!fetchChildrenPending.isEmpty()) {
										DataRequestMonitor<ChildrenInfo> pendingRm = fetchChildrenPending.poll();
										pendingRm.setData(getData());
										pendingRm.done();
									}
								} else {
									rm.setStatus(getStatus());
									rm.done();

									while (!fetchChildrenPending.isEmpty()) {
										DataRequestMonitor<ChildrenInfo> pendingRm = fetchChildrenPending.poll();
										pendingRm.setStatus(getStatus());
										pendingRm.done();
									}
								}
							}
						});
			}
		}

		/**
		 * Fetch the out-standing children.
		 *
		 * @param exprDmc
		 *
		 * @param clientNumChildrenLimit
		 *            If the current limit for the given expression is smaller,
		 *            this limit will be applied.
		 * @param rm
		 *            The data request monitor that will hold the children
		 *            returned
		 * @since 4.3
		 */
		protected void fetchChildren(final IExpressionDMContext exprDmc, int clientNumChildrenLimit,
				final DataRequestMonitor<ChildrenInfo> rm) {

			final int newNumChildrenLimit = clientNumChildrenLimit != IMIExpressions.CHILD_COUNT_LIMIT_UNSPECIFIED
					? clientNumChildrenLimit
					: 1;

			boolean addChildren = requiresAdditionalChildren(newNumChildrenLimit);

			// If we already know the children, no need to go to the back-end
			ExpressionInfo[] childrenArray = getChildren();
			if (childrenArray != null && !addChildren) {
				rm.setData(new ChildrenInfo(childrenArray, fHasMore));
				rm.done();
				return;
			}

			// If the variable does not have children, we can return an empty list right away
			if (!hasChildren()) {
				// First store the empty list, for the next time
				setChildren(new ExpressionInfo[0]);
				rm.setData(new ChildrenInfo(getChildren(), fHasMore));
				rm.done();
				return;
			}

			// For arrays (which could be very large), we create the children ourselves.  This is
			// to avoid creating an enormous amount of children variable objects that the view may
			// never need.  Using -var-list-children will create a variable object for every child
			// immediately, that is why we don't want to use it for arrays.
			if (isArray()) {
				ExpressionInfo[] childrenOfArray = new ExpressionInfo[getNumChildrenHint()];
				String exprName = exprDmc.getExpression();

				int castingIndex = 0;
				// in case of casts, need to resolve that before dereferencing, to be safe
				if (exprDmc instanceof ICastedExpressionDMContext) {
					castingIndex = ((ICastedExpressionDMContext) exprDmc).getCastInfo().getArrayStartIndex();
				}
				if (exprDmc instanceof IIndexedPartitionDMContext) {
					castingIndex = ((IIndexedPartitionDMContext) exprDmc).getIndex();
				}
				for (int i = 0; i < childrenOfArray.length; i++) {
					String fullExpr = exprName + "[" + i + "]";//$NON-NLS-1$//$NON-NLS-2$

					String relExpr;
					if (exprDmc instanceof MIExpressionDMC) {
						relExpr = ((MIExpressionDMC) exprDmc).getRelativeExpression();
					} else {
						// Unexpected, but avoid exception
						relExpr = exprDmc.getExpression();
					}
					relExpr = relExpr + "[" + (castingIndex + i) + "]";//$NON-NLS-1$//$NON-NLS-2$

					childrenOfArray[i] = new ExpressionInfo(fullExpr, relExpr, false, fExprInfo, i);
				}

				// First store these children, for the next time
				setChildren(childrenOfArray);
				fHasMore = false;
				rm.setData(new ChildrenInfo(getChildren(), fHasMore));
				rm.done();
				return;
			}

			// No need to wait for the object to be ready since listing children can be performed
			// at any time, as long as the object is created, which we know it is, since we can only
			// be called here with a fully created object.
			// Also no need to lock the object, since getting the children won't affect other operations

			final int from = (addChildren && (fChildren != null)) ? getNumChildrenHint() : 0;
			final int to = Math.max(newNumChildrenLimit, fExprInfo.getChildCountLimit());

			ICommand<MIVarListChildrenInfo> varListChildren = isSafeToAskForAllChildren()
					? fCommandFactory.createMIVarListChildren(getRootToUpdate().getControlDMContext(), getGdbName())
					: fCommandFactory.createMIVarListChildren(getRootToUpdate().getControlDMContext(), getGdbName(),
							from, to);

			fCommandControl.queueCommand(varListChildren,
					new DataRequestMonitor<MIVarListChildrenInfo>(fSession.getExecutor(), rm) {
						@Override
						protected void handleSuccess() {
							MIVar[] children = getData().getMIVars();
							final boolean localHasMore = getData().hasMore();

							// The elements of this array normally are an ExpressionInfo, unless it corresponds to
							// a fake child (public, protected, private). In this case it is an ExpressionInfo[]
							// representing the children of the fake child.
							// This in done in order to preserve the order (the index-in-parent information),
							// when replacing a fake child by its real children.
							final ExpressionInfo[][] realChildren = new ExpressionInfo[children.length][];

							final CountingRequestMonitor countingRm = new CountingRequestMonitor(fSession.getExecutor(),
									rm) {
								@Override
								protected void handleSuccess() {
									// Store the children in our variable object cache
									addChildren(realChildren);
									fHasMore = localHasMore;
									rm.setData(new ChildrenInfo(getChildren(), fHasMore));

									int updateLimit = updateLimit(to);

									if (!isSafeToAskForAllChildren()) {
										// Make sure the gdb will not hang, if later
										// the varobj is updated, but the underlying
										// data is still uninitialized.
										fCommandControl.queueCommand(fCommandFactory.createMIVarSetUpdateRange(
												getRootToUpdate().getControlDMContext(), getGdbName(), 0, updateLimit),
												new DataRequestMonitor<MIInfo>(fSession.getExecutor(), rm));
									} else {
										rm.done();
									}
								}
							};

							int numSubRequests = 0;
							for (int i = 0; i < children.length; ++i) {
								final MIVar child = children[i];
								final int indexInParent = from + i;
								final int arrayPosition = i;

								// These children get created automatically as variable objects in GDB, so we should
								// add them to the LRU.
								// Note that if this variable object already exists, we can be in three scenarios:
								// 1- the existing object is the same variable object in GDB.  In this case,
								//    the existing and new one are identical so we can keep either one.
								// 2- the existing object is out-of-scope and should be replaced by the new one.
								//    This can happen if a root was found to be out-of-scope, but this child
								//    had not been accessed and therefore had not been removed.
								// 3- the existing object is an in-scope root object representing the same expression.
								//    In this case, either object can be kept and the other one can be deleted.
								//    The existing root could currently be in-use by another operation and may
								//    not be deleted; but since we can only have one entry in the LRU, we are
								//    forced to keep the existing root.  Note that we need not worry about
								//    the newly created child since it will automatically be deleted when
								//    its root is deleted.

								numSubRequests++;

								// Class to keep track of the child's full expression, but also
								// if that child had to use the CastToBaseClassWorkaround,
								// which needs to be propagated to its own children.
								class ChildFullExpressionInfo {
									private String childFullExpression;
									private boolean childHasCastToBaseClassWorkaround;

									public ChildFullExpressionInfo(String path) {
										this(path, false);
									}

									public ChildFullExpressionInfo(String path, boolean hasWorkaround) {
										childFullExpression = path == null ? "" : path; //$NON-NLS-1$
										childHasCastToBaseClassWorkaround = hasWorkaround;
									}

									public String getChildPath() {
										return childFullExpression;
									}

									public boolean getChildHasCastToBaseClassWorkaround() {
										return childHasCastToBaseClassWorkaround;
									}
								}

								final DataRequestMonitor<ChildFullExpressionInfo> childPathRm = new DataRequestMonitor<ChildFullExpressionInfo>(
										fSession.getExecutor(), countingRm) {
									@Override
									protected void handleSuccess() {
										final String childPath = getData().getChildPath();
										// The child varObj we are about to create should have hasCastToBaseClassWorkaround
										// set in two conditions:
										// 1- if its parent was set (which is the current varObj)
										// 2- if the workaround was used for the child itself, which is part of ChildFullExpressionInfo
										final boolean childHasCastToBaseClassWorkaround = fHasCastToBaseClassWorkaround
												|| getData().getChildHasCastToBaseClassWorkaround();

										// For children that do not map to a real expression (such as f.public)
										// GDB returns an empty string.  In this case, we can use another unique
										// name, such as the variable name
										final boolean fakeChild = (childPath.length() == 0);
										final String childFullExpression = fakeChild ? child.getVarName() : childPath;

										// Now try to see if we already have this variable object in our Map
										// Since our map names use the expression, and not the GDB given
										// name, we must determine the correct map name from the varName
										final VariableObjectId childId = new VariableObjectId();
										childId.generateId(childFullExpression, getInternalId());
										MIVariableObject childVar = lruVariableList.get(childId);

										if (childVar != null) {

											if ((childVar.currentState == STATE_CREATING)
													|| (childVar.currentState == STATE_NOT_CREATED)) {

												// We must wait until the child MIVariableObject is fully created.
												// This might succeed, or fail. If it succeeds, we can reuse it as
												// a child, otherwise we create a new MIVariableObject for the
												// varobj just provided by gdb.

												final MIVariableObject monitoredVar = childVar;

												// childVar is not fully created so add a RequestMonitor to the queue
												childVar.updatesPending.add(new DataRequestMonitor<Boolean>(
														fSession.getExecutor(), countingRm) {

													@Override
													protected void handleCompleted() {
														MIVariableObject var = monitoredVar;

														if (!isSuccess()) {

															// Create a fresh MIVariableObject for this child, using
															// the new varobj provided by gdb.
															var = createChild(childId, childFullExpression,
																	indexInParent, child);
														}

														var.fHasCastToBaseClassWorkaround = childHasCastToBaseClassWorkaround;

														if (fakeChild) {
															if (!isSuccess()) {
																fFakeChildren.add(var.fExprInfo);
															}
															addRealChildrenOfFake(var, exprDmc, realChildren,
																	arrayPosition, countingRm);
														} else {
															// This is a real child
															realChildren[arrayPosition] = new ExpressionInfo[] {
																	var.fExprInfo };
															countingRm.done();
														}
													}
												});
											} else if (childVar.currentState == STATE_CREATION_FAILED) {
												// There has been an attempt the create a MIRootVariableObject for a full
												// expression representing a child of a dynamic varobj. Such an attempt always
												// fails. But here we can now create it (see below).
												childVar = null;
											}
											// Note that we must check the root to know if it is out-of-scope.
											// We cannot check the child as it has not be updated and its
											// outOfScope variable is not updated either.
											else if (childVar.getRootToUpdate().isOutOfScope()) {
												childVar.deleteInGdb();
												childVar = null;
											} else {
												// The child already exists so we can re-use it.
												childVar.fHasCastToBaseClassWorkaround = childHasCastToBaseClassWorkaround;
												if (fakeChild) {
													// I don't think this should happen, but we put it just in case
													addRealChildrenOfFake(childVar, exprDmc, realChildren,
															arrayPosition, countingRm);
												} else {
													// This is a real child, use it directly, however, we must
													// make sure that its relative expression is expressed with respect
													// to its parent, which may not be the case already, since that child
													// might have been created directly (not through the parent).
													// That is why we set the relative expression explicitly
													// See bug 432888
													ExpressionInfo oldInfo = childVar.getExpressionInfo();
													realChildren[arrayPosition] = new ExpressionInfo[] {
															new ExpressionInfo(oldInfo.getFullExpr(), child.getExp(),
																	oldInfo.isDynamic(), oldInfo.getParent(),
																	oldInfo.getIndexInParentExpression()) };
													countingRm.done();
												}
											}
										}

										if (childVar == null) {
											childVar = createChild(childId, childFullExpression, indexInParent, child);

											childVar.fHasCastToBaseClassWorkaround = childHasCastToBaseClassWorkaround;

											if (fakeChild) {
												fFakeChildren.add(childVar.fExprInfo);
												addRealChildrenOfFake(childVar, exprDmc, realChildren, arrayPosition,
														countingRm);
											} else {
												// This is a real child
												realChildren[arrayPosition] = new ExpressionInfo[] {
														childVar.fExprInfo };
												countingRm.done();
											}
										}
									}
								};

								if (isAccessQualifier(child.getExp())) {
									// This is just a qualifier level of C++, so we don't need
									// to call -var-info-path-expression for real, but just pretend we did.
									childPathRm.setData(new ChildFullExpressionInfo("")); //$NON-NLS-1$
									childPathRm.done();
								} else if (isDynamic() || fExprInfo.hasDynamicAncestor()) {
									// Equivalent to (which can't be implemented): child.hasDynamicAncestor
									// The new child has a dynamic ancestor. Such children don't support
									// var-info-path-expression. Build the expression ourselves.
									childPathRm.setData(new ChildFullExpressionInfo(
											buildChildExpression(exprDmc.getExpression(), child.getExp())));
									childPathRm.done();
								} else if (fHasCastToBaseClassWorkaround) {
									// We had to use the "CastToBaseClass" workaround in the hierarchy, so we
									// know -var-info-path-expression won't work in this case.  We have to
									// build the expression ourselves again to keep the workaround as part
									// of the child's expression.
									childPathRm.setData(new ChildFullExpressionInfo(
											buildChildExpression(exprDmc.getExpression(), child.getExp())));
									childPathRm.done();
								} else {
									// To build the child id, we need the fully qualified expression which we
									// can get from -var-info-path-expression starting from GDB 6.7
									fCommandControl.queueCommand(
											fCommandFactory.createMIVarInfoPathExpression(
													getRootToUpdate().getControlDMContext(), child.getVarName()),
											new DataRequestMonitor<MIVarInfoPathExpressionInfo>(fSession.getExecutor(),
													childPathRm) {
												@Override
												protected void handleCompleted() {
													if (isSuccess()) {
														final String expression = getData().getFullExpression();

														if (needFixForGDBBug320277()
																&& child.getExp().equals(child.getType())
																&& !isAccessQualifier(
																		getExpressionInfo().getRelExpr())) {
															// Special handling for a derived class that is cast to its base class (see bug 320277)
															//
															// If the name of a child equals its type then it could be a base class.
															// The exception is when the name of the actual variable is identical with the type name (bad coding style :-))
															// The only way to tell the difference is to check if the parent is a fake (public/private/protected).
															//
															// What we could do instead, is make sure we are using C++ (using -var-info-expression).  That would
															// be safer.  However, at this time, there does not seem to be a way to create a variable with the same
															// name and type using plain C, so we are safe.
															//
															// When we know we are dealing with derived class that is cast to its base class
															// -var-info-path-expression returns (*(testbase*) this) and in some cases
															// this expression will fail when being evaluated in GDB because of a GDB bug.
															// Instead, we need (*(struct testbase*) this).
															//
															// To check if GDB actually has this bug we call -data-evaluate-expression with the return value
															// of -var-info-path-expression
															IExpressionDMContext exprDmcMIData = fExpressionService
																	.createExpression(exprDmc, expression);
															fCommandControl.queueCommand(
																	fCommandFactory.createMIDataEvaluateExpression(
																			exprDmcMIData),
																	new DataRequestMonitor<MIDataEvaluateExpressionInfo>(
																			fSession.getExecutor(), childPathRm) {
																		@Override
																		protected void handleCompleted() {
																			if (isSuccess()) {
																				childPathRm.setData(
																						new ChildFullExpressionInfo(
																								expression));
																				childPathRm.done();
																			} else {
																				// We build the expression ourselves
																				// We must also indicate that this workaround has been used for this child
																				// so that we know to keep using it for further descendants.
																				childPathRm.setData(
																						new ChildFullExpressionInfo(
																								buildDerivedChildExpression(
																										exprDmc.getExpression(),
																										child.getExp()),
																								true));
																				childPathRm.done();
																			}
																		}
																	});
														} else {
															childPathRm
																	.setData(new ChildFullExpressionInfo(expression));
															childPathRm.done();
														}
													} else {
														// If we don't have var-info-path-expression
														// build the expression ourselves
														// Note that this does not work well yet
														childPathRm.setData(
																new ChildFullExpressionInfo(buildChildExpression(
																		exprDmc.getExpression(), child.getExp())));
														childPathRm.done();
													}
												}
											});
								}
							}

							countingRm.setDoneCount(numSubRequests);
						}
					});
		}

		/**
		 * Create a child variable of this MIVariableObject and initialize
		 * it from the given MIVar data.
		 *
		 * @param childId
		 * @param childFullExpression
		 * @param indexInParent
		 * @param childData
		 *
		 * @return The new child.
		 *
		 * @since 4.0
		 */
		protected MIVariableObject createChild(final VariableObjectId childId, final String childFullExpression,
				final int indexInParent, final MIVar childData) {

			MIVariableObject var = createVariableObject(childId, this);
			ExpressionInfo childInfo = new ExpressionInfo(childFullExpression, childData.getExp(),
					childData.isDynamic(), fExprInfo, indexInParent);

			var.initFrom(childData, childInfo);
			return var;
		}

		/**
		 * @param clientLimit
		 * @return True, if the client specified limit requires to check for
		 *         further children.
		 *
		 * @since 4.0
		 */
		protected boolean requiresAdditionalChildren(int clientLimit) {
			return !isSafeToAskForAllChildren() && (fExprInfo.getChildCountLimit() < calculateNewLimit(clientLimit));
		}

		/**
		 * @param newLimit
		 *            The new limit on the number of children being asked for or
		 *            being updated.
		 *
		 * @return The new limit.
		 * @since 4.0
		 */
		protected int updateLimit(int newLimit) {
			fExprInfo.setChildCountLimit(calculateNewLimit(newLimit));
			return fExprInfo.getChildCountLimit();
		}

		private int calculateNewLimit(int clientLimit) {
			int limit = fExprInfo.getChildCountLimit();

			if (!isSafeToAskForAllChildren() && clientLimit != IMIExpressions.CHILD_COUNT_LIMIT_UNSPECIFIED) {
				if (limit == IMIExpressions.CHILD_COUNT_LIMIT_UNSPECIFIED) {
					return clientLimit;
				} else if (limit < clientLimit) {
					return clientLimit;
				}
			}

			return limit;
		}

		/**
		 * Obtain the children of the given fake child (public, protected, or
		 * private) and insert them into a list of children at a given position.
		 *
		 * @param fakeChild
		 * @param frameCtxProvider
		 * @param realChildren
		 * @param position
		 * @param rm The request monitor on which to call done upon completion.
		 */
		private void addRealChildrenOfFake(MIVariableObject fakeChild, IExpressionDMContext frameCtxProvider,
				final ExpressionInfo[][] realChildren, final int position, final RequestMonitor rm) {

			MIExpressionDMC fakeExprCtx = createExpressionCtx(frameCtxProvider, fakeChild.fExprInfo);

			// This is just a qualifier level of C++, and we must get the
			// children of this child to get the real children
			fakeChild.getChildren(fakeExprCtx, IMIExpressions.CHILD_COUNT_LIMIT_UNSPECIFIED,
					new DataRequestMonitor<ChildrenInfo>(fSession.getExecutor(), rm) {

						@Override
						protected void handleCompleted() {
							if (isSuccess()) {
								realChildren[position] = getData().getChildren();

								// Fake nodes can never be dynamic varobjs, and because
								// of this, hasMore is always false.
								assert (!getData().hasMore());
							}
							rm.done();
						}
					});
		}

		/**
		 * Method performing special handling for a derived class that is cast to its base class (see bug 320277).
		 * The command '-var-info-path-expression' returns (*(testbase*) this) but we need (*(struct testbase*) this).
		 * Also, in case of a namespace this method adds additional backticks:
		 * (*(struct 'namespace::testbase'*) this)
		 */
		private String buildDerivedChildExpression(String parentExp, String childExpr) {

			final String CAST_PREFIX = "struct "; //$NON-NLS-1$

			// Before doing the cast, let's surround the child expression (base class name) with quotes
			// if it contains a :: which indicates a namespace
			String childNameForCast = childExpr.contains("::") ? "'" + childExpr + "'" : childExpr; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
			String childFullExpression;
			if (isPointer()) {
				// casting to pointer base class requires a slightly different format
				childFullExpression = "*(" + CAST_PREFIX + childNameForCast + "*)(" + parentExp + ")";//$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
			} else {
				// casting to base class
				childFullExpression = "(" + CAST_PREFIX + childNameForCast + ")" + parentExp;//$NON-NLS-1$ //$NON-NLS-2$
			}

			return childFullExpression;
		}

		/**
		 * This method builds a child expression based on its parent's expression.
		 * It is a fallback solution for when GDB doesn't support the var-info-path-expression.
		 *
		 * This method does not take care of inherited classes such as
		 * class foo : bar {
		 * ...
		 * }
		 * that case is hanlded by buildDerivedChildExpression
		 */
		private String buildChildExpression(String parentExp, String childExp) {
			String childFullExpression;

			// If the current varObj is a fake object, we obtain the proper parent
			// expression from the parent of the varObj.
			if (isAccessQualifier(fExprInfo.getRelExpr())) {
				parentExp = getParent().getExpression();
			}

			// For pointers, the child expression is already contained in the parent,
			// so we must simply prefix with *
			//  See Bug219179 for more information.
			if (!isDynamic() && !fExprInfo.hasDynamicAncestor() && isPointer()) {
				childFullExpression = "*(" + parentExp + ")"; //$NON-NLS-1$//$NON-NLS-2$
			} else {
				// We must surround the parentExp with parentheses because it
				// may be a casted expression.
				childFullExpression = "(" + parentExp + ")." + childExp; //$NON-NLS-1$ //$NON-NLS-2$
			}

			// No need for a special case for arrays since we deal with arrays differently
			// and don't call this method for them

			return childFullExpression;
		}

		/**
		 * This method returns the count of children of the variable object
		 * passed as a parameter.
		 *
		 * @param exprDmc
		 *
		 * @param numChildrenLimit
		 *            No need to check for more than this number of children.
		 *            However, it is legal to return a higher count if
		 *            we already new from earlier call that there are more
		 *            children.
		 *
		 * @param rm
		 *            The data request monitor that will hold the count of
		 *            children returned
		 * @since 4.3
		 */
		protected void getChildrenCount(IExpressionDMContext exprDmc, final int numChildrenLimit,
				final DataRequestMonitor<ChildrenCountInfo> rm) {
			if (isNumChildrenHintTrustworthy()) {
				rm.setData(new ChildrenCountInfo(getNumChildrenHint(), hasMore()));
				rm.done();
				return;
			}

			getChildren(exprDmc, numChildrenLimit, new DataRequestMonitor<ChildrenInfo>(fSession.getExecutor(), rm) {

				@Override
				protected void handleSuccess() {
					rm.setData(new ChildrenCountInfo(getData().getChildren().length, getData().hasMore()));
					rm.done();
				}
			});
		}

		/**
		 * This method request the back-end to change the value of the variable object.
		 *
		 * @param value
		 *            The new value.
		 *  @param formatId
		 *            The format the new value is specified in.
		 * @param rm
		 *            The request monitor to indicate the operation is finished
		 */
		private void writeValue(String value, String formatId, final RequestMonitor rm) {

			// If the variable is a complex structure (including an array), then we cannot write to it
			if (isComplex()) {
				rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, IDsfStatusConstants.REQUEST_FAILED,
						"Cannot change the value of a complex expression", null)); //$NON-NLS-1$
				rm.done();
				return;
			}

			// First deal with the format.  For GDB, the way to specify a format is to prefix the value with
			// 0x for hex, 0 for octal etc  So we need to make sure that 'value' has this prefix.
			// Note that there is no way to specify a binary format for GDB up to and including
			// GDB 6.7.1, so we convert 'value' into a decimal format.
			// If the formatId is NATURAL, we do nothing for now because it is more complicated.
			// For example for a bool, a value of "true" is correct and should be left as is,
			// but for a pointer a value of 16 should be sent to GDB as 0x16.  To figure this out,
			// we need to know the type of the variable, which we don't have yet.

			if (formatId.equals(IFormattedValues.HEX_FORMAT)) {
				if (!value.startsWith("0x")) { //$NON-NLS-1$
					value = "0x" + value; //$NON-NLS-1$
				}
			} else if (formatId.equals(IFormattedValues.OCTAL_FORMAT)) {
				if (!value.startsWith("0")) { //$NON-NLS-1$
					value = "0" + value; //$NON-NLS-1$
				}
			} else if (formatId.equals(IFormattedValues.BINARY_FORMAT)) {
				// convert from binary to decimal
				if (value.startsWith("0b")) { //$NON-NLS-1$
					value = value.substring(2, value.length());
				}
				try {
					value = new BigInteger(value, 2).toString();
				} catch (NumberFormatException e) {
					rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, IDsfStatusConstants.INVALID_HANDLE,
							"Invalid binary number: " + value, e)); //$NON-NLS-1$
					rm.done();
					return;
				}

				formatId = IFormattedValues.DECIMAL_FORMAT;
			} else if (formatId.equals(IFormattedValues.DECIMAL_FORMAT)) {
				// nothing to do
			} else if (formatId.equals(IFormattedValues.NATURAL_FORMAT)) {
				// we do nothing for now and let the user have put in the proper value
			} else {
				rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, IDsfStatusConstants.INVALID_HANDLE,
						"Unknown format: " + formatId, null)); //$NON-NLS-1$
				rm.done();
				return;
			}

			// If the value has not changed, no need to set it.
			// Return a warning status so that handleSuccess is not called and we don't send
			// an ExpressionChanged event
			if (value.equals(getValue(formatId))) {
				rm.setStatus(new Status(IStatus.WARNING, GdbPlugin.PLUGIN_ID, IDsfStatusConstants.NOT_SUPPORTED,
						"Setting to the same value of: " + value, null)); //$NON-NLS-1$
				rm.done();
				return;
			}

			// No need to be in ready state or to lock the object
			fCommandControl.queueCommand(
					fCommandFactory.createMIVarAssign(getRootToUpdate().getControlDMContext(), getGdbName(), value),
					new DataRequestMonitor<MIVarAssignInfo>(fSession.getExecutor(), rm) {
						@Override
						protected void handleSuccess() {
							// We must also mark all variable objects
							// as out-of-date. This is because some variable objects may be affected
							// by this one having changed.
							// e.g.,
							//    int i;
							//    int* pi = &i;
							// Here, if 'i' is changed by the user, then 'pi' will also change
							// Since there is no way to know this unless we keep track of all addresses,
							// we must mark everything as out-of-date.  See bug 213061
							markAllOutOfDate();

							// Useless since we just marked everything as out-of-date
							// resetValues(getData().getValue());

							rm.done();
						}
					});
		}

		private boolean isAccessQualifier(String str) {
			return str.equals("private") || str.equals("public") || str.equals("protected"); //$NON-NLS-1$  //$NON-NLS-2$  //$NON-NLS-3$
		}

		/**
		 * @return If true, this variable object can be reported as changed in
		 *         a -var-update MI command.
		 */
		public boolean isModifiable() {
			if (!isComplex() || isDynamic()) {
				return true;
			}
			return false;
		}

		/**
		 * @param exprCtx
		 * @param rm
		 *
		 * @since 4.0
		 */
		public void create(final IExpressionDMContext exprCtx, final RequestMonitor rm) {

			if (currentState == STATE_NOT_CREATED) {

				currentState = STATE_CREATING;

				final MIExpressionDMC miExprCtx = (MIExpressionDMC) exprCtx;
				final int indexInParent = miExprCtx.getExpressionInfo().getIndexInParentExpression();

				fCommandControl.queueCommand(
						fCommandFactory.createMIVarListChildren(getParent().getRootToUpdate().getControlDMContext(),
								getParent().getGdbName(), indexInParent, indexInParent + 1),
						new DataRequestMonitor<MIVarListChildrenInfo>(fSession.getExecutor(), rm) {

							@Override
							protected void handleSuccess() {
								if (getData().getMIVars().length == 1) {
									MIVar miVar = getData().getMIVars()[0];

									ExpressionInfo localExprInfo = miExprCtx.getExpressionInfo();

									localExprInfo.setDynamic(miVar.isDynamic());

									initFrom(miVar, localExprInfo);

									if (fExprInfo.isDynamic() && (fExprInfo
											.getChildCountLimit() != IMIExpressions.CHILD_COUNT_LIMIT_UNSPECIFIED)) {
										// Restore the original update range.
										fCommandControl.queueCommand(
												fCommandFactory.createMIVarSetUpdateRange(
														getRootToUpdate().getControlDMContext(), getGdbName(), 0,
														fExprInfo.getChildCountLimit()),
												new DataRequestMonitor<MIInfo>(fSession.getExecutor(), rm));
									} else {
										rm.done();
									}
								} else {
									rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID,
											IDsfStatusConstants.INTERNAL_ERROR,
											"Unexpected return on -var-list-children", null)); //$NON-NLS-1$
									rm.done();
								}
							}
						});
			} else {
				assert false;
			}
		}

		private void initFrom(MIVar miVar, ExpressionInfo newExprInfo) {
			// Possible Optimization in GDB: In -var-list-children, the has_more
			// field is missing for the children. As a workaround, we assume that
			// if numChild is 0 and has_more is omitted, we have more children.
			boolean newHasMore = miVar.hasMore() || (miVar.isDynamic() && (miVar.getNumChild() == 0));

			assert miVar.getRawFields() != null;
			fRaw = miVar.getRawFields();

			setGdbName(miVar.getVarName());
			setDisplayHint(miVar.getDisplayHint());
			setExpressionData(newExprInfo, miVar.getType(), miVar.getNumChild(), newHasMore);

			// This will replace any existing entry
			lruVariableList.put(getInternalId(), this);

			// Is this new child a modifiable descendant of the root?
			if (isModifiable()) {
				getRootToUpdate().addModifiableDescendant(miVar.getVarName(), this);
			}
		}
	}

	/**
	 * Method to allow to override the MIVariableObject creation
	 *
	 * @since 3.0
	 */
	protected MIVariableObject createVariableObject(VariableObjectId id, MIVariableObject parentObj) {
		return new MIVariableObject(id, parentObj);
	}

	/**
	 * Method to allow to override the MIVariableObject creation
	 *
	 * @since 4.0
	 */
	protected MIVariableObject createVariableObject(VariableObjectId id, MIVariableObject parentObj,
			boolean needsCreation) {
		return new MIVariableObject(id, parentObj, needsCreation);
	}

	/**
	 * @since 3.0
	 */
	public class MIRootVariableObject extends MIVariableObject {

		// The control context within which this variable object was created
		// It only needs to be stored in the Root VarObj since any children
		// will have the same control context
		private ICommandControlDMContext fControlContext = null;

		private boolean fOutOfDate = false;

		/**
		 * A modifiable descendant is any variable object that is a descendant and
		 * for which the value (leaf variable objects and dynamic variable objects)
		 * or number of children (dynamic variable objects) can change.
		 */
		private Map<String, MIVariableObject> modifiableDescendants;

		public MIRootVariableObject(VariableObjectId id) {
			super(id, null);
			currentState = STATE_NOT_CREATED;
			modifiableDescendants = new HashMap<>();
		}

		public ICommandControlDMContext getControlDMContext() {
			return fControlContext;
		}

		public boolean isUpdating() {
			return currentState == STATE_UPDATING;
		}

		public void setOutOfDate(boolean outOfDate) {
			fOutOfDate = outOfDate;
		}

		public boolean getOutOfDate() {
			return fOutOfDate;
		}

		// Remember that we must add ourself as a modifiable descendant if our value can change
		public void addModifiableDescendant(String gdbName, MIVariableObject descendant) {
			modifiableDescendants.put(gdbName, descendant);
		}

		/**
		 * Removes the descendant with the specified name from the collection of
		 * modifiable descendants. Does nothing if there is no child with such
		 * name.
		 *
		 * @since 4.1
		 */
		public void removeModifiableDescendant(String gdbName) {
			modifiableDescendants.remove(gdbName);
		}

		/**
		 * @since 4.0
		 */
		public void processChanges(MIVarChange[] updates, RequestMonitor rm) {
			CountingRequestMonitor countingRm = new CountingRequestMonitor(fSession.getExecutor(), rm);
			countingRm.setDoneCount(updates.length);

			for (MIVarChange update : updates) {
				MIVariableObject descendant = modifiableDescendants.get(update.getVarName());

				// Descendant should never be null, but just to be safe
				if (descendant != null) {
					descendant.processChange(update, countingRm);
				} else {
					// This can for instance happen if a child MIVariableObject is deleted
					// from the cache. The corresponding varobj in gdb does still exist,
					// and if it is changed, gdb reports it as changed in -var-update.
					countingRm.done();
				}
			}
		}

		@Override
		public void create(final IExpressionDMContext exprCtx, final RequestMonitor rm) {

			if (currentState == STATE_NOT_CREATED) {

				currentState = STATE_CREATING;
				fControlContext = DMContexts.getAncestorOfType(exprCtx, ICommandControlDMContext.class);

				fCommandControl.queueCommand(fCommandFactory.createMIVarCreate(exprCtx, exprCtx.getExpression()),
						new DataRequestMonitor<MIVarCreateInfo>(fSession.getExecutor(), rm) {
							@Override
							protected void handleCompleted() {
								if (isSuccess()) {
									setGdbName(getData().getName());
									setDisplayHint(getData().getDisplayHint());

									MIExpressionDMC miExprCtx = (MIExpressionDMC) exprCtx;
									ExpressionInfo localExprInfo = miExprCtx.getExpressionInfo();

									localExprInfo.setDynamic(getData().isDynamic());

									// Do not initialize the parent or indexInParent, since they may
									// already be set to something. This will happen for arrays.
									// Their default values are ok for other cases i.e., null and -1
									// bug 420366

									setExpressionData(localExprInfo, getData().getType(), getData().getNumChildren(),
											getData().hasMore());

									// Store the value returned at create (available in GDB 6.7)
									// Don't store if it is an array, since we want to show
									// the address of an array as its value
									if (getData().getValue() != null && !isArray()) {
										setValue(getCurrentFormat(), getData().getValue());
									}

									// If we are modifiable, we should be in our modifiable list
									if (isModifiable()) {
										addModifiableDescendant(getData().getName(), MIRootVariableObject.this);
									}

									if (localExprInfo.isDynamic() && (localExprInfo
											.getChildCountLimit() != IMIExpressions.CHILD_COUNT_LIMIT_UNSPECIFIED)) {

										// Restore the original update range.
										fCommandControl.queueCommand(
												fCommandFactory.createMIVarSetUpdateRange(
														getRootToUpdate().getControlDMContext(), getGdbName(), 0,
														localExprInfo.getChildCountLimit()),
												new DataRequestMonitor<MIInfo>(fSession.getExecutor(), rm));
									} else {
										rm.done();
									}
								} else {
									rm.setStatus(getStatus());
									rm.done();
								}
							}
						});
			} else {
				assert false;
			}
		}

		@Override
		public void update(final DataRequestMonitor<Boolean> rm) {

			if (isOutOfScope()) {
				rm.setData(false);
				rm.done();
			} else if (currentState != STATE_READY) {
				// Object is not fully created or is being updated
				// so add RequestMonitor to pending queue
				updatesPending.add(rm);
			} else if (!getOutOfDate()) {
				rm.setData(false);
				rm.done();
			} else {
				// Object needs to be updated in the back-end
				currentState = STATE_UPDATING;

				// In GDB, var-update will only report a change if -var-evaluate-expression has
				// changed -- in the current format--.  This means that situations like
				// double z = 1.2;
				// z = 1.4;
				// Will not report a change if the format is anything else than natural.
				// This is because 1.2 and 1.4 are both printed as 1, 0x1, etc
				// Since we cache the values of every format, we must know if -any- format has
				// changed, not just the current one.
				// To solve this, we always do an update in the natural format; I am not aware
				// of any case where the natural format would stay the same, but another format
				// would change.  However, since a var-update update all children as well,
				// we must make sure these children are also in the natural format
				// The simplest way to do this is that whenever we change the format
				// of a variable object, we immediately set it back to natural with a second
				// var-set-format command.  This is done in the getValue() method
				fCommandControl.queueCommand(
						fCommandFactory.createMIVarUpdate(getRootToUpdate().getControlDMContext(), getGdbName()),
						new DataRequestMonitor<MIVarUpdateInfo>(fSession.getExecutor(), rm) {
							@Override
							protected void handleCompleted() {
								if (isSuccess()) {
									setOutOfDate(false);

									MIVarChange[] changes = getData().getMIVarChanges();
									if (changes.length > 0 && !changes[0].isInScope()) {
										// Object is out-of-scope
										currentState = STATE_READY;

										outOfScope = true;

										// We can delete this root in GDB right away.  This is safe, even
										// if the root has children, because they are also out-of-scope.
										// We -must- also remove this entry from our LRU.  If we don't
										// we can end-up with a race condition that create this object
										// twice, or have an infinite loop while never re-creating the object.
										// The can happen if we update a child first then we request
										// the root later,
										lruVariableList.remove(getInternalId());

										rm.setData(true);
										rm.done();

										while (!updatesPending.isEmpty()) {
											DataRequestMonitor<Boolean> pendingRm = updatesPending.poll();
											pendingRm.setData(false);
											pendingRm.done();
										}
									} else {
										// The root object is now up-to-date, we must parse the changes, if any.
										processChanges(changes, new RequestMonitor(fSession.getExecutor(), rm) {
											@Override
											protected void handleCompleted() {
												currentState = STATE_READY;

												// We only mark this root as updated in our list if it is in-scope.
												// For out-of-scope object, we don't ever need to re-update them so
												// we don't need to add them to this list.
												rootVariableUpdated(MIRootVariableObject.this);

												if (isSuccess()) {
													rm.setData(false);
												} else {
													rm.setStatus(getStatus());
												}
												rm.done();

												while (!updatesPending.isEmpty()) {
													DataRequestMonitor<Boolean> pendingRm = updatesPending.poll();
													if (isSuccess()) {
														pendingRm.setData(false);
													} else {
														pendingRm.setStatus(getStatus());
													}
													pendingRm.done();
												}
											}
										});
									}
								} else {
									// We were not able to update for some reason
									currentState = STATE_READY;

									rm.setData(false);
									rm.done();

									while (!updatesPending.isEmpty()) {
										DataRequestMonitor<Boolean> pendingRm = updatesPending.poll();
										pendingRm.setStatus(getStatus());
										pendingRm.done();
									}
								}
							}
						});
			}
		}

		/**
		 * This method request the back-end to delete a variable object.
		 * We check if the GDB name has been filled to confirm that this object
		 * was actually successfully created on the back-end.
		 * Only root variable objects are deleted, while children are left in GDB
		 * to be deleted automatically when their root is deleted.
		 */
		@Override
		public void deleteInGdb() {
			if (getGdbName() != null) {
				fCommandControl.queueCommand(
						fCommandFactory.createMIVarDelete(getRootToUpdate().getControlDMContext(), getGdbName()),
						new DataRequestMonitor<MIVarDeleteInfo>(fSession.getExecutor(), null));
				// Nothing to do in the requestMonitor, since the object was already
				// removed from our list before calling this method.

				// Set the GDB name to null to make sure we don't attempt to delete
				// this variable a second time.  This can happen if the LRU triggers
				// an automatic delete.
				setGdbName(null);
			} else {
				// Variable was never created or was already deleted, no need to do anything.
			}

			super.deleteInGdb();
		}
	}

	/**
	 * Method to allow to override the MIRootVariableObject creation.
	 *
	 * @since 3.0
	 */
	protected MIRootVariableObject createRootVariableObject(VariableObjectId id) {
		return new MIRootVariableObject(id);
	}

	/**
	 * This class represents an unique identifier for a variable object.
	 *
	 * The following must be considered to obtain a unique name:
	 *     - the expression itself
	 *     - the execution context
	 *     - relative depth of frame based on the frame context and the total depth of the stack
	 *
	 * Note that if no frameContext is specified (only Execution, or even only Container), which can
	 * characterize a global variable for example, we will only use the available information.
	 *
	 * @since 3.0
	 */
	public class VariableObjectId {
		// We don't use the expression context because it is not safe to compare them
		// See bug 187718.  So we store the expression itself, and it's parent execution context.
		private String fExpression = null;
		private IExecutionDMContext fExecContext = null;
		// We need the depth of the frame.  The frame level is not sufficient because
		// the same frame will have a different level based on the current depth of the stack
		private Integer fFrameId = null;

		public VariableObjectId() {
		}

		@Override
		public boolean equals(Object other) {
			if (other instanceof VariableObjectId) {
				VariableObjectId otherId = (VariableObjectId) other;
				return (fExpression == null ? otherId.fExpression == null : fExpression.equals(otherId.fExpression))
						&& (fExecContext == null ? otherId.fExecContext == null
								: fExecContext.equals(otherId.fExecContext))
						&& (fFrameId == null ? otherId.fFrameId == null : fFrameId.equals(otherId.fFrameId));
			}
			return false;
		}

		@Override
		public int hashCode() {
			return (fExpression == null ? 0 : fExpression.hashCode())
					+ (fExecContext == null ? 0 : fExecContext.hashCode())
					+ (fFrameId == null ? 0 : fFrameId.hashCode());
		}

		public void generateId(IExpressionDMContext exprCtx, final RequestMonitor rm) {
			fExpression = exprCtx.getExpression();

			fExecContext = DMContexts.getAncestorOfType(exprCtx, IExecutionDMContext.class);
			if (fExecContext == null) {
				rm.done();
				return;
			}

			final IFrameDMContext frameCtx = DMContexts.getAncestorOfType(exprCtx, IFrameDMContext.class);
			if (frameCtx == null) {
				rm.done();
				return;
			}

			// We need the current stack depth to be able to make a unique and reproducible name
			// for this expression.  This is pretty efficient since the stackDepth will be retrieved
			// from the StackService command cache after the first time.
			fStackService.getStackDepth(fExecContext, 0, new DataRequestMonitor<Integer>(fSession.getExecutor(), rm) {
				@Override
				protected void handleSuccess() {
					fFrameId = Integer.valueOf(getData() - frameCtx.getLevel());
					rm.done();
				}
			});
		}

		public void generateId(String childFullExp, VariableObjectId parentId) {
			// The execution context and the frame depth are the same as the parent
			fExecContext = parentId.fExecContext;
			fFrameId = parentId.fFrameId;
			// The expression here must be the one that is part of IExpressionContext for this child
			// This will allow us to find a variable object directly
			fExpression = childFullExp;
		}
	}

	/**
	 * Method to allow to override the VariableObjectId creation.
	 *
	 * @since 3.0
	 */
	protected VariableObjectId createVariableObjectId() {
		return new VariableObjectId();
	}

	/**
	 * This is the real work horse of managing our objects. Not only must every
	 * value be unique to get inserted, this also creates an LRU (least recently
	 * used). When we hit our size limitation, the LRUsed will be removed to
	 * make space. Removing means that a GDB request to delete the object is
	 * generated.  We must also take into consideration the fact that GDB will
	 * automatically delete children of a variable object, when deleting the parent
	 * variable object.  Our solution to that is to tweak the LRU to make sure that
	 * children are always older than their parents, to guarantee the children will
	 * always be delete before their parents.
	 *
	 */
	private static class LRUVariableCache extends LinkedHashMap<VariableObjectId, MIVariableObject> {
		public static final long serialVersionUID = 0;

		// Maximum allowed concurrent variables
		private static final int MAX_VARIABLE_LIST = 1000;

		public LRUVariableCache() {
			super(0, // Initial load capacity
					0.75f, // Load factor as defined in JAVA 1.5
					true); // Order is dictated by access, not insertion
		}

		// We never remove doing put operations.  Instead, we rely on our get() operations
		// to trigger the remove.  See bug 200897
		@Override
		public boolean removeEldestEntry(Map.Entry<VariableObjectId, MIVariableObject> eldest) {
			return false;
		}

		@Override
		public MIVariableObject get(Object key) {
			MIVariableObject varObj = super.get(key);
			touchAncestors(varObj);

			// If we're over our max size, attempt to remove eldest entry.
			if (size() > MAX_VARIABLE_LIST) {
				Map.Entry<VariableObjectId, MIVariableObject> eldest = entrySet().iterator().next();
				// First make sure we are not deleting ourselves!
				if (!eldest.getValue().equals(varObj)
						&& eldest.getValue().currentState == MIVariableObject.STATE_READY) {
					remove(eldest.getKey());
				}
			}
			return varObj;
		}

		private void touchAncestors(MIVariableObject varObj) {
			while (varObj != null) {
				varObj = varObj.getParent();
				// If there is a parent, touch it
				if (varObj != null) {
					super.get(varObj.getInternalId());
				}
			}
		}

		@Override
		public MIVariableObject put(VariableObjectId key, MIVariableObject varObj) {
			MIVariableObject retVal = super.put(key, varObj);

			// Touch all parents of this element so as
			// to guarantee they are not deleted before their children.
			touchAncestors(varObj);

			return retVal;
		}

		@Override
		public MIVariableObject remove(Object key) {
			MIVariableObject varObj = super.remove(key);
			if (varObj != null) {
				varObj.deleteInGdb();
			}
			return varObj;
		}
	}

	private GDBTypeParser fGDBTypeParser = null;

	private final DsfSession fSession;

	/** Provides access to the GDB/MI back-end */
	private final ICommandControl fCommandControl;
	private CommandFactory fCommandFactory;

	// The stack service needs to be used to get information such
	// as the stack depth to differentiate between expressions that have the
	// same name but refer to a different context
	private final IStack fStackService;
	private IExpressions fExpressionService;

	// Typically, there will only be one listener, since only the ExpressionService will use this class
	private final List<ICommandListener> fCommandProcessors = new ArrayList<>();

	/** Our least recently used cache */
	private final LRUVariableCache lruVariableList;

	/** The list of root variable objects that have been updated */
	private final LinkedList<MIRootVariableObject> updatedRootList = new LinkedList<>();

	/**
	 * MIVariableManager constructor
	 *
	 * @param session
	 *            The session we are working with
	 * @param tracker
	 *            The service tracker that can be used to find other services
	 */
	public MIVariableManager(DsfSession session, DsfServicesTracker tracker) {
		fSession = session;
		lruVariableList = new LRUVariableCache();
		fCommandControl = tracker.getService(ICommandControl.class);
		fStackService = tracker.getService(IStack.class);
		fExpressionService = tracker.getService(IExpressions.class);
		fCommandFactory = tracker.getService(IMICommandControl.class).getCommandFactory();

		// Register to receive service events for this session.
		fSession.addServiceEventListener(this, null);
	}

	public void dispose() {
		fSession.removeServiceEventListener(this);
	}

	/**
	 * @since 3.0
	 */
	protected DsfSession getSession() {
		return fSession;
	}

	/**
	 * @since 3.0
	 */
	protected ICommandControl getCommandControl() {
		return fCommandControl;
	}

	/**
	 * @since 3.0
	 */
	protected void rootVariableUpdated(MIRootVariableObject rootObj) {
		updatedRootList.add(rootObj);
	}

	/**
	 * @since 3.0
	 */
	protected Map<VariableObjectId, MIVariableObject> getLRUCache() {
		return lruVariableList;
	}

	private GDBTypeParser getGDBTypeParser() {
		if (fGDBTypeParser == null) {
			fGDBTypeParser = createGDBTypeParser();
		}
		return fGDBTypeParser;
	}

	/**
	 * This method returns a variable object based on the specified
	 * ExpressionDMC, creating it in GDB if it was not created already.
	 * The method guarantees that the variable is finished creating and that
	 * is it not out-of-scope.
	 *
	 * @param exprCtx
	 *            The expression context to which the variable object is applied to.
	 *
	 * @param rm
	 *            The data request monitor that will contain the requested variable object
	 */
	private void getVariable(final IExpressionDMContext exprCtx, final DataRequestMonitor<MIVariableObject> rm) {
		// Generate an id for this expression so that we can determine if we already
		// have a variable object tracking it.  If we don't we'll need to create one.
		final VariableObjectId id = createVariableObjectId();
		id.generateId(exprCtx, new RequestMonitor(fSession.getExecutor(), rm) {
			@Override
			protected void handleSuccess() {
				getVariable(id, exprCtx, rm);
			}
		});
	}

	private void getVariable(final VariableObjectId id, final IExpressionDMContext exprCtx,
			final DataRequestMonitor<MIVariableObject> rm) {

		final MIVariableObject varObj = lruVariableList.get(id);

		if (varObj == null) {
			// We do not have this varObject, so we create it
			createVariable(id, exprCtx, rm);
		} else {
			// We have found a varObject, but it may not be updated yet.
			// Updating the object will also tell us if it is out-of-scope
			// and if we should re-create it.
			varObj.update(new DataRequestMonitor<Boolean>(fSession.getExecutor(), rm) {
				@Override
				protected void handleSuccess() {

					boolean shouldCreateNew = getData().booleanValue();

					if (varObj.isOutOfScope()) {
						// The variable object is out-of-scope and we
						// should not use it.
						if (shouldCreateNew) {
							/*
							 * It may happen that when accessing a varObject we find it to be
							 * out-of-scope.  The expression for which we are trying to access a varObject
							 * could still be valid, and therefore we should try to create a new varObject for
							 * that expression.  This can happen for example if two methods use the same name
							 * for a variable. In the case when we find that a varObject is out-of-scope (when
							 * its root is out-of-scope) the following should be done:
							 *
							 * - create a new varObject for the expression (as a root varObject) and insert it
							 * in the LRU.  Make sure that when creating children of this new varObject, they
							 * will replace any old children with the same name in the LRU (this is ok since the
							 * children being replaced are also out-of-scope).
							 */

							createVariable(id, exprCtx, rm);
						} else {
							// Just request the variable object again
							// We must use this call to handle the fact that
							// the new object might be in the middle of being
							// created.
							getVariable(id, exprCtx, rm);
						}
					} else {
						// The variable object is up-to-date and valid

						MIExpressionDMC miExprCtx = (MIExpressionDMC) exprCtx;
						ExpressionInfo ctxExprInfo = miExprCtx.getExpressionInfo();
						ExpressionInfo varExprInfo = varObj.getExpressionInfo();
						// Don't use equals() below because we are concerned with other fields
						// of ExpressionInfo that are not considered when doing equals().
						// Instead, only consider equal if both objects are the same one
						if (ctxExprInfo != varExprInfo) {
							// exprCtrx could just be created via IExpressions.createExpression,
							// and thus the parent-child relationship is not yet set.
							// Set that relationship while keeping the relative expression of
							// the original context (see bug 393930)
							miExprCtx.setExpressionInfo(new ExpressionInfo(miExprCtx.getExpression(),
									miExprCtx.getRelativeExpression(), varExprInfo.isDynamic(), varExprInfo.getParent(),
									varExprInfo.getIndexInParentExpression()));
						}

						rm.setData(varObj);
						rm.done();
					}
				}
			});
		}
	}

	/**
	 * This method creates a variable object in GDB.
	 */
	private void createVariable(final VariableObjectId id, final IExpressionDMContext exprCtx,
			final DataRequestMonitor<MIVariableObject> rm) {

		// If we have a dynamic variable object as ancestor, we cannot use
		// -var-create, so we must create ourselves creating the root, and
		// then use -var-list-children for each further ancestor.
		final MIExpressionDMC miExprCtx = (MIExpressionDMC) exprCtx;
		final ExpressionInfo parentInfo = miExprCtx.getExpressionInfo().getParent();

		if ((parentInfo != null) && miExprCtx.getExpressionInfo().hasDynamicAncestor()) {

			// Need to set parent when it is known.
			final MIVariableObject newVarObj = createVariableObject(id, null, true);

			// We must put this object in our map right away, in case it is
			// requested again, before it completes its creation.
			// Note that this will replace any old entry with the same id.
			lruVariableList.put(id, newVarObj);

			MIExpressionDMC parentExprCtx = createExpressionCtx(exprCtx, parentInfo);

			getVariable(parentExprCtx, new DataRequestMonitor<MIVariableObject>(fSession.getExecutor(), rm) {

				@Override
				protected void handleCompleted() {

					if (isSuccess()) {
						final MIVariableObject parentObj = getData();
						newVarObj.setParent(parentObj);

						newVarObj.create(miExprCtx, new RequestMonitor(fSession.getExecutor(), rm) {

							@Override
							protected void handleCompleted() {
								if (isSuccess()) {
									rm.setData(newVarObj);
									newVarObj.creationCompleted(true);
								} else {
									// Object was not created, remove it from our list
									lruVariableList.remove(id);
									// We avoid this race condition by sending the notifications _after_ removing
									// the object from the LRU, to avoid any new requests being queue.
									// See https://bugs.eclipse.org/bugs/show_bug.cgi?id=231655
									newVarObj.creationCompleted(false);
									rm.setStatus(getStatus());
								}
								rm.done();
							}
						});
					} else {
						// Object was not created, remove it from our list
						lruVariableList.remove(id);
						// We avoid this race condition by sending the notifications _after_ removing
						// the object from the LRU, to avoid any new requests being queue.
						// See https://bugs.eclipse.org/bugs/show_bug.cgi?id=231655
						newVarObj.creationCompleted(false);

						rm.setStatus(getStatus());
						rm.done();
					}
				}
			});

			return;
		}

		// Variable objects that are created directly like this, are considered ROOT variable objects
		// in comparison to variable objects that are children of other variable objects.
		final MIRootVariableObject newVarObj = createRootVariableObject(id);

		// We must put this object in our map right away, in case it is
		// requested again, before it completes its creation.
		// Note that this will replace any old entry with the same id.
		lruVariableList.put(id, newVarObj);

		newVarObj.create(exprCtx, new RequestMonitor(fSession.getExecutor(), rm) {
			@Override
			protected void handleCompleted() {
				if (isSuccess()) {
					// Also store the object as a varObj that is up-to-date
					rootVariableUpdated(newVarObj);
					// VarObj can now be used by others
					newVarObj.creationCompleted(true);

					rm.setData(newVarObj);
					rm.done();
				} else {
					// Object was not created, remove it from our list
					lruVariableList.remove(id);
					// Tell any waiting monitors that creation failed.
					// It is important to do this call after we have removed the id
					// from our LRU; this is to avoid the following:
					//   The same varObj is requested before it was removed from the LRU
					//   but after we called creationCompleted().
					//   In this case, the request for this varObj would be queued, but
					//   since creationCompleted() already sent the notifications
					//   the newly queue request will never get serviced.
					// We avoid this race condition by sending the notifications _after_ removing
					// the object from the LRU, to avoid any new requests being queue.
					// See https://bugs.eclipse.org/bugs/show_bug.cgi?id=231655
					newVarObj.creationCompleted(false);

					rm.setStatus(getStatus());
					rm.done();
				}
			}
		});
	}

	private MIExpressionDMC createExpressionCtx(final IExpressionDMContext frameCtxProvider,
			final ExpressionInfo exprInfo) {

		IFrameDMContext frameCtx = DMContexts.getAncestorOfType(frameCtxProvider, IFrameDMContext.class);

		MIExpressionDMC exprCtx = new MIExpressionDMC(frameCtxProvider.getSessionId(), exprInfo, frameCtx);

		return exprCtx;
	}

	/**
	 * This method requests the back-end to change the value of an expression.
	 *
	 * @param ctx
	 *            The context of the expression we want to change
	 * @param expressionValue
	 *            The new value of the expression
	 * @param formatId
	 *            The format in which the expressionValue is specified in
	 * @param rm
	 *            The request monitor to indicate the operation is finished
	 */
	// This method can be called directly from the ExpressionService, since it cannot be cached
	public void writeValue(final IExpressionDMContext ctx, final String expressionValue, final String formatId,
			final RequestMonitor rm) {

		getVariable(ctx, new DataRequestMonitor<MIVariableObject>(fSession.getExecutor(), rm) {
			@Override
			protected void handleSuccess() {
				getData().writeValue(expressionValue, formatId, rm);
			}
		});
	}

	@Override
	public <V extends ICommandResult> ICommandToken queueCommand(final ICommand<V> command, DataRequestMonitor<V> rm) {

		final ICommandToken token = new ICommandToken() {
			@Override
			public ICommand<? extends ICommandResult> getCommand() {
				return command;
			}
		};

		// The MIVariableManager does not buffer commands itself, but sends them directly to the real
		// MICommandControl service.  Therefore, we must immediately tell our calling cache that the command
		// has been sent, since we can never cancel it.  Note that this removes any option of coalescing,
		// but coalescing was not applicable to variableObjects anyway.
		processCommandSent(token);

		if (command instanceof ExprMetaGetVar) {
			@SuppressWarnings("unchecked")
			final DataRequestMonitor<ExprMetaGetVarInfo> drm = (DataRequestMonitor<ExprMetaGetVarInfo>) rm;
			final MIExpressionDMC exprCtx = (MIExpressionDMC) (command.getContext());

			getVariable(exprCtx, new DataRequestMonitor<MIVariableObject>(fSession.getExecutor(), drm) {
				@Override
				protected void handleSuccess() {
					final MIVariableObject varObj = getData();

					if (varObj.isDynamic() && (varObj.getNumChildrenHint() == 0) && varObj.hasMore()) {
						// Bug/feature in gdb? MI sometimes reports 0 number of children, and hasMore=1.
						// This however, is not a safe indicator that there are children,
						// unless there has been a -var-list-children before.
						// The following call will
						// 1) try to fetch at least one child, because isNumChildrenHintTrustworthy()
						//    returns false for this combination
						// 2) result in the desired -var-list-children, unless it has happened already
						// such that the number of children can at least be used to reliably
						// tell whether there are children or not.
						varObj.getChildrenCount(exprCtx, 1,
								new DataRequestMonitor<ChildrenCountInfo>(fSession.getExecutor(), drm) {
									@Override
									protected void handleSuccess() {
										drm.setData(new ExprMetaGetVarInfo(exprCtx.getRelativeExpression(), varObj,
												getData().getChildrenCount()));
										drm.done();
										processCommandDone(token, drm.getData());
									}
								});
					} else {
						drm.setData(new ExprMetaGetVarInfo(exprCtx.getRelativeExpression(), varObj));
						drm.done();
						processCommandDone(token, drm.getData());
					}
				}
			});
		} else if (command instanceof ExprMetaGetAttributes) {
			@SuppressWarnings("unchecked")
			final DataRequestMonitor<ExprMetaGetAttributesInfo> drm = (DataRequestMonitor<ExprMetaGetAttributesInfo>) rm;
			final IExpressionDMContext exprCtx = (IExpressionDMContext) (command.getContext());

			getVariable(exprCtx, new DataRequestMonitor<MIVariableObject>(fSession.getExecutor(), drm) {
				@Override
				protected void handleSuccess() {
					getData().getAttributes(new DataRequestMonitor<Boolean>(fSession.getExecutor(), drm) {
						@Override
						protected void handleSuccess() {
							drm.setData(new ExprMetaGetAttributesInfo(getData()));
							drm.done();
							processCommandDone(token, drm.getData());
						}
					});
				}
			});

		} else if (command instanceof ExprMetaGetValue) {
			@SuppressWarnings("unchecked")
			final DataRequestMonitor<ExprMetaGetValueInfo> drm = (DataRequestMonitor<ExprMetaGetValueInfo>) rm;
			final FormattedValueDMContext valueCtx = (FormattedValueDMContext) (command.getContext());
			final IExpressionDMContext exprCtx = DMContexts.getAncestorOfType(valueCtx, IExpressionDMContext.class);

			getVariable(exprCtx, new DataRequestMonitor<MIVariableObject>(fSession.getExecutor(), drm) {
				@Override
				protected void handleSuccess() {
					getData().getValue(valueCtx,
							new DataRequestMonitor<FormattedValueDMData>(fSession.getExecutor(), drm) {
								@Override
								protected void handleSuccess() {
									drm.setData(new ExprMetaGetValueInfo(getData().getFormattedValue()));
									drm.done();
									processCommandDone(token, drm.getData());
								}
							});
				}
			});

		} else if (command instanceof ExprMetaGetChildren) {
			@SuppressWarnings("unchecked")
			final DataRequestMonitor<ExprMetaGetChildrenInfo> drm = (DataRequestMonitor<ExprMetaGetChildrenInfo>) rm;
			final MIExpressionDMC exprCtx = (MIExpressionDMC) (command.getContext());

			getVariable(exprCtx, new DataRequestMonitor<MIVariableObject>(fSession.getExecutor(), drm) {
				@Override
				protected void handleSuccess() {
					getData().getChildren(exprCtx, ((ExprMetaGetChildren) command).getNumChildLimit(),
							new DataRequestMonitor<ChildrenInfo>(fSession.getExecutor(), drm) {
								@Override
								protected void handleSuccess() {
									drm.setData(new ExprMetaGetChildrenInfo(getData().getChildren()));
									drm.done();
									processCommandDone(token, drm.getData());
								}
							});
				}
			});

		} else if (command instanceof ExprMetaGetChildCount) {
			@SuppressWarnings("unchecked")
			final DataRequestMonitor<ExprMetaGetChildCountInfo> drm = (DataRequestMonitor<ExprMetaGetChildCountInfo>) rm;
			final MIExpressionDMC exprCtx = (MIExpressionDMC) (command.getContext());

			getVariable(exprCtx, new DataRequestMonitor<MIVariableObject>(fSession.getExecutor(), drm) {
				@Override
				protected void handleSuccess() {

					getData().getChildrenCount(exprCtx, ((ExprMetaGetChildCount) command).getNumChildLimit(),
							new DataRequestMonitor<ChildrenCountInfo>(fSession.getExecutor(), drm) {
								@Override
								protected void handleSuccess() {
									drm.setData(new ExprMetaGetChildCountInfo(getData().getChildrenCount()));
									drm.done();
									processCommandDone(token, drm.getData());
								}
							});
				}
			});

		} else if (command instanceof MIDataEvaluateExpression<?>) {
			// This does not use the variable objects but sends the command directly to the back-end
			fCommandControl.queueCommand(command, rm);
		} else {
			rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, IDsfStatusConstants.INTERNAL_ERROR,
					"Unexpected Expression Meta command", null)); //$NON-NLS-1$
			rm.done();
		}
		return token;
	}

	/*
	 *   This is the command which allows the user to retract a previously issued command. The
	 *   state of the command  is that it is in the waiting queue  and has not yet been handed
	 *   to the back-end yet.
	 *
	 * (non-Javadoc)
	 * @see org.eclipse.cdt.dsf.mi.service.command.IDebuggerControl#removeCommand(org.eclipse.cdt.dsf.mi.service.command.commands.ICommand)
	 */
	@Override
	public void removeCommand(ICommandToken token) {
		// It is impossible to remove a command from the MIVariableManager.
		// This should never be called, if we did things right.
		assert false;
	}

	/*
	 *  This command allows the user to try and cancel commands  which have been handed off to the
	 *  back-end. Some back-ends support this with extended GDB/MI commands. If the support is there
	 *  then we will attempt it.  Because of the bidirectional nature of the GDB/MI command stream
	 *  there is no guarantee that this will work. The response to the command could be on its way
	 *  back when the cancel command is being issued.
	 *
	 * (non-Javadoc)
	 * @see org.eclipse.cdt.dsf.mi.service.command.IDebuggerControl#cancelCommand(org.eclipse.cdt.dsf.mi.service.command.commands.ICommand)
	 */
	@Override
	public void addCommandListener(ICommandListener processor) {
		fCommandProcessors.add(processor);
	}

	@Override
	public void removeCommandListener(ICommandListener processor) {
		fCommandProcessors.remove(processor);
	}

	@Override
	public void addEventListener(IEventListener processor) {
	}

	@Override
	public void removeEventListener(IEventListener processor) {
	}

	private void processCommandSent(ICommandToken token) {
		for (ICommandListener processor : fCommandProcessors) {
			processor.commandSent(token);
		}
	}

	private void processCommandDone(ICommandToken token, ICommandResult result) {
		for (ICommandListener processor : fCommandProcessors) {
			processor.commandDone(token, result);
		}
	}

	/**
	 * @since 1.1
	 */
	public void markAllOutOfDate() {
		MIRootVariableObject root;
		while ((root = updatedRootList.poll()) != null) {
			root.setOutOfDate(true);
		}
	}

	@DsfServiceEventHandler
	public void eventDispatched(IRunControl.IResumedDMEvent e) {
		// Program has resumed, all variable objects need to be updated.
		// Since only roots can actually be updated in GDB, we only need
		// to deal with those.  Also, to optimize this operation, we have
		// a list of all roots that have been updated, so we only have to
		// set those to needing to be updated.
		markAllOutOfDate();
	}

	@DsfServiceEventHandler
	public void eventDispatched(IRunControl.ISuspendedDMEvent e) {
	}

	@DsfServiceEventHandler
	public void eventDispatched(IMemoryChangedEvent e) {
		// Some memory has changed.  We currently do not know the address
		// of each of our variable objects, so there is no way to know
		// which one is affected.  Mark them all as out of date.
		// The views will fully refresh on a MemoryChangedEvent
		markAllOutOfDate();
	}

	/**
	 * @since 3.0
	 */
	@DsfServiceEventHandler
	public void eventDispatched(ITraceRecordSelectedChangedDMEvent e) {
		// We have a big limitation with tracepoints!
		// GDB usually only reports a depth of 1, for every trace record, no
		// matter where it occurred.  This means that our naming scheme for VariableObjectId
		// fails miserably because all objects will have the same depth and we will confuse
		// them.  Until we find a good solution, we have to clear our entire list of
		// of variable objects (and delete them in GDB to avoid having too many).
		Iterator<Map.Entry<VariableObjectId, MIVariableObject>> iterator = lruVariableList.entrySet().iterator();
		while (iterator.hasNext()) {
			iterator.next();
			iterator.remove();
		}
	}

	/**
	 * GDB has a bug which makes -data-evaluate-expression fail when using
	 * the return value of -var-info-path-expression in the case of derived classes.
	 * To work around this bug, we don't use -var-info-path-expression for some derived
	 * classes and all their descendants.
	 *
	 * This method can be overridden to easily disable the workaround, for versions
	 * of GDB that no longer have the bug.
	 *
	 * See http://sourceware.org/bugzilla/show_bug.cgi?id=11912
	 * and Bug 320277.
	 *
	 * The bug was fixed in GDB 7.3.1.
	 *
	 * @since 4.1
	 */
	protected boolean needFixForGDBBug320277() {
		return true;
	}

	/**
	 * @since 4.4
	 */
	protected GDBTypeParser createGDBTypeParser() {
		return new GDBTypeParser();
	}

}
