Manually allocate delegate?

Tofu Ninja via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Sat Nov 21 00:04:22 PST 2015


On Saturday, 21 November 2015 at 00:30:45 UTC, userABCabc123 
wrote:
> 
> Yes:
>
> ========================
> class Foo
> {
>     void bar(){writeln(__PRETTY_FUNCTION__);}
> }
>
> auto uncollectedDelegate(T, string name)(ref T t)
> {
>     import std.experimental.allocator.mallocator;
>     struct Dg{void* ptr, funcptr;}
>
>     void* funcptr = &__traits(getMember, T, name);
>     void* ptr = cast(void*)t;
>
>     Dg* dg = cast(Dg*) Mallocator.instance.allocate(Dg.sizeof);
>     dg.ptr = ptr;
>     dg.funcptr = funcptr;
>     return dg;
> }
>
> void main(string[] args)
> {
>     Foo foo = new Foo;
>     auto dg = uncollectedDelegate!(Foo, "bar")(foo);
>     auto tdg = cast(void delegate()*) dg;
>     (*tdg)();
> }
> ========================
>
> with just a type __traits(getMember,...) on a delegate will 
> only return the function address in the process image. so 
> without the context ptr, just like a static or a global 
> function. Later you set the context by hand, using a pointer to 
> an instance.

I think you are misunderstanding a bit what my original question 
was. The delegate it self is not gc allocated. The delegate it 
self is just 2 pointers(a function pointer and a context 
pointer), they are simply stack allocated. I am not woried about 
allocating that bit. What I am worried about allocating is the 
context, and primarily the context for nested functions(often 
called a closure).

For delegates to member functions, the context pointer is always 
just a pointer to the object that you pulled the delegate off of. 
To avoid gc allocating the context there, all you need to do is 
just don't gc allocate the object. Simple. In your example the 
context is still gc allocated with new Foo;. You actually added 
in another allocation on top of that with the mallocator. You now 
allocate the delegate it self, which normally can just be stack 
allocated.

The problem that I was concerned about was the case of nested 
function delegates. For delegates to nested functions that need 
to generate a closure, the allocation of the closure is 
implicitly done and done with the gc. As far as I can tell, there 
is no way to know anything about that closure, not its size, 
layout, contents, no way to manually allocate it.

Example:
auto foo(int x)
{
    int bar(){ return x; }
    return &bar; // <-- implicitly allocates a closure with the gc
}


More information about the Digitalmars-d-learn mailing list