On Wed, 21 Sep 2011 18:32:49 +0200, deadalnix <deadal...@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

Reply via email to