Heap fucntion calls

Simen Kjaeraas simen.kjaras at gmail.com
Wed Sep 21 10:56:33 PDT 2011


On Wed, 21 Sep 2011 18:32:49 +0200, deadalnix <deadalnix at gmail.com> wrote:

> D has a wonderfull feature named delegate. Delegate can acess local  
> data, thus would be dangerous if thoses data were on the stack. For what  
> I understand, when a delegate can access the local data of a function,  
> those data are set on the heap instead of the stack, resulting on a  
> slower function call, but on a safe delegate behaviour.
>
> I'm wondering what's going on behind the hood when such a function is  
> called. are the parameter passed to the function on the stack and the  
> copied on the heap ? In such a situation, data are copied two times.  
> Will a postblit constructor be called two times ? Or is the function  
> taggued as « heap function » and then only the pointer is passed in the  
> function call ?

It's the latter. A delegate is simply a function pointer/context pointer
pair, and the exact same thing is used for pointers to member functions
as for lexical closures.


> Secondly, how does thing like scope(exit) are handled in such a case ?  
> When the constext is collected by the GC ? When the function ends it's  
> execution ? The try {} finally {} analogy suggest the second one, but  
> this is definitively not an exit of the scope, the scope being still  
> accsible throw the delegate.

scope(exit) foo();
// stuff

is simply rewritten as

try {
     // stuff
}
finally {
     foo();
}

Hence, again the latter is the case. In this case:

string delegate() foo() {
     string s = "initialized";
     scope( exit ) s = "destroyed";
     auto ret = (){return s;}
     return ret;
}

void bar() {
     assert(foo()() == "destroyed");
}

The assert passes.


> Those are exemple but more generaly, my question isn't about thoses  
> exemples. It is about what really is going on. Let's say, what would be  
> the C translation of such a function call or somethung similar.

void foo() {
     int x = 5;
     auto dg = () {x = 4;}
     dg();
}

is roughly equivalent to:

typedef struct foo_dg_1_delegate {
     void (*funcptr)(struct foo_dg_1_context*);
     void* ptr;
};

typedef struct foo_dg_1_context {
     int x;
};

void foo_dg_1(struct foo_dg_1_context* ctx) {
     ctx->x = 4;
}

void foo(void) {
     struct foo_dg_1_delegate dg;
     struct foo_dg_1_context* ctx = (struct  
foo_dg_1_context*)malloc(sizeof(struct foo_dg_1_context));
     dg.funcptr = &foo_dg_1;
     dg.ptr = ctx;
     ctx->x = 5;
     dg.funcptr(dg.ptr);
}

-- 
   Simen


More information about the Digitalmars-d-learn mailing list