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
}

Reply via email to