Objective-C Interop Extensions
Nicholas Wilson
iamthewilsonator at hotmail.com
Sat Nov 16 22:47:09 UTC 2024
On Saturday, 16 November 2024 at 22:29:36 UTC, Luna wrote:
> ## Proposal
>
> Currently DLang has, in some compilers, support for ObjectiveC
> types being declared. However, modern Objective-C code is
> strongly dependent on autorelease and auto release pools.
> Without them Objective-C code leaks memory (see:
> https://developer.apple.com/documentation/quartzcore/cametallayer?language=objc).
>
> To alleviate this, clang implements the concept of an
> `@autoreleasepool` block, this block frees all Objective-C
> classes which have called `autorelease`. In the case of Metal,
> for example, a lot of internal data uses autorelease calls.
>
> The `@autoreleasepool` blocks in clang are implemented via 2
> helper functions declared in the objective-c runtime
> `libobjc.dylib` or the like in alternate runtime
> implementations.
> ```d
> extern(C) extern void* objc_autoreleasePoolPush();
> extern(C) extern void objc_autoreleasePoolPop(void*);
> ```
>
> My proposal is to add 2 new hooks to the D runtime emitted by
> the compiler as well as a new keyword, `autoreleasepool`. This
> keyword should be followed by a block.
>
> The runtime hooks should have a default implementation which do
> nothing.
> ```d
> void* _d_pool_enter() { return null; }
> void _d_pool_leave(void*) { }
> ```
>
> Whenever an `autoreleasepool` block is encountered by the
> compiler, the following code should be emitted.
> ```d
> // Note: __ctx_ptr is just a placeholder, the name of the
> variable should be unique.
> void* __ctx_ptr = _d_pool_enter();
>
> // Code goes here
>
> _d_pool_leave(__ctx_ptr);
> ```
>
> autorelease pools should additionally, on macOS, automatically
> be generated in the runtime entry point and wrap the user D
> main function, and threads created in D should also include
> pool enter and leave calls.
>
> If the D compiler links to a library defining
> `objc_autoreleasePoolPush` and `objc_autoreleasePoolPop`, the D
> runtime hooks should link against those, instead.
>
> ## Why not use NSAutoreleasePool?
>
> The `Foundation` library includes a class called
> NSAutoreleasePool, however i've found that if Objective-C's
> runtime is compiled with ARC (Automatic Reference Counting)
> support, then NSAutoreleasePool becomes no-op in some
> instances, which in turn causes memory leaks.
This would be easy to do, synchronised works in pretty much the
exact same way, but why does this need to be a compiler thing?
i.e. what does it offer that
```d
struct AutoreleasePool
{
private void* __p;
static AutoreleasePool opCall()
{
AutoreleasePool ret;
ret.__p = objc_autoreleasePoolPush();
return ret;
}
~this () { objc_autoreleasePoolPop(__p); }
}
void main()
{
auto x = AutoreleasePool();
}
```
does not?
I think I saw some of your code that used a scope delegate as
`autorelease((){ ... });` why is that not sufficient?
Given how niche this is, there had better be a very good reason
for adding it, e.g. generality with regular D code, not just
Obj-C.
More information about the dip.ideas
mailing list