www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Delegate context pointers

reply Etienne Cimon <etcimon gmail.com> writes:
I was wondering, what exactly gets saved in a context pointer?

Is it the equivalent of [&] in C++? Is there anything copied by value? 
Is there a way to do that?
Jan 26 2014
parent reply "Jakob Ovrum" <jakobovrum gmail.com> writes:
On Monday, 27 January 2014 at 02:56:44 UTC, Etienne Cimon wrote:
 I was wondering, what exactly gets saved in a context pointer?

 Is it the equivalent of [&] in C++? Is there anything copied by 
 value? Is there a way to do that?

D delegates work differently from C++ closures. A delegate is a "fat pointer" - it is the aggregate of a function pointer and a context pointer - so the size of a delegate is always the size of two pointers, no matter what they point to. The function pointer points to a non-static nested function or a struct/class non-static member function. The context pointer points to a stack frame, a struct/class instance or a GC-heap-allocated copy of a stack frame (heap-allocated closure). The context pointer is needed so the function can refer to its upvalues, such as outer local variables for a nested function, or member fields for a member function. In all cases the calling convention is the same, which means that a delegate retrieved from a member function and one retrieved from a nested function are interchangeable as long as they have the same parameter types and return type. A copy is only made if the closure needs to be moved to the heap to avoid escaping references to stack memory beyond its lifetime. This is why it's safe to return delegates retrieved from nested functions from the outer function, even though the nested functions can refer to local variables. C++ closures work similarly to D non-static nested structs: they carry copies or references to upvalues as hidden members of their type. In C++, this type is unnamed - there is no syntax for it, it can only be referred to with type inference (such as by wrapping it with std::function). In D, nested structs are named but the scope of the name is limited - once the struct instance leaves the function, it is no longer identifiable by name, which is the reason for their moniker "voldemort type". By the way, this kind of question is best aimed at the D.learn group :)
Jan 26 2014
parent Etienne Cimon <etcimon gmail.com> writes:
On 2014-01-26 22:20, Jakob Ovrum wrote:
 C++ closures work similarly to D non-static nested structs: they carry
 copies or references to upvalues as hidden members of their type. In
 C++, this type is unnamed - there is no syntax for it, it can only be
 referred to with type inference (such as by wrapping it with
 std::function). In D, nested structs are named but the scope of the name
 is limited - once the struct instance leaves the function, it is no
 longer identifiable by name, which is the reason for their moniker
 "voldemort type".

That must be why the only way to refer to those nested struct types is by returning auto and using typeof on the variable that absorbs the value. I was mostly wondering if the return values of static structs used inside the closure would be captured within that closure. I see it's only about local variables or other outer instances, so if I add a closure to a dynamic delegate array it should allow me to pick up a new pointer returned by the static struct. I love your work on LuaD btw, I'm using it as the first step of runtime as a configuration file in a vibe.d cms/framework, and also as a vibe.d runtime page (I intend to pass over most of my convenience functions to luastate). It allows me to have configuration namespaces with comments, which is the most precious dependency of a library-based CMS. You can see an example of how I'm using it here: https://github.com/GlobecSys/w3Vibe/blob/master/examples/luadebugger/config.lua Thanks!
Jan 26 2014