digitalmars.D.learn - Manually allocate delegate?
- Tofu Ninja (1/1) Jul 12 2015 Is it even possible?
- ketmar (2/3) Jul 12 2015 what do you mean?=
- Tofu Ninja (5/8) Jul 12 2015 Sorry, thought the title was enough.
- Baz (20/30) Jul 12 2015 You can copy a delegate in a GC-free chunk but so far i think
- Tofu Ninja (26/47) Jul 12 2015 That is not manually allocating a delegate context, and & in that
- Baz (3/30) Jul 12 2015 At least now your Question is clearer and understandable...but
- Tofu Ninja (2/4) Jul 12 2015 Sorry if I came off as rude, didn't mean to... >.>
- ketmar (4/15) Jul 12 2015 nope. there is no way to overload context allocation function, afaik. at...
- Tofu Ninja (6/22) Jul 12 2015 Hmmmmm.... with allocators being added, this seems like something
- Adam D. Ruppe (2/5) Jul 12 2015 _d_allocmemory
- ketmar (3/9) Jul 13 2015 tnx. if i note that i don't know which function does something, there=20
- userABCabc123 (30/40) Nov 20 2015 Yes:
- Tofu Ninja (29/60) Nov 21 2015 I think you are misunderstanding a bit what my original question
- Adam D. Ruppe (49/50) Jul 12 2015 Yes, though you need to use an entirely different approach for
- Tofu Ninja (3/8) Jul 13 2015 This seems like a reasonable solution, even though it's not
- Jack Applegame (28/29) Nov 21 2015 You can use function instead delegate, and bind captured
On Sun, 12 Jul 2015 08:38:00 +0000, Tofu Ninja wrote:Is it even possible?what do you mean?=
Jul 12 2015
On Sunday, 12 July 2015 at 08:47:37 UTC, ketmar wrote:On Sun, 12 Jul 2015 08:38:00 +0000, Tofu Ninja wrote:Sorry, thought the title was enough. The context for a delegate(assuming not a method delegate) is allocated by the GC. Is there any way to allocate the context manually.Is it even possible?what do you mean?
Jul 12 2015
On Sunday, 12 July 2015 at 09:03:25 UTC, Tofu Ninja wrote:On Sunday, 12 July 2015 at 08:47:37 UTC, ketmar wrote:You can copy a delegate in a GC-free chunk but so far i think that the simple fact to get a delegate with "&" will allocate from the GC. By the way i'd be interested to see the runtime function that creates a delegate. i see nothing in druntime. --- import std.stdio, std.c.stdlib, std.c.string; class Foo { void bar(){writeln("bang");} } void main(string[] args) { auto foo = new Foo; auto dg0 = &foo.bar; auto dg1 = *cast(void delegate()*) malloc(size_t.sizeof * 2); memmove(cast(void*)&dg1, cast(void*)&dg0, size_t.sizeof * 2); dg1(); } ---On Sun, 12 Jul 2015 08:38:00 +0000, Tofu Ninja wrote:Sorry, thought the title was enough. The context for a delegate(assuming not a method delegate) is allocated by the GC. Is there any way to allocate the context manually.Is it even possible?what do you mean?
Jul 12 2015
On Sunday, 12 July 2015 at 10:19:02 UTC, Baz wrote:You can copy a delegate in a GC-free chunk but so far i think that the simple fact to get a delegate with "&" will allocate from the GC. By the way i'd be interested to see the runtime function that creates a delegate. i see nothing in druntime. --- import std.stdio, std.c.stdlib, std.c.string; class Foo { void bar(){writeln("bang");} } void main(string[] args) { auto foo = new Foo; auto dg0 = &foo.bar; auto dg1 = *cast(void delegate()*) malloc(size_t.sizeof * 2); memmove(cast(void*)&dg1, cast(void*)&dg0, size_t.sizeof * 2); dg1(); } ---That is not manually allocating a delegate context, and & in that instance does not even allocate. For delegates to class methods, the context is just the "this" pointer of the object, so the context in that code is just foo, which you still allocated on the gc. The delegate itself (the function pointer and the context pointer) is just allocated on the stack. What I am talking about is the context that implicitly gets allocated when you make a delegate to a nested function. void main(string[] args) { auto d = bar(); d(); } auto bar() { int x = 5; void foo() { writeln(x); } auto d = &foo; // <-- allocates return d; }
Jul 12 2015
On Sunday, 12 July 2015 at 10:39:44 UTC, Tofu Ninja wrote:On Sunday, 12 July 2015 at 10:19:02 UTC, Baz wrote:At least now your Question is clearer and understandable...but sorry goodbye. I don't feel good vibes here. See ya ^^.[...]That is not manually allocating a delegate context, and & in that instance does not even allocate. For delegates to class methods, the context is just the "this" pointer of the object, so the context in that code is just foo, which you still allocated on the gc. The delegate itself (the function pointer and the context pointer) is just allocated on the stack. What I am talking about is the context that implicitly gets allocated when you make a delegate to a nested function. void main(string[] args) { auto d = bar(); d(); } auto bar() { int x = 5; void foo() { writeln(x); } auto d = &foo; // <-- allocates return d; }
Jul 12 2015
On Sunday, 12 July 2015 at 11:22:41 UTC, Baz wrote:At least now your Question is clearer and understandable...but sorry goodbye. I don't feel good vibes here. See ya ^^.Sorry if I came off as rude, didn't mean to... >.>
Jul 12 2015
On Sun, 12 Jul 2015 09:03:24 +0000, Tofu Ninja wrote:On Sunday, 12 July 2015 at 08:47:37 UTC, ketmar wrote:nope. there is no way to overload context allocation function, afaik. at=20 least without patching druntime, and i still don't know what one have to=20 patch. ;-)=On Sun, 12 Jul 2015 08:38:00 +0000, Tofu Ninja wrote:=20 Sorry, thought the title was enough. =20 The context for a delegate(assuming not a method delegate) is allocated by the GC. Is there any way to allocate the context manually.Is it even possible?what do you mean?
Jul 12 2015
On Sunday, 12 July 2015 at 11:42:09 UTC, ketmar wrote:On Sun, 12 Jul 2015 09:03:24 +0000, Tofu Ninja wrote:Hmmmmm.... with allocators being added, this seems like something that needs to be fixed. Maybe when allocators do get added then the implicit allocations for the context could be done with the global allocator, that and other implicit allocations like array resizing. Guess I will just wait and see how it plays out.On Sunday, 12 July 2015 at 08:47:37 UTC, ketmar wrote:nope. there is no way to overload context allocation function, afaik. at least without patching druntime, and i still don't know what one have to patch. ;-)On Sun, 12 Jul 2015 08:38:00 +0000, Tofu Ninja wrote:Sorry, thought the title was enough. The context for a delegate(assuming not a method delegate) is allocated by the GC. Is there any way to allocate the context manually.Is it even possible?what do you mean?
Jul 12 2015
On Sunday, 12 July 2015 at 11:42:09 UTC, ketmar wrote:nope. there is no way to overload context allocation function, afaik. at least without patching druntime, and i still don't know what one have to patch. ;-)_d_allocmemory
Jul 12 2015
On Sun, 12 Jul 2015 12:45:10 +0000, Adam D. Ruppe wrote:On Sunday, 12 July 2015 at 11:42:09 UTC, ketmar wrote:tnx. if i note that i don't know which function does something, there=20 always be someone who will point me at the function. like it! ;-)=nope. there is no way to overload context allocation function, afaik. at least without patching druntime, and i still don't know what one have to patch. ;-)=20 _d_allocmemory
Jul 13 2015
On Sunday, 12 July 2015 at 09:03:25 UTC, Tofu Ninja wrote:On Sunday, 12 July 2015 at 08:47:37 UTC, ketmar wrote:Yes: ======================== class Foo { void bar(){writeln(__PRETTY_FUNCTION__);} } auto uncollectedDelegate(T, string name)(ref T t) { import std.experimental.allocator.mallocator; struct Dg{void* ptr, funcptr;} void* funcptr = &__traits(getMember, T, name); void* ptr = cast(void*)t; Dg* dg = cast(Dg*) Mallocator.instance.allocate(Dg.sizeof); dg.ptr = ptr; dg.funcptr = funcptr; return dg; } void main(string[] args) { Foo foo = new Foo; auto dg = uncollectedDelegate!(Foo, "bar")(foo); auto tdg = cast(void delegate()*) dg; (*tdg)(); } ======================== with just a type __traits(getMember,...) on a delegate will only return the function address in the process image. so without the context ptr, just like a static or a global function. Later you set the context by hand, using a pointer to an instance.On Sun, 12 Jul 2015 08:38:00 +0000, Tofu Ninja wrote:Sorry, thought the title was enough. The context for a delegate(assuming not a method delegate) is allocated by the GC. Is there any way to allocate the context manually.Is it even possible?what do you mean?
Nov 20 2015
On Saturday, 21 November 2015 at 00:30:45 UTC, userABCabc123 wrote:Yes: ======================== class Foo { void bar(){writeln(__PRETTY_FUNCTION__);} } auto uncollectedDelegate(T, string name)(ref T t) { import std.experimental.allocator.mallocator; struct Dg{void* ptr, funcptr;} void* funcptr = &__traits(getMember, T, name); void* ptr = cast(void*)t; Dg* dg = cast(Dg*) Mallocator.instance.allocate(Dg.sizeof); dg.ptr = ptr; dg.funcptr = funcptr; return dg; } void main(string[] args) { Foo foo = new Foo; auto dg = uncollectedDelegate!(Foo, "bar")(foo); auto tdg = cast(void delegate()*) dg; (*tdg)(); } ======================== with just a type __traits(getMember,...) on a delegate will only return the function address in the process image. so without the context ptr, just like a static or a global function. Later you set the context by hand, using a pointer to an instance.I think you are misunderstanding a bit what my original question was. The delegate it self is not gc allocated. The delegate it self is just 2 pointers(a function pointer and a context pointer), they are simply stack allocated. I am not woried about allocating that bit. What I am worried about allocating is the context, and primarily the context for nested functions(often called a closure). For delegates to member functions, the context pointer is always just a pointer to the object that you pulled the delegate off of. To avoid gc allocating the context there, all you need to do is just don't gc allocate the object. Simple. In your example the context is still gc allocated with new Foo;. You actually added in another allocation on top of that with the mallocator. You now allocate the delegate it self, which normally can just be stack allocated. The problem that I was concerned about was the case of nested function delegates. For delegates to nested functions that need to generate a closure, the allocation of the closure is implicitly done and done with the gc. As far as I can tell, there is no way to know anything about that closure, not its size, layout, contents, no way to manually allocate it. Example: auto foo(int x) { int bar(){ return x; } return &bar; // <-- implicitly allocates a closure with the gc }
Nov 21 2015
On Sunday, 12 July 2015 at 08:38:01 UTC, Tofu Ninja wrote:Is it even possible?Yes, though you need to use an entirely different approach for closures: make a struct. Remember that delegates can come from local variable use or a `this` object being used and work the same way to the outside world. If it is local variables, the compiler emits the allocate calls and you have little control over it. If it comes from an object though, you have much more control: control over what is stored and control over how it is allocated. The one notable thing you do NOT control is the delegate's lifetime. Once it becomes a delegate, it is interchangable with other delegates and is likely to be mixed in with other things and the recipient has no way of knowing where it came from. That's a feature in general, but it also means they can't know if they have to free() or release_reference() it.... if you need that, you might use a custom delegate type instead of the built in one. Anyway though, just make a struct with the data you need to capture and a call method, then pass that around. Before: void foo() { int a; a = 10; // other code using a use_delegate( { a++; } ); } After: void foo() { static struct Captures { int a; void dg1() { a++; } } Captures captures; with(captures) { a = 10; // other code uing a } use_delegate(&captures.dg1); // WARNING: since captures is owned by this scope, use_delegate had better not hold on to it! But you could just as well have done Captures* captures = malloc(...) too. } So it is slightly more verbose and moves the inline delegate up to the struct (though if you got clever, you could probably change that too, like a delegate factory that takes a function and a this at the call point: dg( (_this) { _this.a++; }, captures); perhaps), but really the extra syntax overhead is small for real programs anyway. And the clarity of what is and isn't captured might be worth it.
Jul 12 2015
On Sunday, 12 July 2015 at 12:56:17 UTC, Adam D. Ruppe wrote:On Sunday, 12 July 2015 at 08:38:01 UTC, Tofu Ninja wrote:This seems like a reasonable solution, even though it's not perfect, it seems like the only valid way to do this. Tnx :)Is it even possible?Yes, though you need to use an entirely different approach for closures: make a struct. [...]
Jul 13 2015
On Sunday, 12 July 2015 at 08:38:01 UTC, Tofu Ninja wrote:Is it even possible?You can use function instead delegate, and bind captured variables as struct: http://dpaste.dzfl.pl/6e23bbcfe17f auto bind(F: R function(ARGS), R, ARGS...)(F fn, ARGS args) nogc { struct Functor { F fn; ARGS args; this(F fn_, ARGS args_) { fn = fn_; args = args_; } R opCall() { return fn(args); } } return Functor(fn, args); } import std.stdio; auto foo(int x) { static int bar(ref int x){ return x++; } return bind(&bar, x); } void main() { auto f1 = foo(5); auto f2 = foo(10); writefln("%s, %s, %s", f1(), f1(), f1()); writefln("%s, %s, %s", f2(), f2(), f2()); }
Nov 21 2015