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.