View Issue Details

IDProjectCategoryView StatusLast Update
0037819FPCDocumentationpublic2020-09-30 10:00
ReporterMartin Friebe Assigned ToOndrej Pokorny  
PrioritynormalSeverityminorReproducibilityalways
Status resolvedResolutionfixed 
Platform64bit IntelOSwin 10 
Product Version3.2.0 
Summary0037819: Documentation for TThread.RemoveQueuedEvents
Descriptionhttps://www.freepascal.org/docs-html/rtl/classes/tthread.removequeuedevents.html

>> all calls to the given method .... are removed.

type TThreadMethod = procedure of object;
public class procedure TThread.RemoveQueuedEvents( aThread: TThread; aMethod: TThreadMethod);

"The given method" can either refer to
- "aMethod", which is a variable containing a code reference, AND an instance
- the code reference contained in "aMethod"

Currently the 2nd applies (and appears to also be "what Delphi does"). // Ondrej edit: Delphi compares both Code and Data pointers

The documentation should be reworded, to make it more clear that the value of the instance passed in as part of the parameters fulfils no purpose and is ignored.

----------
While it could be inferred from the fact that "calls to" do not care about arguments passed to the callee, this "hint" seems very subtle compared to the fact that half of a parameter passed to RemoveQueuedEvents is ignored.


Steps To Reproduceprogram Project1;

{$ifdef fpc}
  {$mode delphi}
  {$Macro on}
  {$Define AtomicIncrement:=InterlockedIncrement}
  {$Define AtomicDecrement:=InterlockedDecrement}
{$else}
  {$APPTYPE CONSOLE}
{$endif}

uses
  {$IFDEF UNIX} cthreads, {$ENDIF} Classes;

type
  TMyClass = class
  public
    ThreadID, ClassID: Integer;
    procedure Foo;
  end;

  TMyThread = class(TThread)
  private
    ID: Integer;
    c1, c2: TMyClass;
  public
    procedure Execute; override;

    constructor Create(const AID: Integer);
    destructor Destroy; override;
  end;
var
  i: integer;
constructor TMyThread.Create(const AID: Integer);
begin
  AtomicIncrement(i);
  ID := AID;
  FreeOnTerminate := False;
  c1 := TMyClass.Create;
  c1.ThreadID := ID;
  c1.ClassID := 1;
  c2 := TMyClass.Create;
  c2.ThreadID := ID;
  c2.ClassID := 2;
  inherited Create(False);
end;

destructor TMyThread.Destroy;
begin
  c1.Free;
  c2.Free;
  inherited Destroy;
end;

procedure TMyThread.Execute;
begin
  Queue(self, c1.Foo);
  Queue(self, c2.Foo);
  Sleep(500);
  case ID of
    1: RemoveQueuedEvents(Self, c1.Foo);
    2: RemoveQueuedEvents(nil, c1.Foo);
    3: RemoveQueuedEvents(Self, nil);
  end;
  AtomicDecrement(i);
end;

procedure TMyClass.Foo;
begin
  writeln('In Foo: ThreadID=', ThreadID, ', ClassID=', ClassID);
end;

var
  t1, t2, t3: TMyThread;
begin
  i := 0;
  t1 := TMyThread.Create(1);
  t2 := TMyThread.Create(2);
  t3 := TMyThread.Create(3);
  while i > 0 do ;
  CheckSynchronize();
  ReadLn;
  t1.Free;
  t2.Free;
  t3.Free;
end.

---
Delphi output:
In Foo: ThreadID=2, ClassID=2
---
FPC: output:
// nothing -- FPC deletes too much
Additional InformationSee also https://lists.freepascal.org/pipermail/fpc-devel/2020-September/043165.html and replies
TagsNo tags attached.
Fixed in Revision1755
FPCOldBugId
FPCTarget-
Attached Files

Activities

Martin Friebe

2020-09-26 14:52

manager   ~0125874

Update:
Now there are 2 opposing answers

https://lists.freepascal.org/pipermail/fpc-devel/2020-September/043172.html

Mattias: Delphi checks Code and Data.
https://lists.freepascal.org/pipermail/fpc-devel/2020-September/043172.html

Pascal R: you get no "In Foo"!
https://lists.freepascal.org/pipermail/fpc-devel/2020-September/043171.html

So depending on who is right, this may be documentation OR implementation

Ondrej Pokorny

2020-09-29 16:22

developer   ~0125958

They are not opposing answers. You just interpreted the results wrongly. Read the Delphi documentation again: http://docwiki.embarcadero.com/Libraries/Sydney/en/System.Classes.TThread.RemoveQueuedEvents :

RemoveQueuedEvents removes queued method calls. The operation proceeds in one of two ways. If AThread is specified, then all method calls queued by this thread are removed. If AThread is nil, then all calls to the specified AMethod method are removed, regardless of the thread that queued the call.

That means that if you use the AThread parameter (AThread<>nil), the AMethod parameter doesn't matter.
The second statement ("If AThread is nil") is not exactly true. The AMethod methods are removed also if AThread is not nil. It's either AThread or AMethod, not exclusive.

To prove this behavior, I updated the steps-to-reproduce with a test program (a modified version of yours).

Michael Van Canneyt

2020-09-29 16:46

administrator   ~0125961

@Ondrej,

I talked with Sven about this issue, he's also working on it:
in FPC apparently only the code (instead of code+data) pointer is considered.

Please synchronize with him if you plan to change things.

Ondrej Pokorny

2020-09-30 10:00

developer   ~0125978

I fixed the docs. Please check and close if OK.

Issue History

Date Modified Username Field Change
2020-09-26 14:37 Martin Friebe New Issue
2020-09-26 14:37 Martin Friebe Status new => assigned
2020-09-26 14:37 Martin Friebe Assigned To => Michael Van Canneyt
2020-09-26 14:52 Martin Friebe Note Added: 0125874
2020-09-29 16:22 Ondrej Pokorny Note Added: 0125958
2020-09-29 16:22 Ondrej Pokorny Steps to Reproduce Updated View Revisions
2020-09-29 16:22 Ondrej Pokorny FPCTarget => -
2020-09-29 16:23 Ondrej Pokorny Steps to Reproduce Updated View Revisions
2020-09-29 16:29 Ondrej Pokorny Steps to Reproduce Updated View Revisions
2020-09-29 16:29 Ondrej Pokorny Steps to Reproduce Updated View Revisions
2020-09-29 16:30 Ondrej Pokorny Assigned To Michael Van Canneyt => Ondrej Pokorny
2020-09-29 16:42 Ondrej Pokorny Description Updated View Revisions
2020-09-29 16:46 Michael Van Canneyt Note Added: 0125961
2020-09-30 10:00 Ondrej Pokorny Status assigned => resolved
2020-09-30 10:00 Ondrej Pokorny Resolution open => fixed
2020-09-30 10:00 Ondrej Pokorny Fixed in Revision => 1755
2020-09-30 10:00 Ondrej Pokorny Note Added: 0125978