mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-08-18 02:19:32 +02:00
LCL: made QueueAsyncCall and RemoveAsyncCalls thread safe
git-svn-id: trunk@31143 -
This commit is contained in:
parent
db47008d5d
commit
44fa8c6766
@ -1148,6 +1148,7 @@ type
|
|||||||
Top, Last: PAsyncCallQueueItem;
|
Top, Last: PAsyncCallQueueItem;
|
||||||
end;
|
end;
|
||||||
TAsyncCallQueues = record
|
TAsyncCallQueues = record
|
||||||
|
CritSec: TRTLCriticalSection;
|
||||||
Cur: TAsyncCallQueue; // currently processing
|
Cur: TAsyncCallQueue; // currently processing
|
||||||
Next: TAsyncCallQueue; // new calls added to this queue
|
Next: TAsyncCallQueue; // new calls added to this queue
|
||||||
end;
|
end;
|
||||||
|
@ -102,6 +102,7 @@ begin
|
|||||||
anoEscapeForCancelControl,anoF1ForHelp,anoArrowToSelectNextInParent];
|
anoEscapeForCancelControl,anoF1ForHelp,anoArrowToSelectNextInParent];
|
||||||
ApplicationActionComponent:=Self;
|
ApplicationActionComponent:=Self;
|
||||||
OnMenuPopupHandler:=@MenuPopupHandler;
|
OnMenuPopupHandler:=@MenuPopupHandler;
|
||||||
|
System.InitCriticalSection(FAsyncCall.CritSec);
|
||||||
|
|
||||||
FFindGlobalComponentEnabled:=true;
|
FFindGlobalComponentEnabled:=true;
|
||||||
RegisterFindGlobalComponentProc(@FindApplicationComponent);
|
RegisterFindGlobalComponentProc(@FindApplicationComponent);
|
||||||
@ -143,6 +144,8 @@ begin
|
|||||||
ExitProc:=FOldExitProc;
|
ExitProc:=FOldExitProc;
|
||||||
|
|
||||||
ProcessAsyncCallQueue;
|
ProcessAsyncCallQueue;
|
||||||
|
System.DoneCriticalSection(FAsyncCall.CritSec);
|
||||||
|
|
||||||
if OnMenuPopupHandler=@MenuPopupHandler then
|
if OnMenuPopupHandler=@MenuPopupHandler then
|
||||||
OnMenuPopupHandler:=nil;
|
OnMenuPopupHandler:=nil;
|
||||||
|
|
||||||
@ -1020,42 +1023,52 @@ var
|
|||||||
begin
|
begin
|
||||||
with FAsyncCall do begin
|
with FAsyncCall do begin
|
||||||
// move the items of NextQueue to CurQueue, keep the order
|
// move the items of NextQueue to CurQueue, keep the order
|
||||||
if Next.Top<>nil then
|
System.EnterCriticalsection(CritSec);
|
||||||
begin
|
try
|
||||||
if Cur.Last<>nil then
|
if Next.Top<>nil then
|
||||||
begin
|
begin
|
||||||
assert(Cur.Top <> nil, 'TApplication.ProcessAsyncCallQueue: Last entry found, while Top not assigned');
|
if Cur.Last<>nil then
|
||||||
Cur.Last^.NextItem:=Next.Top;
|
begin
|
||||||
Next.Top^.PrevItem:=Cur.Last;
|
assert(Cur.Top <> nil, 'TApplication.ProcessAsyncCallQueue: Last entry found, while Top not assigned');
|
||||||
end else begin
|
Cur.Last^.NextItem:=Next.Top;
|
||||||
assert(Cur.Top = nil, 'TApplication.ProcessAsyncCallQueue: Last entry found, while Top not assigned');
|
Next.Top^.PrevItem:=Cur.Last;
|
||||||
Cur.Top:=Next.Top;
|
end else begin
|
||||||
|
assert(Cur.Top = nil, 'TApplication.ProcessAsyncCallQueue: Last entry found, while Top not assigned');
|
||||||
|
Cur.Top:=Next.Top;
|
||||||
|
end;
|
||||||
|
Cur.Last:=Next.Last;
|
||||||
|
Next.Top:=nil;
|
||||||
|
Next.Last:=nil;
|
||||||
end;
|
end;
|
||||||
Cur.Last:=Next.Last;
|
finally
|
||||||
Next.Top:=nil;
|
System.LeaveCriticalsection(CritSec);
|
||||||
Next.Last:=nil;
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
// process items from top to last in 'Cur' queue
|
// process items from top to last in 'Cur' queue
|
||||||
// this can create new items, which are added to the 'Next' queue
|
// this can create new items, which are added to the 'Next' queue
|
||||||
// or it can call ProcessAsyncCallQueue, for example via calling
|
// or it can call ProcessAsyncCallQueue, for example via calling
|
||||||
// Application.ProcesssMessages
|
// Application.ProcesssMessages
|
||||||
while Cur.Top <> nil do
|
repeat
|
||||||
begin
|
|
||||||
// remove top item from queue
|
// remove top item from queue
|
||||||
lItem:=Cur.Top;
|
System.EnterCriticalSection(CritSec);
|
||||||
Cur.Top := lItem^.NextItem;
|
try
|
||||||
if Cur.Top = nil then
|
if Cur.Top=nil then exit;
|
||||||
Cur.Last := nil
|
lItem:=Cur.Top;
|
||||||
else
|
Cur.Top := lItem^.NextItem;
|
||||||
Cur.Top^.PrevItem := nil;
|
if Cur.Top = nil then
|
||||||
// free item
|
Cur.Last := nil
|
||||||
Event:=lItem^.Method;
|
else
|
||||||
Data:=lItem^.Data;
|
Cur.Top^.PrevItem := nil;
|
||||||
Dispose(lItem);
|
// free item
|
||||||
|
Event:=lItem^.Method;
|
||||||
|
Data:=lItem^.Data;
|
||||||
|
Dispose(lItem);
|
||||||
|
finally
|
||||||
|
System.LeaveCriticalSection(CritSec);
|
||||||
|
end;
|
||||||
// call event
|
// call event
|
||||||
Event(Data);
|
Event(Data);
|
||||||
end;
|
until false;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -2167,16 +2180,21 @@ begin
|
|||||||
lItem^.Method := AMethod;
|
lItem^.Method := AMethod;
|
||||||
lItem^.Data := Data;
|
lItem^.Data := Data;
|
||||||
lItem^.NextItem := nil;
|
lItem^.NextItem := nil;
|
||||||
with FAsyncCall.Next do begin
|
System.EnterCriticalsection(FAsyncCall.CritSec);
|
||||||
lItem^.PrevItem := Last;
|
try
|
||||||
if Last<>nil then begin
|
with FAsyncCall.Next do begin
|
||||||
assert(Top <> nil, 'TApplication.QueueAsyncCall: Top entry missing (but last is assigned)');
|
lItem^.PrevItem := Last;
|
||||||
Last^.NextItem := lItem
|
if Last<>nil then begin
|
||||||
end else begin
|
assert(Top <> nil, 'TApplication.QueueAsyncCall: Top entry missing (but last is assigned)');
|
||||||
assert(Last = nil, 'TApplication.QueueAsyncCall: Last entry found, while Top not assigned');
|
Last^.NextItem := lItem
|
||||||
Top := lItem;
|
end else begin
|
||||||
|
assert(Last = nil, 'TApplication.QueueAsyncCall: Last entry found, while Top not assigned');
|
||||||
|
Top := lItem;
|
||||||
|
end;
|
||||||
|
Last := lItem;
|
||||||
end;
|
end;
|
||||||
Last := lItem;
|
finally
|
||||||
|
System.LeaveCriticalsection(FAsyncCall.CritSec);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
if Assigned(WakeMainThread) then
|
if Assigned(WakeMainThread) then
|
||||||
@ -2215,8 +2233,13 @@ begin
|
|||||||
if AppDoNotCallAsyncQueue in FFlags then
|
if AppDoNotCallAsyncQueue in FFlags then
|
||||||
raise Exception.Create('TApplication.QueueAsyncCall already shut down');
|
raise Exception.Create('TApplication.QueueAsyncCall already shut down');
|
||||||
|
|
||||||
DoRemoveAsyncCalls(FAsyncCall.Cur);
|
System.EnterCriticalsection(FAsyncCall.CritSec);
|
||||||
DoRemoveAsyncCalls(FAsyncCall.Next);
|
try
|
||||||
|
DoRemoveAsyncCalls(FAsyncCall.Cur);
|
||||||
|
DoRemoveAsyncCalls(FAsyncCall.Next);
|
||||||
|
finally
|
||||||
|
System.LeaveCriticalSection(FAsyncCall.CritSec);
|
||||||
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TApplication.FreeComponent(Data: PtrInt);
|
procedure TApplication.FreeComponent(Data: PtrInt);
|
||||||
|
@ -9324,26 +9324,6 @@ begin
|
|||||||
ACritSec:=System.PRTLCriticalSection(CritSection);
|
ACritSec:=System.PRTLCriticalSection(CritSection);
|
||||||
System.EnterCriticalsection(ACritSec^);
|
System.EnterCriticalsection(ACritSec^);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{var
|
|
||||||
Crit,
|
|
||||||
tmp : ppthread_mutex_t;
|
|
||||||
begin
|
|
||||||
New(Crit);
|
|
||||||
If CritSection <> 0 then
|
|
||||||
Try
|
|
||||||
Crit^ := ppthread_mutex_t(CritSection)^;
|
|
||||||
except
|
|
||||||
begin
|
|
||||||
CritSection := Longint(Crit);
|
|
||||||
exit;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
pthread_mutex_lock(Crit^);
|
|
||||||
tmp := ppthread_mutex_t(CritSection);
|
|
||||||
CritSection := Longint(Crit);
|
|
||||||
Dispose(Tmp);
|
|
||||||
end;}
|
|
||||||
{$Else}
|
{$Else}
|
||||||
begin
|
begin
|
||||||
end;
|
end;
|
||||||
@ -9357,25 +9337,6 @@ begin
|
|||||||
ACritSec:=System.PRTLCriticalSection(CritSection);
|
ACritSec:=System.PRTLCriticalSection(CritSection);
|
||||||
System.LeaveCriticalsection(ACritSec^);
|
System.LeaveCriticalsection(ACritSec^);
|
||||||
end;
|
end;
|
||||||
{var
|
|
||||||
Crit,
|
|
||||||
tmp : ppthread_mutex_t;
|
|
||||||
begin
|
|
||||||
New(Crit);
|
|
||||||
If CritSection <> 0 then
|
|
||||||
Try
|
|
||||||
Crit^ := ppthread_mutex_t(CritSection)^;
|
|
||||||
except
|
|
||||||
begin
|
|
||||||
CritSection := Longint(Crit);
|
|
||||||
exit;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
pthread_mutex_unlock(Crit^);
|
|
||||||
tmp := ppthread_mutex_t(CritSection);
|
|
||||||
CritSection := Longint(Crit);
|
|
||||||
Dispose(Tmp);
|
|
||||||
end;}
|
|
||||||
{$Else}
|
{$Else}
|
||||||
begin
|
begin
|
||||||
end;
|
end;
|
||||||
@ -9391,26 +9352,6 @@ begin
|
|||||||
Dispose(ACritSec);
|
Dispose(ACritSec);
|
||||||
CritSection:=0;
|
CritSection:=0;
|
||||||
end;
|
end;
|
||||||
{var
|
|
||||||
Crit,
|
|
||||||
tmp : ppthread_mutex_t;
|
|
||||||
begin
|
|
||||||
New(Crit);
|
|
||||||
If CritSection <> 0 then
|
|
||||||
Try
|
|
||||||
Crit^ := ppthread_mutex_t(CritSection)^;
|
|
||||||
except
|
|
||||||
begin
|
|
||||||
CritSection := Longint(Crit);
|
|
||||||
exit;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
pthread_mutex_destroy(Crit^);
|
|
||||||
Dispose(Crit);
|
|
||||||
tmp := ppthread_mutex_t(CritSection);
|
|
||||||
CritSection := 0;
|
|
||||||
Dispose(Tmp);
|
|
||||||
end;}
|
|
||||||
{$Else}
|
{$Else}
|
||||||
begin
|
begin
|
||||||
end;
|
end;
|
||||||
|
Loading…
Reference in New Issue
Block a user