I implemented delegates in D
BBasile via Digitalmars-d
digitalmars-d at puremagic.com
Thu Jun 9 16:53:33 PDT 2016
On Thursday, 9 June 2016 at 21:02:26 UTC, maik klein wrote:
> I am currently writing a task system and I have this case where
> I want to send a delegate to a different thread but this
> delegate also captures a variable. I use this to implement a
> "future".
>
> Now as far as I know this delegate will allocate GC memory and
> I just wanted to avoid that, just for fun.
>
> Here is the code https://dpaste.dzfl.pl/cd77fce99a5b
>
> I have only worked on it a couple of hours and I am sure there
> are many problems with it.
>
> Basically the idea is that you can use normal lambda syntax. If
> you want a function that returns and int and takes an int, you
> can write it like this:
>
> (int i) => i
>
> If you want a function that returns an int, takes an int, but
> also captures and int you would write it like this
>
> (int i, int captured) => i + captured
>
> But you also have to declare the base function type without the
> captured variables beforehand.
>
> Fn!(FnType!(int, int), (int i, int captured) => i +
> captured)(42);
>
> That is how I know what the captured variables are.
>
> The only part that is currently missing are polymorphic
> delegates. They are not too useful if I can't pack them into
> the same array.
>
> I guess I have to do this with classes/interfaces.
>
> Thoughts?
>
> Has this been done before?
What you have here is more functor, to the extent that you can
memorize the parameters. The problem is that it's not compatible
with the delegates as defined in the language.
Actual D delegates get collected when we take the address and the
context of a member function with "&". To allocate the delegate
itself in the non GC heap is easy (with a struct that contains
two pointers).
Your message has motivated me to make this, thanks to a union
true nogc delegates are possible:
=========================================
module runnable;
union Delegate(FT)
{
// delegate layout as defined in the D ABI
struct DgMembers
{
void* ptr;
FT funcptr;
}
DgMembers members;
// the 2nd member is "true" D delegate type
import std.array: replace;
mixin("alias DT = " ~ FT.stringof.replace("function",
"delegate") ~ ";");
DT dg;
}
void main() @nogc
{
static struct Foo
{
@nogc string delegate() test;
@nogc string source() {return "test";}
}
import std.experimental.allocator.mallocator;
import std.experimental.allocator;
Foo foo;
alias DelegateT = Delegate!(typeof(&Foo.source));
// &Foo.source takes the static address, i.e in the data
segment
DelegateT* dg = make!DelegateT(Mallocator.instance);
dg.members.ptr = &foo;
dg.members.funcptr = &Foo.source;
foo.test = dg.dg;
assert(foo.test() == "test");
}
=========================================
Here you have a true D delegate that's conform with the language.
More information about the Digitalmars-d
mailing list