todolist, symlist, fix possible corruption of the input data

when a new thread was started before the previous one ended

  close #35
This commit is contained in:
Basile Burg 2020-05-05 14:15:06 +02:00
parent 83ca2ded4c
commit 92945de403
3 changed files with 53 additions and 36 deletions

View File

@ -1,5 +1,11 @@
# v3.9.2-dev
## Regressions
- Symbol list: performance regression, async behavior is now emulated with threads. (#35)
- Todolist: performance regression, async behavior is now emulated with threads. (#35)
- Todolist: small non growing leak introduced in v3.9.0
## Bugs fixed
- Editor, Diff: the button used to "reload from disk and reset the history" didn't work.

View File

@ -138,13 +138,14 @@ type
fAutoExpandErrors: boolean;
fSortSymbols: boolean;
fSmartExpander: boolean;
fTreeDataToThread: string;
fSourcecodeForThread: string;
fTreeDataFromThread: string;
fLockThreadedParsing: boolean;
ndAlias, ndClass, ndEnum, ndFunc, ndUni: TTreeNode;
ndImp, ndIntf, ndMix, ndStruct, ndTmp: TTreeNode;
ndVar, ndWarn, ndErr, ndUt: TTreeNode;
procedure getTreeDataInThread;
procedure gotTreeDataFromThread(sender: TObject);
procedure threadedParsing;
procedure threadedParsingFinished(sender: TObject);
procedure TreeDblClick(Sender: TObject);
procedure actRefreshExecute(Sender: TObject);
procedure actAutoRefreshExecute(Sender: TObject);
@ -733,6 +734,8 @@ end;
procedure TSymbolListWidget.getSymbols;
begin
if fLockThreadedParsing then
exit;
if fDoc.isNil then
exit;
if (fDoc.Lines.Count = 0) or not fDoc.isDSource then
@ -741,16 +744,17 @@ begin
updateVisibleCat;
exit;
end;
fTreeDataToThread := fDoc.Lines.Text;
TTHread.ExecuteInThread(@getTreeDataInThread, @gotTreeDataFromThread);
fSourcecodeForThread := fDoc.Lines.Text;
fLockThreadedParsing := true;
TTHread.ExecuteInThread(@threadedParsing, @threadedParsingFinished);
end;
procedure TSymbolListWidget.getTreeDataInThread;
procedure TSymbolListWidget.threadedParsing;
begin
fTreeDataFromThread := listSymbols(PChar(fTreeDataToThread), fDeep);
fTreeDataFromThread := listSymbols(PChar(fSourcecodeForThread), fDeep);
end;
procedure TSymbolListWidget.gotTreeDataFromThread(sender: TObject);
procedure TSymbolListWidget.threadedParsingFinished(sender: TObject);
function getCatNode(node: TTreeNode; stype: TSymbolType ): TTreeNode;
function newCat(const aCat: string): TTreeNode;
@ -832,11 +836,11 @@ procedure TSymbolListWidget.gotTreeDataFromThread(sender: TObject);
end;
var
s: string;
i: Integer;
f: string;
n: TTreeNode;
begin
fLockThreadedParsing := false;
if fDoc.isNil then
exit;

View File

@ -7,6 +7,7 @@ interface
uses
Classes, SysUtils, FileUtil, ListFilterEdit, Forms, Controls,
strutils, Graphics, Dialogs, ExtCtrls, Menus, Buttons, ComCtrls,
syncobjs,
u_widget, process, u_common, u_interfaces, u_synmemo, u_processes,
u_writableComponent, u_observer, u_sharedres, u_dexed_d,
u_dsgncontrols;
@ -88,6 +89,9 @@ type
procedure mnuAutoRefreshClick(Sender: TObject);
procedure toolbarResize(Sender: TObject);
private
fFileListForThread: string;
fSerializedTodoItemFromThread: string;
fLockItemsScanning: boolean;
fAutoRefresh: Boolean;
fSingleClick: Boolean;
fColumns: TTodoColumns;
@ -95,8 +99,6 @@ type
fDoc: TDexedMemo;
fTodos: TTodoItems;
fOptions: TTodoOptions;
fTodoItemsDataFromThread: string;
fTodoItemsresultFromThread: string;
// IDocumentObserver
procedure docNew(document: TDexedMemo);
procedure docFocused(document: TDexedMemo);
@ -118,8 +120,8 @@ type
// TODOlist things
function getContext: TTodoContext;
procedure scanTodoItems(autoRefreshed: boolean);
procedure scanTodoInThread;
procedure scannedTodoInThread(Sender : TObject);
procedure threadedScanning;
procedure threadedScanningFinished(Sender : TObject);
procedure clearTodoList;
procedure fillTodoList;
procedure lstItemsColumnClick(Sender: TObject; Column: TListColumn);
@ -418,16 +420,19 @@ end;
procedure TTodoListWidget.scanTodoItems(autoRefreshed: boolean);
var
ctxt: TTodoContext;
i,j: integer;
nme: string;
str: string = '';
txt: TMemoryStream;
c: TTodoContext;
i: integer;
j: integer;
n: string;
begin
if fLockItemsScanning then
exit;
fFileListForThread := '';
clearTodoList;
ctxt := getContext;
case ctxt of
c := getContext;
case c of
tcNone: exit;
tcProject: if (fProj = nil) or (fProj.sourcesCount = 0) then
exit;
@ -435,50 +440,51 @@ begin
exit;
end;
if ctxt = tcProject then
if c = tcProject then
begin
i := 0;
j := fProj.sourcesCount-1;
if autoRefreshed and (j > fOptions.disableIfMoreFilesThan) then
exit;
for i := 0 to j do
begin
nme := fProj.sourceAbsolute(i);
if not hasDlangSyntax(nme.extractFileExt) then
n := fProj.sourceAbsolute(i);
if not hasDlangSyntax(n.extractFileExt) then
continue;
str += nme;
if not n.fileExists then
continue;
fFileListForThread += n;
if i <> j then
str += PathSeparator;
fFileListForThread += PathSeparator;
end;
end
else if fDoc.fileName <> newdocPageCaption then
begin
str := fDoc.fileName;
fFileListForThread := fDoc.fileName;
end;
if str.isNotEmpty then
if fFileListForThread.isNotEmpty then
begin
fTodoItemsDataFromThread := str;
TThread.ExecuteInThread(@scanTodoInThread, @scannedTodoInThread);
fLockItemsScanning := true;
TThread.ExecuteInThread(@threadedScanning, @threadedScanningFinished);
end;
end;
procedure TTodoListWidget.scanTodoInThread;
procedure TTodoListWidget.threadedScanning;
begin
fTodoItemsResultFromThread := todoItems(PChar(fTodoItemsDataFromThread));
fSerializedTodoItemFromThread := todoItems(PChar(fFileListForThread));
end;
procedure TTodoListWidget.scannedTodoInThread(Sender : TObject);
procedure TTodoListWidget.threadedScanningFinished(Sender : TObject);
var
txt: TmemoryStream;
begin
if fTodoItemsResultFromThread.length < 10 then
if fSerializedTodoItemFromThread.length < 10 then
exit;
txt := TMemoryStream.create;
try
txt.Write(fTodoItemsResultFromThread[1], fTodoItemsResultFromThread.length);
txt.Position:=0;
txt.Write(fSerializedTodoItemFromThread[1], fSerializedTodoItemFromThread.length);
txt.Position := 0;
fTodos.loadFromTxtStream(txt);
fillTodoList;
finally
@ -542,6 +548,7 @@ begin
lstItems.Column[4].Visible := True;
end;
lstItems.EndUpdate;
fLockItemsScanning := false;
end;
procedure TTodoListWidget.handleListClick(Sender: TObject);