mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-07 06:28:55 +02:00
+ add Delphi compatible TThread.ForceQueue() which enqueues the method also for the main thread (at least if the RTL is in multi threading mode, otherwise it's still executed right away - whether this is Delphi compatible needs to be tested as I only have a 10.1 currently which does not yet support TThread.ForceQueue())
+ added test git-svn-id: trunk@37359 -
This commit is contained in:
parent
4f39e57f62
commit
81a0f88d8c
1
.gitattributes
vendored
1
.gitattributes
vendored
@ -11407,6 +11407,7 @@ tests/tbs/tb0628.pp svneol=native#text/pascal
|
||||
tests/tbs/tb0629.pp svneol=native#text/pascal
|
||||
tests/tbs/tb0630.pp svneol=native#text/pascal
|
||||
tests/tbs/tb0631.pp svneol=native#text/pascal
|
||||
tests/tbs/tb0632.pp svneol=native#text/pascal
|
||||
tests/tbs/tb205.pp svneol=native#text/plain
|
||||
tests/tbs/tb610.pp svneol=native#text/pascal
|
||||
tests/tbs/tb613.pp svneol=native#text/plain
|
||||
|
@ -289,11 +289,11 @@ begin
|
||||
end;
|
||||
|
||||
|
||||
procedure ThreadQueueAppend(aEntry: TThread.PThreadQueueEntry);
|
||||
procedure ThreadQueueAppend(aEntry: TThread.PThreadQueueEntry; aQueueIfMain: Boolean);
|
||||
begin
|
||||
{ do we really need a synchronized call? }
|
||||
{$ifdef FPC_HAS_FEATURE_THREADING}
|
||||
if GetCurrentThreadID = MainThreadID then
|
||||
if (GetCurrentThreadID = MainThreadID) and (not aQueueIfMain or not IsMultiThread) then
|
||||
{$endif}
|
||||
begin
|
||||
ExecuteThreadQueueEntry(aEntry);
|
||||
@ -383,7 +383,7 @@ class procedure TThread.Synchronize(AThread: TThread; AMethod: TThreadMethod);
|
||||
|
||||
syncentry^.Exception := Nil;
|
||||
syncentry^.Method := AMethod;
|
||||
ThreadQueueAppend(syncentry);
|
||||
ThreadQueueAppend(syncentry, False);
|
||||
|
||||
syncentry^.Method := Nil;
|
||||
syncentry^.Next := Nil;
|
||||
@ -502,6 +502,12 @@ end;
|
||||
|
||||
|
||||
class procedure TThread.Queue(aThread: TThread; aMethod: TThreadMethod); static;
|
||||
begin
|
||||
InternalQueue(aThread, aMethod, False);
|
||||
end;
|
||||
|
||||
|
||||
class procedure TThread.InternalQueue(aThread: TThread; aMethod: TThreadMethod; aQueueIfMain: Boolean); static;
|
||||
var
|
||||
queueentry: PThreadQueueEntry;
|
||||
begin
|
||||
@ -516,10 +522,21 @@ begin
|
||||
queueentry^.Method := aMethod;
|
||||
|
||||
{ the queueentry is freed by CheckSynchronize (or by RemoveQueuedEvents) }
|
||||
ThreadQueueAppend(queueentry);
|
||||
ThreadQueueAppend(queueentry, aQueueIfMain);
|
||||
end;
|
||||
|
||||
|
||||
procedure TThread.ForceQueue(aMethod: TThreadMethod);
|
||||
begin
|
||||
ForceQueue(Self, aMethod);
|
||||
end;
|
||||
|
||||
|
||||
class procedure TThread.ForceQueue(aThread: TThread; aMethod: TThreadMethod); static;
|
||||
begin
|
||||
InternalQueue(aThread, aMethod, True);
|
||||
end;
|
||||
|
||||
class procedure TThread.RemoveQueuedEvents(aThread: TThread; aMethod: TThreadMethod);
|
||||
var
|
||||
entry, tmpentry, lastentry: PThreadQueueEntry;
|
||||
|
@ -1649,6 +1649,7 @@ type
|
||||
FSynchronizeEntry: PThreadQueueEntry;
|
||||
class function GetCurrentThread: TThread; static;
|
||||
class function GetIsSingleProcessor: Boolean; static; inline;
|
||||
class procedure InternalQueue(aThread: TThread; aMethod: TThreadMethod; aQueueIfMain: Boolean); static;
|
||||
procedure CallOnTerminate;
|
||||
function GetPriority: TThreadPriority;
|
||||
procedure SetPriority(Value: TThreadPriority);
|
||||
@ -1666,6 +1667,7 @@ type
|
||||
procedure Execute; virtual; abstract;
|
||||
procedure Synchronize(AMethod: TThreadMethod);
|
||||
procedure Queue(aMethod: TThreadMethod);
|
||||
procedure ForceQueue(aMethod: TThreadMethod); inline;
|
||||
property ReturnValue: Integer read FReturnValue write FReturnValue;
|
||||
property Terminated: Boolean read FTerminated;
|
||||
{$if defined(windows) or defined(OS2)}
|
||||
@ -1714,6 +1716,7 @@ type
|
||||
class function CheckTerminated: Boolean; static;
|
||||
class procedure Synchronize(AThread: TThread; AMethod: TThreadMethod);
|
||||
class procedure Queue(aThread: TThread; aMethod: TThreadMethod); static;
|
||||
class procedure ForceQueue(aThread: TThread; aMethod: TThreadMethod); inline; static;
|
||||
class procedure RemoveQueuedEvents(aThread: TThread; aMethod: TThreadMethod); static;
|
||||
class procedure RemoveQueuedEvents(aMethod: TThreadMethod); static;
|
||||
class procedure RemoveQueuedEvents(aThread: TThread); static;
|
||||
|
77
tests/tbs/tb0632.pp
Normal file
77
tests/tbs/tb0632.pp
Normal file
@ -0,0 +1,77 @@
|
||||
{ Note: needs multi threading }
|
||||
program tb0632;
|
||||
|
||||
{$mode objfpc}
|
||||
|
||||
uses
|
||||
{$ifdef unix}
|
||||
cthreads,
|
||||
{$endif}
|
||||
classes;
|
||||
|
||||
type
|
||||
TTest = class
|
||||
private
|
||||
fValue: LongInt;
|
||||
procedure DoTest;
|
||||
public
|
||||
procedure Test;
|
||||
end;
|
||||
|
||||
TDummyThread = class(TThread)
|
||||
public
|
||||
constructor Create;
|
||||
protected
|
||||
procedure Execute; override;
|
||||
end;
|
||||
|
||||
{ TDummyThread }
|
||||
|
||||
constructor TDummyThread.Create;
|
||||
begin
|
||||
inherited Create(True);
|
||||
FreeOnTerminate := True;
|
||||
end;
|
||||
|
||||
procedure TDummyThread.Execute;
|
||||
begin
|
||||
{ empty }
|
||||
end;
|
||||
|
||||
{ TTest }
|
||||
|
||||
procedure TTest.DoTest;
|
||||
begin
|
||||
Inc(fValue);
|
||||
end;
|
||||
|
||||
procedure TTest.Test;
|
||||
begin
|
||||
TThread.Queue(Nil, @DoTest);
|
||||
if fValue <> 1 then
|
||||
Halt(1);
|
||||
TThread.ForceQueue(Nil, @DoTest);
|
||||
if fValue <> 1 then
|
||||
Halt(2);
|
||||
CheckSynchronize;
|
||||
if fValue <> 2 then
|
||||
Halt(3);
|
||||
Writeln('Ok');
|
||||
end;
|
||||
|
||||
var
|
||||
t: TTest;
|
||||
begin
|
||||
{$ifdef FPC_HAS_FEATURE_THREADING}
|
||||
{ ensure that the RTL is in multi threading mode, otherwise CheckSynchronize
|
||||
ignores the queue }
|
||||
TDummyThread.Create.Start;
|
||||
|
||||
t := TTest.Create;
|
||||
try
|
||||
t.Test;
|
||||
finally
|
||||
t.Free;
|
||||
end;
|
||||
{$endif}
|
||||
end.
|
Loading…
Reference in New Issue
Block a user