Browse Source

Lazy getting refactored. Started lazy getting of properties

git-svn-id: svn://svn.sharpdevelop.net/sharpdevelop/trunk@835 1ccf3a8d-04fe-1044-b7c0-cef0b8235c61
shortcuts
David Srbecký 20 years ago
parent
commit
7318cbb775
  1. 4
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Threads/Function.cs
  2. 26
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/Evals/Eval.cs
  3. 66
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/PropertyVariable.cs
  4. 62
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/Variable.cs
  5. 12
      src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/VariableCollection.cs

4
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Threads/Function.cs

@ -499,7 +499,9 @@ namespace Debugger
if (debugger.PausedReason != PausedReason.AllEvalsComplete) { if (debugger.PausedReason != PausedReason.AllEvalsComplete) {
debugger.AddEval(eval); debugger.AddEval(eval);
} }
yield return new PropertyVariable(eval, method.Name.Remove(0, 4)); yield return new PropertyVariable(debugger,
method.Name.Remove(0, 4),
delegate {return eval;});
} }
} }
} }

26
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/Evals/Eval.cs

@ -27,7 +27,7 @@ namespace Debugger
ICorDebugValue[] args; ICorDebugValue[] args;
bool evaluating = false; bool evaluating = false;
bool completed = false; bool evaluated = false;
bool successful = false; bool successful = false;
Value result; Value result;
@ -43,9 +43,9 @@ namespace Debugger
/// <summary> /// <summary>
/// True if the evaluation has been completed. /// True if the evaluation has been completed.
/// </summary> /// </summary>
public bool Completed { public bool Evaluated {
get { get {
return completed; return evaluated;
} }
} }
@ -74,13 +74,17 @@ namespace Debugger
} }
/// <summary> /// <summary>
/// The result of the evaluation if the evaluation is complete and has returned a value. Null otherwise. /// The result of the evaluation. Always non-null, but it may be UnavailableValue.
/// </summary> /// </summary>
public Value Result { public Value Result {
get { get {
if (completed) { if (Evaluated) {
if (successful) { if (Successful) {
return result; if (result != null) {
return result;
} else {
return new UnavailableValue(debugger, "No return value");
}
} else { } else {
ObjectValue exception = (ObjectValue)result; ObjectValue exception = (ObjectValue)result;
while (exception.Type != "System.Exception") { while (exception.Type != "System.Exception") {
@ -89,7 +93,11 @@ namespace Debugger
return new UnavailableValue(debugger, result.Type + ": " + exception["_message"].Value.AsString); return new UnavailableValue(debugger, result.Type + ": " + exception["_message"].Value.AsString);
} }
} else { } else {
return null; if (Evaluating) {
return new UnavailableValue(debugger, "Evaluating...");
} else {
return new UnavailableValue(debugger, "Evaluation pending");
}
} }
} }
} }
@ -134,7 +142,7 @@ namespace Debugger
protected internal virtual void OnEvalComplete(EvalEventArgs e) protected internal virtual void OnEvalComplete(EvalEventArgs e)
{ {
evaluating = false; evaluating = false;
completed = true; evaluated = true;
ICorDebugValue corValue; ICorDebugValue corValue;
corEval.GetResult(out corValue); corEval.GetResult(out corValue);

66
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/PropertyVariable.cs

@ -11,69 +11,37 @@ using Debugger.Interop.CorDebug;
namespace Debugger namespace Debugger
{ {
/// <summary>
/// Delegate that is used to get eval. This delegate may be called at any time and should never return null.
/// </summary>
public delegate Eval EvalCreator();
public class PropertyVariable: Variable public class PropertyVariable: Variable
{ {
Eval eval; EvalCreator evalCreator;
Eval cachedEval;
public event EventHandler<DebuggerEventArgs> ValueEvaluated;
internal PropertyVariable(Eval eval, string name):base(new UnavailableValue(eval.Debugger), name) internal PropertyVariable(NDebugger debugger, string name, EvalCreator evalCreator):base(debugger, name, null)
{ {
this.Eval = eval; this.evalCreator = evalCreator;
this.valueGetter = delegate{return Eval.Result;};
} }
public bool IsEvaluated { public bool IsEvaluated {
get { get {
return eval.Completed; return Eval.Evaluated;
}
}
protected override Value GetValue()
{
if (IsEvaluated) {
if (eval.Result != null) {
return eval.Result;
} else {
return new UnavailableValue(debugger, "No return value");
}
} else {
if (eval.Evaluating) {
return new UnavailableValue(debugger, "Evaluating...");
} else {
return new UnavailableValue(debugger, "Evaluation pending");
}
} }
} }
public Eval Eval { public Eval Eval {
get { get {
return eval; if (cachedEval == null || cachedEval.Result.IsExpired) {
} cachedEval = evalCreator();
set { if (cachedEval == null) throw new DebuggerException("EvalGetter returned null");
if (debugger.PausedReason != PausedReason.AllEvalsComplete) { cachedEval.EvalStarted += delegate { OnValueChanged(); };
eval = value; cachedEval.EvalComplete += delegate { OnValueChanged(); };
eval.EvalStarted += EvalStarted;
eval.EvalComplete += EvalComplete;
OnValueChanged();
} }
} return cachedEval;
}
void EvalStarted(object sender, EvalEventArgs args)
{
OnValueChanged();
}
void EvalComplete(object sender, EvalEventArgs args)
{
OnValueEvaluated();
OnValueChanged();
}
protected void OnValueEvaluated()
{
if (ValueEvaluated != null) {
ValueEvaluated(this, new DebuggerEventArgs(debugger));
} }
} }
} }

62
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/Variable.cs

@ -11,6 +11,9 @@ using Debugger.Interop.CorDebug;
namespace Debugger namespace Debugger
{ {
/// <summary>
/// Delegate that is used to get value. This delegate may be called at any time and should never return null.
/// </summary>
public delegate Value ValueGetter(); public delegate Value ValueGetter();
public class Variable: RemotingObjectBase public class Variable: RemotingObjectBase
@ -18,10 +21,10 @@ namespace Debugger
protected NDebugger debugger; protected NDebugger debugger;
string name; string name;
Value val;
VariableCollection subVariables; VariableCollection subVariables;
event ValueGetter updating; protected ValueGetter valueGetter;
Value cachedValue;
public event EventHandler<VariableEventArgs> ValueChanged; public event EventHandler<VariableEventArgs> ValueChanged;
public event EventHandler<VariableCollectionEventArgs> ValueRemovedFromCollection; public event EventHandler<VariableCollectionEventArgs> ValueRemovedFromCollection;
@ -39,33 +42,20 @@ namespace Debugger
} }
/// <summary> /// <summary>
/// Gets value of variable, which is safe to use. /// Gets value of variable which is safe to use (it is not null and it is not expired)
/// </summary> /// </summary>
public Value Value { public Value Value {
get { get {
Value v = GetValue(); if (cachedValue == null || cachedValue.IsExpired) {
if (v == null) { cachedValue = valueGetter();
return new UnavailableValue(debugger); if (cachedValue == null) throw new DebuggerException("ValueGetter returned null");
cachedValue.ValueChanged += delegate { OnValueChanged(); };
} }
if (v.IsExpired) { if (cachedValue.IsExpired) {
return new UnavailableValue(debugger, "The value has expired"); return new UnavailableValue(debugger, "The value has expired");
} else {
return v;
} }
return cachedValue;
} }
internal set {
val = value;
val.ValueChanged += delegate { OnValueChanged(); };
OnValueChanged();
}
}
protected virtual Value GetValue()
{
if ((val == null || val.IsExpired) && updating != null) {
val = updating();
}
return val;
} }
/// <summary> /// <summary>
@ -81,7 +71,7 @@ namespace Debugger
public bool MayHaveSubVariables { public bool MayHaveSubVariables {
get { get {
return val.MayHaveSubVariables; return Value.MayHaveSubVariables;
} }
} }
@ -92,42 +82,34 @@ namespace Debugger
} }
} }
void OnSubVariablesUpdating(object sender, VariableCollectionEventArgs e)
{
subVariables.UpdateTo(Value.GetSubVariables(delegate{return this.Value;}));
}
protected internal virtual void OnValueRemovedFromCollection(VariableCollectionEventArgs e) { protected internal virtual void OnValueRemovedFromCollection(VariableCollectionEventArgs e) {
if (ValueRemovedFromCollection != null) { if (ValueRemovedFromCollection != null) {
ValueRemovedFromCollection(this, e); ValueRemovedFromCollection(this, e);
} }
} }
public Variable(NDebugger debugger, ICorDebugValue corValue, string name):this(debugger, Value.CreateValue(debugger, corValue), name, null) public Variable(NDebugger debugger, ICorDebugValue corValue, string name):this(Value.CreateValue(debugger, corValue), name)
{ {
} }
public Variable(NDebugger debugger, string name, ValueGetter updating):this(debugger, null, name, updating) public Variable(Value val, string name):this(val.Debugger, name, delegate {return val;})
{ {
} }
public Variable(Value val, string name):this(val.Debugger, val, name, null) public Variable(NDebugger debugger, string name, ValueGetter valueGetter)
{
}
Variable(NDebugger debugger, Value val, string name, ValueGetter updating)
{ {
this.debugger = debugger; this.debugger = debugger;
if (val != null) {
this.Value = val;
}
this.name = name; this.name = name;
this.updating = updating; this.valueGetter = valueGetter;
this.subVariables = new VariableCollection(debugger); this.subVariables = new VariableCollection(debugger);
this.subVariables.Updating += OnSubVariablesUpdating; this.subVariables.Updating += OnSubVariablesUpdating;
} }
void OnSubVariablesUpdating(object sender, VariableCollectionEventArgs e)
{
subVariables.UpdateTo(Value.GetSubVariables(delegate{return this.Value;}));
}
} }
} }

12
src/AddIns/Misc/Debugger/Debugger.Core/Project/Src/Variables/VariableCollection.cs

@ -157,18 +157,8 @@ namespace Debugger
foreach(Variable newVariable in newVariables) { foreach(Variable newVariable in newVariables) {
if (this.Contains(newVariable.Name)) { if (this.Contains(newVariable.Name)) {
Variable oldVariable = this[newVariable.Name];
// Update existing variable
/*if (oldVariable.Value is ObjectValue && newVariable.Value is ObjectValue && debugger.PausedReason == PausedReason.AllEvalsComplete) {
((ObjectValue)newVariable.Value).toString = ((ObjectValue)oldVariable.Value).toString;
}
if (oldVariable is PropertyVariable) {
((PropertyVariable)oldVariable).Eval = ((PropertyVariable)newVariable).Eval;
} else {
oldVariable.Value = newVariable.Value;
}*/
// Keep the variable in the list // Keep the variable in the list
toBeRemoved.Remove(oldVariable); toBeRemoved.Remove(this[newVariable.Name]);
} else { } else {
// Add new variable // Add new variable
this.Add(newVariable); this.Add(newVariable);

Loading…
Cancel
Save