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
_______________________________________________
fpc-devel maillist - [email protected]
http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel