IDE: compiler options: other options: fixed dangling OnIdle, fixed thread accessing non thread safe methods

git-svn-id: trunk@45538 -
This commit is contained in:
mattias 2014-06-15 14:43:35 +00:00
parent df78add6dd
commit c0b4888159
5 changed files with 99 additions and 34 deletions

View File

@ -6,7 +6,7 @@ object frmAllCompilerOptions: TfrmAllCompilerOptions
Caption = 'frmAllCompilerOptions'
ClientHeight = 497
ClientWidth = 622
OnShow = FormShow
OnCreate = FormCreate
LCLVersion = '1.3'
object sbAllOptions: TScrollBox
Left = 0

View File

@ -23,7 +23,7 @@ type
procedure btnResetOptionsFilterClick(Sender: TObject);
procedure cbShowModifiedClick(Sender: TObject);
procedure edOptionsFilterChange(Sender: TObject);
procedure FormShow(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
FIdleConnected: Boolean;
FOptionsReader: TCompilerOptReader;
@ -66,6 +66,7 @@ end;
destructor TfrmAllCompilerOptions.Destroy;
begin
IdleConnected:=false;
FGeneratedControls.Clear;
FreeAndNil(FGeneratedControls);
inherited Destroy;
@ -76,7 +77,7 @@ begin
Result := FOptionsReader.ToCustomOptions(aStrings, cbUseComments.Checked);
end;
procedure TfrmAllCompilerOptions.FormShow(Sender: TObject);
procedure TfrmAllCompilerOptions.FormCreate(Sender: TObject);
begin
Caption:=lisAllOptions;
edOptionsFilter.Hint := lisFilterTheAvailableOptionsList;
@ -110,6 +111,8 @@ end;
procedure TfrmAllCompilerOptions.SetIdleConnected(AValue: Boolean);
begin
if csDestroying in ComponentState then
AValue:=false;
if FIdleConnected = AValue then exit;
FIdleConnected := AValue;
if FIdleConnected then
@ -132,9 +135,10 @@ var
StartTime: TDateTime;
begin
IdleConnected := False;
if FOptionsThread=nil then exit;
Screen.Cursor := crHourGlass;
try
FOptionsThread.WaitFor; // Make sure the options are read.
FOptionsThread.EndParsing; // Make sure the options are read.
if FOptionsReader.ErrorMsg <> '' then
DebugLn(FOptionsReader.ErrorMsg)
else begin

View File

@ -209,6 +209,8 @@ type
procedure Clear;
function UpdateTargetParam: Boolean;
function ReadAndParseOptions: TModalResult;
function ParseOptions(OutputI, OutputH: TStringList): TModalResult;
procedure ReadCompiler(CompPath, Params: string; out OutputI, OutputH: TStringList);
function FilterOptions(aFilter: string; aOnlySelected: Boolean): Boolean;
function FindOptionById(aId: integer): TCompilerOpt;
function FromCustomOptions(aStrings: TStrings): TModalResult;
@ -228,12 +230,20 @@ type
private
fReader: TCompilerOptReader;
fReadTime: TDateTime;
fCompPath: string;
fCompParams: string;
fOutputI: TStringList;
fOutputH: TStringList;
fStartedOnce: boolean;
function GetErrorMsg: string;
procedure Clear; // (main thread)
protected
procedure Execute; override;
public
constructor Create(aReader: TCompilerOptReader);
destructor Destroy; override;
procedure StartParsing; // (main thread)
procedure EndParsing; // (main thread)
public
property ReadTime: TDateTime read fReadTime;
property ErrorMsg: string read GetErrorMsg;
@ -1166,29 +1176,43 @@ function TCompilerOptReader.ReadAndParseOptions: TModalResult;
// fpc -Fr$(FPCMsgFile) -h
// fpc -Fr$(FPCMsgFile) -i
var
Lines: TStringList;
OutputI: TStringList;
OutputH: TStringList;
begin
if fCompilerExecutable = '' then
fCompilerExecutable := 'fpc'; // Let's hope "fpc" is found in PATH.
try
ReadCompiler(fCompilerExecutable, fParsedTarget, OutputI, OutputH);
Result:=ParseOptions(OutputI, OutputH);
finally
OutputI.Free;
OutputH.Free;
end;
end;
function TCompilerOptReader.ParseOptions(OutputI, OutputH: TStringList
): TModalResult;
begin
OptionIdCounter := 0;
fErrorMsg := '';
if fCompilerExecutable = '' then
fCompilerExecutable := 'fpc'; // Let's hope "fpc" is found in PATH.
// FPC with option -i
Lines:=RunTool(fCompilerExecutable, fParsedTarget + ' -i');
try
if Lines = Nil then Exit(mrCancel);
Result := ParseI(Lines);
if OutputI = Nil then Exit(mrCancel);
Result := ParseI(OutputI);
if Result <> mrOK then Exit;
finally
Lines.Free;
if OutputH = Nil then Exit(mrCancel);
Result := ParseH(OutputH);
end;
procedure TCompilerOptReader.ReadCompiler(CompPath, Params: string; out
OutputI, OutputH: TStringList);
begin
OutputH:=nil;
OutputI:=nil;
if CompPath = '' then
CompPath := 'fpc'; // Let's hope "fpc" is found in PATH.
// FPC with option -i
OutputI:=RunTool(CompPath, Params + ' -i');
// FPC with option -h
Lines:=RunTool(fCompilerExecutable, fParsedTarget + ' -h');
try
if Lines = Nil then Exit(mrCancel);
Result := ParseH(Lines);
finally
Lines.Free;
end;
OutputH:=RunTool(CompPath, Params + ' -h');
end;
function TCompilerOptReader.FilterOptions(aFilter: string; aOnlySelected: Boolean): Boolean;
@ -1364,12 +1388,15 @@ constructor TCompilerOptThread.Create(aReader: TCompilerOptReader);
begin
inherited Create(True);
//FreeOnTerminate:=True;
fStartedOnce:=false;
fReader:=aReader;
fReader.UpdateTargetParam;
end;
destructor TCompilerOptThread.Destroy;
begin
if fStartedOnce then
WaitFor;
Clear;
inherited Destroy;
end;
@ -1378,17 +1405,51 @@ begin
Result := fReader.ErrorMsg;
end;
procedure TCompilerOptThread.Clear;
begin
FreeAndNil(fOutputH);
FreeAndNil(fOutputI);
end;
procedure TCompilerOptThread.StartParsing;
begin
if fStartedOnce then
WaitFor;
fReader.CompilerExecutable:=LazarusIDE.GetFPCompilerFilename;;
fReader.UpdateTargetParam;
fCompPath:=fReader.CompilerExecutable;
fCompParams:=fReader.ParsedTarget;
Start;
fStartedOnce:=true;
end;
procedure TCompilerOptThread.EndParsing;
begin
if fStartedOnce then
WaitFor;
if (fOutputI<>nil) or (fOutputH<>nil) then begin
try
fReader.ParseOptions(fOutputI,fOutputH);
except
on E: Exception do
fReader.ErrorMsg := 'Error parsing compiler output: '+E.Message;
end;
Clear;
end;
end;
procedure TCompilerOptThread.Execute;
var
StartTime: TDateTime;
begin
StartTime := Now;
try
fReader.CompilerExecutable := LazarusIDE.GetFPCompilerFilename;
fReader.ReadAndParseOptions;
if fOutputI<>nil then exit;
if fOutputH<>nil then exit;
fReader.ReadCompiler(fCompPath,fCompParams,fOutputI,fOutputH);
except
on E: Exception do
fReader.ErrorMsg := 'Error parsing options: '+E.Message;
fReader.ErrorMsg := 'Error reading compiler: '+E.Message;
end;
fReadTime := Now-StartTime;
end;

View File

@ -161,7 +161,7 @@ begin
IdleConnected := False;
Screen.Cursor := crHourGlass;
try
FOptionsThread.WaitFor; // Make sure the options are read.
FOptionsThread.EndParsing; // Make sure the options are read.
// Parse and separate defines from other options.
FOptionsReader.FromCustomOptions(FCustomOptions);
// Check the found defines in the GUI.

View File

@ -31,7 +31,7 @@ uses
Classes, SysUtils, math, AVL_Tree, LazLogger, Forms, Controls, Graphics,
Dialogs, StdCtrls, LCLProc, ComCtrls, LCLType, ExtCtrls, Buttons,
CodeToolsCfgScript, KeywordFuncLists, LazarusIDEStrConsts,
IDEOptionsIntf, CompOptsIntf, IDECommands, Project, PackageDefs,
IDEOptionsIntf, CompOptsIntf, IDECommands, LazIDEIntf, Project, PackageDefs,
CompilerOptions, Compiler, AllCompilerOptions, CustomDefines,
EditorOptions, SynEdit, SynEditKeyCmds, SynCompletion, SourceSynEditor;
@ -366,18 +366,15 @@ begin
if Value then begin
if Assigned(fOptionsThread) then
begin
fOptionsThread.WaitFor; // Make sure the thread has finished running.
fOptionsThread.EndParsing; // Make sure the thread has finished running.
if FOptionsReader.UpdateTargetParam then begin
// Does not happen because UpdateTargetParam uses global macros
// which change only after closing the options window.
// This code is here for future refactoring, to react to changed target in GUI.
FOptionsReader.Clear;
fOptionsThread.Start; // Read new options.
fOptionsThread.StartParsing; // Read new options.
end;
end
else begin
fOptionsThread := TCompilerOptThread.Create(FOptionsReader);
fOptionsThread.Start;
fOptionsThread.StartParsing;
end;
end;
end;
@ -391,6 +388,8 @@ end;
procedure TCompilerOtherOptionsFrame.SetIdleConnected(AValue: Boolean);
begin
if csDestroying in ComponentState then
AValue:=false;
if FIdleConnected=AValue then exit;
FIdleConnected:=AValue;
if FIdleConnected then
@ -675,6 +674,7 @@ end;
destructor TCompilerOtherOptionsFrame.Destroy;
begin
IdleConnected:=false;
FreeAndNil(fOptionsThread);
FreeAndNil(FOptionsReader);
FreeAndNil(FCompletionHistory);