[fpc-devel] Blocks support

Sven Barth pascaldragon at googlemail.com
Wed Jul 16 21:19:30 CEST 2014


On 16.07.2014 18:45, Jonas Maebe wrote:
>> > "Capturing local state" means that the block gets a copy or a
>> > reference to a variable that is local to the context where it is
>> > instantiated (instantiated in our case means "the place where we assign
>> > the address of a procedure/function to an "is block" variable).
>>
>> Delphi is a bit confusing here: each anonymous function instantiated in
>> a function shares a reference to a copy of the variable... :/ (at least
>> if I remember correctly)
>
> While working on this, I didn't realise at all that Delphi had to have
> rules already regarding capturing local variables for its own anonymous
> method support. I've now read what it does and it indeed always has the
> same behaviour as variables declared as "__block" in C blocks. So I
> would propose to use this behaviour for consistency and leave out
> support for capturing local variables as const/snapshot values.

It would however be good if we'd at least have support for 
const/snapshot values so that we could easily add it once we come up 
with a suitable syntax.

> Similarly, they also already have a syntax for "block type" variables
> (var proc: reference to function(l: longint): longint;"), so I propose
> to use that one as well instead of my "is block". Possibly with "cdecl;"
> at the end to differentiate between C blocks and whatever the FPC
> implementation will be, since some people will probably want to
> reimplement the blocks runtime, or something similar, in Pascal
> (definitely not me).

I'm not that sure whether using the same syntax is a good idea... people 
want to have Delphi compatible anonymous functions which are basically 
reference counted interfaces instead of records...

>>  > However:
>>  >
>>  > * Methods of Pascal classes
>>  >
>>  > As explained above, the "self" parameter has to be captured by the
>> > block in this case. If nothing special is done, then this self pointer
>> > will be treated like a regular pointer and you will be responsible for
>> > freeing it. However, in case a block is passed to an asynchronous
>> > routine, the question will most likely be "when is it safe to free that
>> > instance", and I'm not sure how to do that. The blocks runtime supports
>> > adding code that will be executed when a block is copied and when it is
>> > freed, but since Pascal classes don't have an internal reference count,
>> > there's not much we can do automatically here.
>> >
>> > There is a way to make a Pascal class reference counted, by making it
>> > a descendent of TInterfacedObject (or more generally, by implementing
>> > the IUnknown interface) and only handling it via interface
>> variables, so
>> > maybe the compiler could generate special code in that case to make
>> sure
>> > that the block does update the reference counts in that case. That way,
>> > you can have a choice between manual and automatic reference
>> counting. I
>> > still have to think this through to determine whether this reference
>> > counted approach is in fact feasible to implement.
>>
>> We would need reference counting support anyway for Pascal strings and
>> arrays if we'd allow it on non-Mac OS X
>
> I don't understand this. As mentioned, there are block-specific
> callbacks that are automatically invoked whenever a block is copied or
> destroyed (which has to be performed by ABI-defined helpers). In those
> callbacks (which are compiler-generated), the compiler can put code to
> handle the reference counting of reference-counted types. The problem is
> only with non-reference-counted types such as classes.

Ah, they are block specific. That wasn't that clear to me before. 
*blush* Ok, then the compiler can generate code for the reference 
counting (which it needs to do anyway) and we just leave non-ARC classes 
be... Delphi doesn't handle them specially either.

>> And
>> interfaces and ARC classes will "simply" need that as well... For normal
>> classes I'd say that it's the responsibility of the programmer to free
>> them, but maybe we could somehow provide access to that "after use"
>> functionality you mentioned (e.g. another function that can be assigned
>> or something like that, though I don't have a good syntax idea right now)
>
> There's no callback that is called only when the last instance of a
> block is destroyed. Although I guess we could do that ourselves by
> inserting a reference count of our own as part of the "captured" data...
> The syntax could be done similar as with enumeration callbacks: provide
> a static class method with a particular name that takes an instance of
> that class as parameter and if it exists, the compiler will generate the
> cleanup call/reference counting stuff and call the method with the
> instance as parameter).

Yes, I mixed that callback stuff up a bit...

> PS: the blocks ABI and their behaviour is fairly well documented at
> http://clang.llvm.org/docs/Block-ABI-Apple.html

Thanks. :)

Regards,
Sven



More information about the fpc-devel mailing list