Debugger: Ide, Watches reduce notifications in Begin/EndUpdate

This commit is contained in:
Martin 2022-01-23 22:36:49 +01:00
parent 867d12b46d
commit fa2ec38d6a
2 changed files with 83 additions and 30 deletions

View File

@ -149,6 +149,7 @@ type
FWatchesInView: TIdeWatches; FWatchesInView: TIdeWatches;
FPowerImgIdx, FPowerImgIdxGrey: Integer; FPowerImgIdx, FPowerImgIdxGrey: Integer;
FUpdateAllNeeded, FUpdatingAll: Boolean; FUpdateAllNeeded, FUpdatingAll: Boolean;
FWatchInUpDateItem: TIdeWatch;
FStateFlags: TWatchesDlgStateFlags; FStateFlags: TWatchesDlgStateFlags;
function GetSelected: TIdeWatch; // The focused Selected Node function GetSelected: TIdeWatch; // The focused Selected Node
function GetThreadId: Integer; function GetThreadId: Integer;
@ -165,6 +166,7 @@ type
function GetSelectedSnapshot: TSnapshot; function GetSelectedSnapshot: TSnapshot;
property Watches: TIdeWatches read GetWatches; property Watches: TIdeWatches read GetWatches;
protected protected
procedure DoBeginUpdate; override;
procedure DoEndUpdate; override; procedure DoEndUpdate; override;
procedure DoWatchesChanged; override; procedure DoWatchesChanged; override;
function ColSizeGetter(AColId: Integer; var ASize: Integer): Boolean; function ColSizeGetter(AColId: Integer; var ASize: Integer): Boolean;
@ -345,6 +347,7 @@ var
VNode: PVirtualNode; VNode: PVirtualNode;
begin begin
if FUpdatingAll then exit; if FUpdatingAll then exit;
if IsUpdating then exit;
if GetSelectedSnapshot <> nil then begin if GetSelectedSnapshot <> nil then begin
actToggleCurrentEnable.Enabled := False; actToggleCurrentEnable.Enabled := False;
actToggleCurrentEnable.Checked := False; actToggleCurrentEnable.Checked := False;
@ -534,13 +537,14 @@ var
begin begin
try try
DisableAllActions; DisableAllActions;
BeginUpdate;
for VNode in tvWatches.SelectedNodes do for VNode in tvWatches.SelectedNodes do
begin begin
VNdWatch := TIdeWatch(tvWatches.NodeItem[VNode]); VNdWatch := TIdeWatch(tvWatches.NodeItem[VNode]);
VNdWatch.Enabled := True; VNdWatch.Enabled := True;
end; end;
finally finally
tvWatchesChange(nil, nil); EndUpdate;
end; end;
end; end;
@ -569,13 +573,14 @@ var
begin begin
try try
DisableAllActions; DisableAllActions;
BeginUpdate;
for VNode in tvWatches.SelectedNodes do for VNode in tvWatches.SelectedNodes do
begin begin
VNdWatch := TIdeWatch(tvWatches.NodeItem[VNode]); VNdWatch := TIdeWatch(tvWatches.NodeItem[VNode]);
VNdWatch.Enabled := False; VNdWatch.Enabled := False;
end; end;
finally finally
tvWatchesChange(nil, nil); EndUpdate;
end; end;
end; end;
@ -634,7 +639,8 @@ begin
Include(FStateFlags, wdsfNeedDeleteAll); Include(FStateFlags, wdsfNeedDeleteAll);
if wdsfUpdating in FStateFlags then exit; if wdsfUpdating in FStateFlags then exit;
Exclude(FStateFlags, wdsfNeedDeleteAll); Exclude(FStateFlags, wdsfNeedDeleteAll);
tvWatches.BeginUpdate; DisableAllActions;
BeginUpdate;
try try
DisableAllActions; DisableAllActions;
VNode := tvWatches.GetFirst; VNode := tvWatches.GetFirst;
@ -643,8 +649,7 @@ begin
VNode := tvWatches.GetFirst; VNode := tvWatches.GetFirst;
end; end;
finally finally
tvWatches.EndUpdate; EndUpdate;
tvWatchesChange(nil, nil);
end; end;
end; end;
@ -653,7 +658,7 @@ var
NewWatches: TIdeWatches; NewWatches: TIdeWatches;
begin begin
DebugLn(DBG_DATA_MONITORS, ['DebugDataWindow: TWatchesDlg.SnapshotChanged ', DbgSName(Sender), ' Upd:', IsUpdating]); DebugLn(DBG_DATA_MONITORS, ['DebugDataWindow: TWatchesDlg.SnapshotChanged ', DbgSName(Sender), ' Upd:', IsUpdating]);
tvWatches.BeginUpdate; BeginUpdate;
// prevent lvWatchesSelectItem when deleting the itews. Snapsot may have been deleted // prevent lvWatchesSelectItem when deleting the itews. Snapsot may have been deleted
FUpdatingAll := True; // will be reset by UpdateAll FUpdatingAll := True; // will be reset by UpdateAll
try try
@ -664,7 +669,7 @@ begin
UpdateAll; UpdateAll;
finally finally
FUpdatingAll := False; // wan reset by UpdateAll anyway FUpdatingAll := False; // wan reset by UpdateAll anyway
tvWatches.EndUpdate; EndUpdate;
end; end;
end; end;
@ -682,6 +687,12 @@ begin
else Result := WatchesMonitor.CurrentWatches; else Result := WatchesMonitor.CurrentWatches;
end; end;
procedure TWatchesDlg.DoBeginUpdate;
begin
inherited DoBeginUpdate;
tvWatches.BeginUpdate;
end;
procedure TWatchesDlg.DoEndUpdate; procedure TWatchesDlg.DoEndUpdate;
begin begin
inherited DoEndUpdate; inherited DoEndUpdate;
@ -689,6 +700,10 @@ begin
FUpdateAllNeeded := False; FUpdateAllNeeded := False;
UpdateAll; UpdateAll;
end; end;
tvWatches.EndUpdate;
if not FUpdatingAll then
tvWatchesChange(nil, nil);
end; end;
procedure TWatchesDlg.DoWatchesChanged; procedure TWatchesDlg.DoWatchesChanged;
@ -727,15 +742,16 @@ begin
Include(FStateFlags, wdsfNeedDeleteCurrent); Include(FStateFlags, wdsfNeedDeleteCurrent);
if (wdsfUpdating in FStateFlags) then exit; if (wdsfUpdating in FStateFlags) then exit;
Exclude(FStateFlags, wdsfNeedDeleteCurrent); Exclude(FStateFlags, wdsfNeedDeleteCurrent);
DisableAllActions;
BeginUpdate;
try try
DisableAllActions;
VNode := tvWatches.GetFirstSelected; VNode := tvWatches.GetFirstSelected;
while VNode <> nil do begin while VNode <> nil do begin
tvWatches.DeleteNodeEx(VNode, True); tvWatches.DeleteNodeEx(VNode, True);
VNode := tvWatches.GetFirstSelected; VNode := tvWatches.GetFirstSelected;
end; end;
finally finally
tvWatchesChange(nil, nil); EndUpdate;
end; end;
end; end;
@ -746,13 +762,14 @@ var
begin begin
try try
DisableAllActions; DisableAllActions;
BeginUpdate;
for VNode in tvWatches.NoInitNodes do for VNode in tvWatches.NoInitNodes do
begin begin
VNdWatch := TIdeWatch(tvWatches.NodeItem[VNode]); VNdWatch := TIdeWatch(tvWatches.NodeItem[VNode]);
VNdWatch.Enabled := False; VNdWatch.Enabled := False;
end; end;
finally finally
tvWatchesChange(nil, nil); EndUpdate;
end; end;
end; end;
@ -763,13 +780,14 @@ var
begin begin
try try
DisableAllActions; DisableAllActions;
BeginUpdate;
for VNode in tvWatches.NoInitNodes do for VNode in tvWatches.NoInitNodes do
begin begin
VNdWatch := TIdeWatch(tvWatches.NodeItem[VNode]); VNdWatch := TIdeWatch(tvWatches.NodeItem[VNode]);
VNdWatch.Enabled := True; VNdWatch.Enabled := True;
end; end;
finally finally
tvWatchesChange(nil, nil); EndUpdate;
end; end;
end; end;
@ -779,12 +797,13 @@ var
begin begin
try try
DisableAllActions; DisableAllActions;
BeginUpdate;
Watch := GetSelected; Watch := GetSelected;
if Watch = nil then Exit; if Watch = nil then Exit;
popEnabled.Checked := not popEnabled.Checked; popEnabled.Checked := not popEnabled.Checked;
Watch.Enabled := popEnabled.Checked; Watch.Enabled := popEnabled.Checked;
finally finally
tvWatchesChange(nil, nil); EndUpdate;
end; end;
end; end;
@ -906,8 +925,16 @@ begin
if (ThreadsMonitor = nil) or (CallStackMonitor = nil) then exit; if (ThreadsMonitor = nil) or (CallStackMonitor = nil) then exit;
if GetStackframe < 0 then exit; // TODO need dedicated validity property if GetStackframe < 0 then exit; // TODO need dedicated validity property
if wdsfUpdating in FStateFlags then begin
if FWatchInUpDateItem <> AWatch then // The watch got data while we requested it, that is fine
FUpdateAllNeeded := True;
exit;
end;
BeginUpdate;
include(FStateFlags, wdsfUpdating); include(FStateFlags, wdsfUpdating);
DebugBoss.LockCommandProcessing; DebugBoss.LockCommandProcessing;
FWatchInUpDateItem := AWatch;
try try
tvWatches.NodeText[VNode, COL_WATCH_EXPR-1]:= AWatch.Expression; tvWatches.NodeText[VNode, COL_WATCH_EXPR-1]:= AWatch.Expression;
WatchValue := AWatch.Values[GetThreadId, GetStackframe]; WatchValue := AWatch.Values[GetThreadId, GetStackframe];
@ -923,13 +950,15 @@ begin
end end
else else
tvWatches.NodeText[VNode, COL_WATCH_VALUE-1]:= '<not evaluated>'; tvWatches.NodeText[VNode, COL_WATCH_VALUE-1]:= '<not evaluated>';
finally
FWatchInUpDateItem := nil;
exclude(FStateFlags, wdsfUpdating); exclude(FStateFlags, wdsfUpdating);
if wdsfNeedDeleteCurrent in FStateFlags then if wdsfNeedDeleteCurrent in FStateFlags then
popDeleteClick(nil); popDeleteClick(nil);
if wdsfNeedDeleteAll in FStateFlags then if wdsfNeedDeleteAll in FStateFlags then
popDeleteAllClick(nil); popDeleteAllClick(nil);
finally EndUpdate;
DebugBoss.UnLockCommandProcessing; DebugBoss.UnLockCommandProcessing;
tvWatches.Invalidate; tvWatches.Invalidate;
end; end;
@ -995,15 +1024,19 @@ procedure TWatchesDlg.WatchAdd(const ASender: TIdeWatches; const AWatch: TIdeWat
var var
VNode: PVirtualNode; VNode: PVirtualNode;
begin begin
VNode := tvWatches.FindNodeForItem(AWatch); BeginUpdate;
if VNode = nil try
then begin VNode := tvWatches.FindNodeForItem(AWatch);
VNode := tvWatches.AddChild(nil, AWatch); if VNode = nil
tvWatches.SelectNode(VNode); then begin
VNode := tvWatches.AddChild(nil, AWatch);
tvWatches.SelectNode(VNode);
end;
UpdateItem(VNode, AWatch);
finally
EndUpdate;
end; end;
UpdateItem(VNode, AWatch);
tvWatchesChange(nil, nil);
end; end;
procedure TWatchesDlg.WatchUpdate(const ASender: TIdeWatches; const AWatch: TIdeWatch); procedure TWatchesDlg.WatchUpdate(const ASender: TIdeWatches; const AWatch: TIdeWatch);
@ -1014,15 +1047,18 @@ begin
if AWatch.Collection <> FWatchesInView then exit; if AWatch.Collection <> FWatchesInView then exit;
try DebugLnEnter(DBG_DATA_MONITORS, ['DebugDataWindow: TWatchesDlg.WatchUpdate Upd:', IsUpdating, ' Watch=',AWatch.Expression]); try DebugLnEnter(DBG_DATA_MONITORS, ['DebugDataWindow: TWatchesDlg.WatchUpdate Upd:', IsUpdating, ' Watch=',AWatch.Expression]);
VNode := tvWatches.FindNodeForItem(AWatch); BeginUpdate;
if VNode = nil try
then WatchAdd(ASender, AWatch) VNode := tvWatches.FindNodeForItem(AWatch);
else UpdateItem(VNode, AWatch); if VNode = nil
then WatchAdd(ASender, AWatch)
else UpdateItem(VNode, AWatch);
finally
EndUpdate;
end;
// TODO: if AWatch <> Selected, then prevent UpdateInspectPane // TODO: if AWatch <> Selected, then prevent UpdateInspectPane
// Selected may update later, and calling UpdateInspectPane will schedule an unsucesful attemptn to fetch data // Selected may update later, and calling UpdateInspectPane will schedule an unsucesful attemptn to fetch data
if not FUpdatingAll
then tvWatchesChange(nil, nil);
finally DebugLnExit(DBG_DATA_MONITORS, ['DebugDataWindow: TWatchesDlg.WatchUpdate']); end; finally DebugLnExit(DBG_DATA_MONITORS, ['DebugDataWindow: TWatchesDlg.WatchUpdate']); end;
end; end;

View File

@ -701,6 +701,7 @@ type
TCurrentWatch = class(TIdeWatch) TCurrentWatch = class(TIdeWatch)
private private
FSnapShot: TIdeWatch; FSnapShot: TIdeWatch;
FAdded: Boolean;
procedure SetSnapShot(const AValue: TIdeWatch); procedure SetSnapShot(const AValue: TIdeWatch);
protected protected
function CreateValueList: TWatchValueList; override; function CreateValueList: TWatchValueList; override;
@ -724,6 +725,7 @@ type
FMonitor: TIdeWatchesMonitor; FMonitor: TIdeWatchesMonitor;
FSnapShot: TIdeWatches; FSnapShot: TIdeWatches;
FDestroying: Boolean; FDestroying: Boolean;
FSkipUpdatedNotification: integer;
procedure SetSnapShot(const AValue: TIdeWatches); procedure SetSnapShot(const AValue: TIdeWatches);
procedure WatchesChanged(Sender: TObject); procedure WatchesChanged(Sender: TObject);
protected protected
@ -5535,13 +5537,18 @@ begin
end; end;
destructor TCurrentWatch.Destroy; destructor TCurrentWatch.Destroy;
var
w: TCurrentWatches;
begin begin
if (TCurrentWatches(Collection) <> nil) if (TCurrentWatches(Collection) <> nil)
then begin then begin
TCurrentWatches(Collection).NotifyRemove(Self); TCurrentWatches(Collection).NotifyRemove(Self);
TCurrentWatches(Collection).DoModified; TCurrentWatches(Collection).DoModified;
end; end;
w := TCurrentWatches(Collection);
inc(w.FSkipUpdatedNotification);
inherited Destroy; inherited Destroy;
dec(w.FSkipUpdatedNotification);
end; end;
procedure TCurrentWatch.LoadFromXMLConfig(const AConfig: TXMLConfig; const APath: string); procedure TCurrentWatch.LoadFromXMLConfig(const AConfig: TXMLConfig; const APath: string);
@ -5582,10 +5589,8 @@ end;
function TIdeWatches.Add(const AExpression: String): TIdeWatch; function TIdeWatches.Add(const AExpression: String): TIdeWatch;
begin begin
BeginUpdate; Result := TIdeWatch(inherited Add); // calls update
Result := TIdeWatch(inherited Add);
Result.Expression := AExpression; Result.Expression := AExpression;
EndUpdate;
end; end;
function TIdeWatches.GetItem(const AnIndex: Integer): TIdeWatch; function TIdeWatches.GetItem(const AnIndex: Integer): TIdeWatch;
@ -5638,7 +5643,9 @@ var
R: TIdeWatch; R: TIdeWatch;
begin begin
// if this is modified, then also update LoadFromXMLConfig // if this is modified, then also update LoadFromXMLConfig
inc(FSkipUpdatedNotification);
Result := TCurrentWatch(inherited Add(AExpression)); Result := TCurrentWatch(inherited Add(AExpression));
dec(FSkipUpdatedNotification);
if FSnapShot <> nil then begin if FSnapShot <> nil then begin
R := FSnapShot.Add(AExpression); R := FSnapShot.Add(AExpression);
Result.SnapShot := R; Result.SnapShot := R;
@ -5729,6 +5736,11 @@ end;
procedure TCurrentWatches.NotifyAdd(const AWatch: TCurrentWatch); procedure TCurrentWatches.NotifyAdd(const AWatch: TCurrentWatch);
begin begin
if UpdateCount > 0 then begin
AWatch.FAdded := True;
exit;
end;
AWatch.FAdded := False;
FMonitor.NotifyAdd(Self, AWatch); FMonitor.NotifyAdd(Self, AWatch);
end; end;
@ -5775,12 +5787,17 @@ procedure TCurrentWatches.Update(Item: TCollectionItem);
var var
m, c: Integer; m, c: Integer;
begin begin
if (UpdateCount > 0) or (FSkipUpdatedNotification > 0) then
exit;
if Item <> nil then begin if Item <> nil then begin
FMonitor.NotifyUpdate(Self, TCurrentWatch(Item)); FMonitor.NotifyUpdate(Self, TCurrentWatch(Item));
end else begin end else begin
m := 0; m := 0;
c := Count; c := Count;
while m < c do begin while m < c do begin
if Items[m].FAdded then
NotifyAdd(Items[m]);
FMonitor.NotifyUpdate(Self, Items[m]); FMonitor.NotifyUpdate(Self, Items[m]);
if c <> Count then begin if c <> Count then begin
m := Max(0, m - Max(0, Count - c)); m := Max(0, m - Max(0, Count - c));