Recent

Author Topic: Internal error with generics  (Read 443 times)

SymbolicFrank

  • Hero Member
  • *****
  • Posts: 1086
Internal error with generics
« on: July 19, 2022, 03:31:00 pm »
I tried to make these classes:

Code: Pascal  [Select][+][-]
  1. unit ThreadFunction;
  2.  
  3. {$mode Delphi}{$H+}
  4.  
  5. {
  6.   Requires PasMP.TPasMPUnboundedQueue in the calling thread!
  7. }
  8.  
  9. interface
  10.  
  11. uses
  12.   Classes, SysUtils, PasMP, Variants;
  13.  
  14. type
  15.  
  16.   TRunFunction<T> = class;
  17.  
  18.   { TRunResult }
  19.  
  20.   TRunResult = class(TObject)
  21.   protected
  22.     MyName: string;
  23.   public
  24.     Value: Variant;
  25.     Reference: TObject;
  26.     property Name: string read MyName;
  27.     constructor Create(ThisName: string);
  28.   end;
  29.  
  30.   { TResultQueue }
  31.  
  32.   TResultQueue = class(TPasMPUnboundedQueue<TRunResult>);
  33.  
  34.   { TThreadFunction }
  35.  
  36.   TThreadFunction<T> = function(ThisThread: TRunFunction<T>; ThisPara: T):
  37.     TRunResult of object;
  38.  
  39.   { TRunFunction }
  40.  
  41.   TRunFunction<T> = class(TThread)
  42.   protected
  43.     MyName: string;
  44.     MyQueue: TResultQueue;
  45.     MyFunction: TThreadFunction<T>;
  46.     MyPara: T;
  47.     procedure Execute; override;
  48.   public
  49.     constructor Create(ThisName: string; ThisQueue: TResultQueue;
  50.       ThisFunction: TThreadFunction<T>; ThisPara: T);
  51.     function PostMessage(ThisValue: Variant; ThisReference: TObject = nil):
  52.       Boolean;
  53.   end;
  54.  
  55.  
  56. implementation
  57.  
  58. { TRunResult }
  59.  
  60. constructor TRunResult.Create(ThisName: string);
  61. begin
  62.   MyName := ThisName;
  63.   Value := Null;
  64.   Reference := nil;
  65. end;
  66.  
  67. { TRunFunction }
  68.  
  69. procedure TRunFunction<T>.Execute;
  70. var
  71.   r: TRunResult;
  72. begin
  73.   if Assigned(MyFunction) then
  74.   begin
  75.     r := MyFunction(Self, MyPara);
  76.     if Assigned(MyQueue) then MyQueue.Enqueue(r);
  77.   end;
  78. end;
  79.  
  80. constructor TRunFunction<T>.Create(ThisName: string; ThisQueue: TResultQueue;
  81.   ThisFunction: TThreadFunction<T>; ThisPara: T);
  82. begin
  83.   inherited Create(True);
  84.  
  85.   FreeOnTerminate := True;
  86.   MyName := ThisName;
  87.   MyQueue := ThisQueue;
  88.   MyFunction := ThisFunction;
  89.   MyPara := ThisPara;
  90.  
  91.   Start;
  92. end;
  93.  
  94. function TRunFunction<T>.PostMessage(ThisValue: Variant; ThisReference: TObject
  95.   ): Boolean;
  96. var
  97.   r: TRunResult;
  98. begin
  99.   if Assigned(MyQueue) then
  100.   begin
  101.     r := TRunResult.Create(MyName);
  102.     r.Value := ThisValue;
  103.     r.Reference := ThisReference;
  104.     MyQueue.Enqueue(r);
  105.   end;
  106. end;
  107.  
  108. end.

But it gives an error on that line. What did I do wrong? With fixed parameters it works.

I'm trying to make it more generic by using generics to pass your own kind of parameter(s).

It uses this.
« Last Edit: July 19, 2022, 04:25:55 pm by SymbolicFrank »

SymbolicFrank

  • Hero Member
  • *****
  • Posts: 1086
Re: Internal error with generics
« Reply #1 on: July 19, 2022, 04:26:31 pm »
I inserted the whole unit, it's small.

PascalDragon

  • Hero Member
  • *****
  • Posts: 4562
  • Compiler Developer
Re: Internal error with generics
« Reply #2 on: July 20, 2022, 09:08:43 am »
But it gives an error on that line. What did I do wrong? With fixed parameters it works.

What error on what line? And with what version of FPC and on what platform? When reporting such things, be detailed.

Code: Pascal  [Select][+][-]
  1. type
  2.   TRunFunction<T> = class;

Forward declarations of generics are not supported in the released versions of FPC. They are only supported from 3.3.1 on. But even then your code triggers a different error for which I have yet to find the cause.

SymbolicFrank

  • Hero Member
  • *****
  • Posts: 1086
Re: Internal error with generics
« Reply #3 on: July 20, 2022, 11:16:11 am »
Ah, my mistake. I overwrote it.

I use trunk on Windows 10 64-bit.

Here:

Code: Pascal  [Select][+][-]
  1.   TRunFunction<T> = class(TThread)
  2.   protected
  3.     MyName: string;                // threadfunction.pas(43,11) Error: Internal error 200204175
  4.     MyQueue: TResultQueue;
  5.     MyFunction: TThreadFunction<T>;
  6.     MyPara: T;
  7.     procedure Execute; override;
  8.   public
  9.     constructor Create(ThisName: string; ThisQueue: TResultQueue;
  10.       ThisFunction: TThreadFunction<T>; ThisPara: T);
  11.     function PostMessage(ThisValue: Variant; ThisReference: TObject = nil):
  12.       Boolean;
  13.   end;
  14.  

I changed it like this:

Code: Pascal  [Select][+][-]
  1. unit ThreadFunction;
  2.  
  3. {$mode Delphi}{$H+}
  4.  
  5. {
  6.   Requires PasMP.TPasMPUnboundedQueue in the calling thread!
  7. }
  8.  
  9. interface
  10.  
  11. uses
  12.   Classes, SysUtils, PasMP, Variants;
  13.  
  14. type
  15.  
  16.   TRunFunction = class;
  17.  
  18.   { TRunResult }
  19.  
  20.   TRunResult = class(TObject)
  21.   protected
  22.     MyName: string;
  23.   public
  24.     Value: Variant;
  25.     Reference: TObject;
  26.     property Name: string read MyName;
  27.     constructor Create(ThisName: string);
  28.   end;
  29.  
  30.   { TResultQueue }
  31.  
  32.   TResultQueue = class(TPasMPUnboundedQueue<TRunResult>);
  33.  
  34.   { TThreadFunction }
  35.  
  36.   TThreadFunction = function(ThisThread: TRunFunction; Para1, Para2: Variant;
  37.     Para3: TObject): TRunResult of object;
  38.  
  39.   { TRunFunction }
  40.  
  41.   TRunFunction = class(TThread)
  42.   protected
  43.     MyName: string;
  44.     MyQueue: TResultQueue;
  45.     MyFunction: TThreadFunction;
  46.     MyPara1: Variant;
  47.     MyPara2: Variant;
  48.     MyPara3: TObject;
  49.     procedure Execute; override;
  50.   public
  51.     constructor Create(ThisName: string; ThisQueue: TResultQueue;
  52.       ThisFunction: TThreadFunction; Para1, Para2: Variant; Para3: TObject = nil);
  53.     function PostMessage(ThisValue: Variant; ThisReference: TObject = nil):
  54.       Boolean;
  55.   end;
  56.  
  57.  
  58. implementation
  59.  
  60. { TRunResult }
  61.  
  62. constructor TRunResult.Create(ThisName: string);
  63. begin
  64.   MyName := ThisName;
  65.   Value := Null;
  66.   Reference := nil;
  67. end;
  68.  
  69. { TRunFunction }
  70.  
  71. procedure TRunFunction.Execute;
  72. var
  73.   r: TRunResult;
  74. begin
  75.   if Assigned(MyFunction) then
  76.   begin
  77.     r := MyFunction(Self, MyPara1, MyPara2, MyPara3);
  78.     if Assigned(MyQueue) then MyQueue.Enqueue(r);
  79.   end;
  80. end;
  81.  
  82. constructor TRunFunction.Create(ThisName: string; ThisQueue: TResultQueue;
  83.   ThisFunction: TThreadFunction; Para1, Para2: Variant; Para3: TObject);
  84. begin
  85.   inherited Create(True);
  86.  
  87.   FreeOnTerminate := True;
  88.   MyName := ThisName;
  89.   MyQueue := ThisQueue;
  90.   MyFunction := ThisFunction;
  91.   MyPara1 := Para1;
  92.   MyPara2 := Para2;
  93.   MyPara3 := Para3;
  94.  
  95.   Start;
  96. end;
  97.  
  98. function TRunFunction.PostMessage(ThisValue: Variant; ThisReference: TObject
  99.   ): Boolean;
  100. var
  101.   r: TRunResult;
  102. begin
  103.   Result := False;
  104.  
  105.   if Assigned(MyQueue) then
  106.   begin
  107.     r := TRunResult.Create(MyName);
  108.     r.Value := ThisValue;
  109.     r.Reference := ThisReference;
  110.     MyQueue.Enqueue(r);
  111.     Result := True;
  112.   end;
  113. end;
  114.  
  115. end.
  116.  

With two variants and an object as parameters. That works. But I would prefer a generic version.
« Last Edit: July 20, 2022, 11:36:15 am by SymbolicFrank »

PascalDragon

  • Hero Member
  • *****
  • Posts: 4562
  • Compiler Developer
Re: Internal error with generics
« Reply #4 on: July 20, 2022, 01:40:41 pm »
Ah, my mistake. I overwrote it.

I use trunk on Windows 10 64-bit.

Okay, then that is the same error I got in the end. Please report a bug (and preferably with an example that does not require PasMP).

SymbolicFrank

  • Hero Member
  • *****
  • Posts: 1086
Re: Internal error with generics
« Reply #5 on: July 20, 2022, 04:45:03 pm »
Done.

There were 5 other bugs like it, but not the same.

 

TinyPortal © 2005-2018