Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / lazarus / 2009-08

local procedure - MultiThreadProc

13 messages · 6 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Jan Kowalski

I need to call ProcThreadPool.DoParallel with "local" procedure as a parameter. Does DoParallel allow local procedures to pass a procedural parameters ? I get err: Error:
Incompatible type for arg no. 1: Got "<address of local procedure(Int64,Pointer,TMultiThreadProcItem);Register>", expected "<procedure variable type of
procedure(Int64,Pointer,TMultiThreadProcItem);Register>"

Best regards
Tomek

Reply by email

Mattias Gärtner
to Jan Kowalski

Zitat von Jan Kowalski :

Show quoted text 8 lines
I need to call ProcThreadPool.DoParallel with "local" procedure as a parameter. Does DoParallel allow local procedures to pass a procedural parameters ? I get err: Error: Incompatible type for arg no. 1: Got "<address of local procedure(Int64,Pointer,TMultiThreadProcItem);Register>", expected "<procedure variable type of procedure(Int64,Pointer,TMultiThreadProcItem);Register>"

That would be really helpful.
But I don't know how to define a local procedure type:

type
   TMTLocalProcedure = procedure(Index: PtrInt; Data: Pointer;
                                 Item: Pointer); ?
var
   p: TMTLocalProcedure;
procedure TestWithLocalProc;
   procedure LocalProc(Index: PtrInt; Data: Pointer; Item:
TMultiThreadProcItem);
   begin
   end;
begin
   ;
end;

Mattias

Reply by email

Martin
to Mattias Gärtner
Mattias G?rtner wrote 13 lines
Zitat von Jan Kowalski : > I need to call ProcThreadPool.DoParallel with "local" procedure as a > parameter. > Does DoParallel allow local procedures to pass a procedural parameters ? > I get err: Error: > Incompatible type for arg no. 1: Got "<address of local > procedure(Int64,Pointer,TMultiThreadProcItem);Register>", expected > "<procedure variable type of > procedure(Int64,Pointer,TMultiThreadProcItem);Register>" That would be really helpful. But I don't know how to define a local procedure type:

I wouldn't be sure it's possible. It makes no sense.

My guess:
A local (nested) procedure has access to the outer(parent or grand-parent if recursive) procedures variables (stackframe). Therefore a local procedure must expect to be somewhere below this parent.

If it was given as a pointer to some other procedure/object, and then called later, this may happen outside the parent. Then no such stackframe does exist, and the local procedure can not work.

Martin

Show quoted text 28 lines
type TMTLocalProcedure = procedure(Index: PtrInt; Data: Pointer; Item: Pointer); ? var p: TMTLocalProcedure; procedure TestWithLocalProc; procedure LocalProc(Index: PtrInt; Data: Pointer; Item: TMultiThreadProcItem); begin end; begin ; end; Mattias -- _______________________________________________ Lazarus mailing list http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus

Reply by email

Vincent Snijders
to Martin
Martin wrote 25 lines
Mattias G?rtner wrote: > Zitat von Jan Kowalski : >> I need to call ProcThreadPool.DoParallel with "local" procedure as a >> parameter. >> Does DoParallel allow local procedures to pass a procedural parameters ? >> I get err: Error: >> Incompatible type for arg no. 1: Got "<address of local >> procedure(Int64,Pointer,TMultiThreadProcItem);Register>", expected >> "<procedure variable type of >> procedure(Int64,Pointer,TMultiThreadProcItem);Register>" > > That would be really helpful. > But I don't know how to define a local procedure type: > I wouldn't be sure it's possible. It makes no sense. My guess: A local (nested) procedure has access to the outer(parent or grand-parent if recursive) procedures variables (stackframe). Therefore a local procedure must expect to be somewhere below this parent. If it was given as a pointer to some other procedure/object, and then called later, this may happen outside the parent. Then no such stackframe does exist, and the local procedure can not work.

And therefore such a local procedure type must be a combination of local scope and address: http://wiki.freepascal.org/Mac_Local_Procedure_Parameters

This feature is not yet implemented:
http://wiki.freepascal.org/Language_related_articles#Ideas_for_new_stuff

Vincent

Reply by email

Mattias Gärtner
to Vincent Snijders

Zitat von Vincent Snijders :

Show quoted text 16 lines
Martin schreef: > Mattias G?rtner wrote: >> Zitat von Jan Kowalski : >>> I need to call ProcThreadPool.DoParallel with "local" procedure >>> as a parameter. >>> Does DoParallel allow local procedures to pass a procedural parameters ? >>> I get err: Error: >>> Incompatible type for arg no. 1: Got "<address of local >>> procedure(Int64,Pointer,TMultiThreadProcItem);Register>", expected >>> "<procedure variable type of >>> procedure(Int64,Pointer,TMultiThreadProcItem);Register>" >> >> That would be really helpful. >> But I don't know how to define a local procedure type: >> > I wouldn't be sure it's possible. It makes no sense.

It makes enough sense in this case.
For example when you want to execute a loop in parallel, then you extract the loop into a procedure. With a local procedure you can keep the variables, which would make the process quite easy. If you can not use a local procedure, then you must define a record and move the local variables there.
Of course nested local procedures creates a whole bunch of problems, so maybe the record approach is much safer.
Maybe the extract procedure tool can be extended to do some of the monotone work automatically.
I will explain the process in more detail on the wiki.

Show quoted text 17 lines
> My guess: > A local (nested) procedure has access to the outer(parent or > grand-parent if recursive) procedures variables (stackframe). > Therefore a local procedure must expect to be somewhere below this > parent. > > If it was given as a pointer to some other procedure/object, and > then called later, this may happen outside the parent. Then no such > stackframe does exist, and the local procedure can not work. > And therefore such a local procedure type must be a combination of local scope and address: http://wiki.freepascal.org/Mac_Local_Procedure_Parameters This feature is not yet implemented: http://wiki.freepascal.org/Language_related_articles#Ideas_for_new_stuff

Mattias

Reply by email

Martin
to Mattias Gärtner
Mattias G?rtner wrote 21 lines
Zitat von Vincent Snijders : > Martin schreef: >> Mattias G?rtner wrote: >>> Zitat von Jan Kowalski : >>>> I need to call ProcThreadPool.DoParallel with "local" procedure as >>>> a parameter. >>>> Does DoParallel allow local procedures to pass a procedural >>>> parameters ? >>>> I get err: Error: >>>> Incompatible type for arg no. 1: Got "<address of local >>>> procedure(Int64,Pointer,TMultiThreadProcItem);Register>", expected >>>> "<procedure variable type of >>>> procedure(Int64,Pointer,TMultiThreadProcItem);Register>" >>> >>> That would be really helpful. >>> But I don't know how to define a local procedure type: >>> >> I wouldn't be sure it's possible. It makes no sense. It makes enough sense in this case.

Sorry badly worded on my behalf.

It makes no sense, should have been: it can not be used the same way like normal procedure references, because it is limited to the scope. the way described on the link by Vincent indeed makes sense

Show quoted text 38 lines
For example when you want to execute a loop in parallel, then you extract the loop into a procedure. With a local procedure you can keep the variables, which would make the process quite easy. If you can not use a local procedure, then you must define a record and move the local variables there. Of course nested local procedures creates a whole bunch of problems, so maybe the record approach is much safer. Maybe the extract procedure tool can be extended to do some of the monotone work automatically. I will explain the process in more detail on the wiki. >> My guess: >> A local (nested) procedure has access to the outer(parent or >> grand-parent if recursive) procedures variables (stackframe). >> Therefore a local procedure must expect to be somewhere below this >> parent. >> >> If it was given as a pointer to some other procedure/object, and >> then called later, this may happen outside the parent. Then no such >> stackframe does exist, and the local procedure can not work. >> > > And therefore such a local procedure type must be a combination of > local scope and address: > http://wiki.freepascal.org/Mac_Local_Procedure_Parameters > > This feature is not yet implemented: > http://wiki.freepascal.org/Language_related_articles#Ideas_for_new_stuff Mattias -- _______________________________________________ Lazarus mailing list http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus

Reply by email

Florian Klaempfl
to Mattias Gärtner: Zitat von Vincent Snijders : It makes enough sense in this case. For example when you…
Show quoted text 31 lines
Zitat von Vincent Snijders : > Martin schreef: >> Mattias G?rtner wrote: >>> Zitat von Jan Kowalski : >>>> I need to call ProcThreadPool.DoParallel with "local" procedure as >>>> a parameter. >>>> Does DoParallel allow local procedures to pass a procedural >>>> parameters ? >>>> I get err: Error: >>>> Incompatible type for arg no. 1: Got "<address of local >>>> procedure(Int64,Pointer,TMultiThreadProcItem);Register>", expected >>>> "<procedure variable type of >>>> procedure(Int64,Pointer,TMultiThreadProcItem);Register>" >>> >>> That would be really helpful. >>> But I don't know how to define a local procedure type: >>> >> I wouldn't be sure it's possible. It makes no sense. It makes enough sense in this case. For example when you want to execute a loop in parallel, then you extract the loop into a procedure. With a local procedure you can keep the variables, which would make the process quite easy. If you can not use a local procedure, then you must define a record and move the local variables there. Of course nested local procedures creates a whole bunch of problems, so maybe the record approach is much safer. Maybe the extract procedure tool can be extended to do some of the monotone work automatically. I will explain the process in more detail on the wiki.

You can create a thread call for local procedures, it needs some hacking though: no type checking is possible, you've to work with pointers and pass the context explicitly.

Reply by email

Mattias Gaertner
to Florian Klaempfl
Show quoted text 36 lines
Mattias G?rtner schrieb: > Zitat von Vincent Snijders : > >> Martin schreef: >>> Mattias G?rtner wrote: >>>> Zitat von Jan Kowalski : >>>>> I need to call ProcThreadPool.DoParallel with "local" procedure >>>>> as a parameter. >>>>> Does DoParallel allow local procedures to pass a procedural >>>>> parameters ? >>>>> I get err: Error: >>>>> Incompatible type for arg no. 1: Got "<address of local >>>>> procedure(Int64,Pointer,TMultiThreadProcItem);Register>", >>>>> expected "<procedure variable type of >>>>> procedure(Int64,Pointer,TMultiThreadProcItem);Register>" >>>> >>>> That would be really helpful. >>>> But I don't know how to define a local procedure type: >>>> >>> I wouldn't be sure it's possible. It makes no sense. > > It makes enough sense in this case. > For example when you want to execute a loop in parallel, then you > extract the loop into a procedure. With a local procedure you can > keep the variables, which would make the process quite easy. If you > can not use a local procedure, then you must define a record and > move the local variables there. > Of course nested local procedures creates a whole bunch of > problems, so maybe the record approach is much safer. > Maybe the extract procedure tool can be extended to do some of the > monotone work automatically. > I will explain the process in more detail on the wiki. You can create a thread call for local procedures, it needs some hacking though: no type checking is possible, you've to work with pointers and pass the context explicitly.

Can you give an example?

Mattias

Reply by email

Mattias Gaertner
to Florian Klaempfl: See http://www.freepascal.org/docs-html/rtl/objects/callpointerlocal.html and e.g. the…
Show quoted text 15 lines
Mattias Gaertner schrieb: >> You can create a thread call for local procedures, it needs some >> hacking though: no type checking is possible, you've to work with >> pointers and pass the context explicitly. > > Can you give an example? See http://www.freepascal.org/docs-html/rtl/objects/callpointerlocal.html and e.g. the comment of Jonas: (0014130) Jonas Maebe (manager) 2007-08-13 15:02 at http://bugs.freepascal.org/view.php?id=9432

Cool. It really works, at least under linux 32bit. I wonder on what other platforms this will work.

I added it to mtprocs. Now you can do:

procedure DoSomething(Value: PtrInt);
var
  p: array[1..2] of Pointer;
  procedure SubProc(Index: PtrInt; Data: Pointer; Item: TMultiThreadProcItem);
  begin
    p[Index]:=Pointer(Value);
  end;
var
  i: Integer;
begin
  ProcThreadPool.DoParallelLocalProc(@SubProc,1,2);
end;

This avoids splitting and produces much more readable code.

Mattias

Reply by email

Florian Klaempfl
to Mattias Gaertner
Show quoted text 19 lines
On Wed, 19 Aug 2009 20:52:41 +0200 Florian Klaempfl wrote: > Mattias Gaertner schrieb: >>> You can create a thread call for local procedures, it needs some >>> hacking though: no type checking is possible, you've to work with >>> pointers and pass the context explicitly. >> Can you give an example? > See > http://www.freepascal.org/docs-html/rtl/objects/callpointerlocal.html > > and e.g. the comment of Jonas: > (0014130) > Jonas Maebe (manager) > 2007-08-13 15:02 > at http://bugs.freepascal.org/view.php?id=9432 Cool. It really works, at least under linux 32bit. I wonder on what other platforms this will work.

objects.pp of FPC uses the same trick (see
http://svn.freepascal.org/cgi-bin/viewvc.cgi/trunk/rtl/inc/objects.pp?revision=7964&view=markup around line 790) so it can be considered as officially supported and should work on most platforms.

Reply by email