digitalmars.D - Avoid GC with closures
- Iakh (20/20) May 26 2016 Functions with lambdas cannot be @nogc as far as they allocates
- bpr (23/25) May 26 2016 Counterexample:
- Iakh (7/32) May 28 2016 The problem is that delegates allocates with GC. And proposed
- Kagamin (7/13) May 27 2016 This compiles just fine and doesn't allocate:
- Iakh (3/16) May 28 2016 Yeah. It doesn't capture any context. But once it does it
- Dicebot (4/6) May 29 2016 Custom allocators are not very suitable for things like closures because
- ZombineDev (10/17) May 29 2016 Maybe an interface for a ref counting allocator (that leverages
- Iakh (3/10) May 30 2016 Yes. It's better to pass something like memory management strategy
Functions with lambdas cannot be nogc as far as they allocates closures. And the way lambdas works is completely different from C++ way. In D using lambda we define how some part of "stack" frame allocates. So in some aspect closure allocation is property of a function. So we need a way to tell compiler how to handle this part of frame. For exapmle: void g() nogc { catch scope(void); int[N] arr = [/*...*/]; arr[].sort!((a, b) => a > b); } Where "catch scope(void);" sets allocator for all lambdas. If it is void closure will be allocated on the stack. Once we will have allocators we will be able to pass them as closure handlers.
May 26 2016
On Thursday, 26 May 2016 at 18:53:35 UTC, Iakh wrote:Functions with lambdas cannot be nogc as far as they allocates closures.Counterexample: // Note that this is NOT a good way to do numerical quadrature! double integrate(scope double delegate(double x) nogc f, double lo, double hi, size_t n) nogc { double result = 0.0; double dx = (hi - lo) / n; double dx2 = dx * 0.5; for (size_t i = 1; i <= n; i++) { result += f(lo + i * dx2) * dx; } return result; } double integrate(scope double delegate(double, double) nogc f, double x0, double x1, double y0, double y1, size_t nX, size_t nY) nogc { return integrate((y) => integrate((x) => f(x,y), x0, x1, nX), y0, y1, nY); } Functions with nogc downward funarg lambdas (delegates) can be nogc. I can't parse the rest of your post, maybe I misunderstand you.
May 26 2016
On Thursday, 26 May 2016 at 21:10:30 UTC, bpr wrote:On Thursday, 26 May 2016 at 18:53:35 UTC, Iakh wrote:Didn't know about "scope". It solves problem partially.Functions with lambdas cannot be nogc as far as they allocates closures.Counterexample: // Note that this is NOT a good way to do numerical quadrature! double integrate(scope double delegate(double x) nogc f, double lo, double hi, size_t n) nogc { double result = 0.0; double dx = (hi - lo) / n; double dx2 = dx * 0.5; for (size_t i = 1; i <= n; i++) { result += f(lo + i * dx2) * dx; } return result; } double integrate(scope double delegate(double, double) nogc f, double x0, double x1, double y0, double y1, size_t nX, size_t nY) nogc { return integrate((y) => integrate((x) => f(x,y), x0, x1, nX), y0, y1, nY); } Functions with nogc downward funarg lambdas (delegates) can be nogc.I can't parse the rest of your post, maybe I misunderstand you.The problem is that delegates allocates with GC. And proposed solution it to tell to the compiler what to use instead of GC heap. It is not only about scoped. It is mostly about memory allocated for closure.
May 28 2016
On Thursday, 26 May 2016 at 18:53:35 UTC, Iakh wrote:void g() nogc { catch scope(void); int[N] arr = [/*...*/]; arr[].sort!((a, b) => a > b); }This compiles just fine and doesn't allocate: void g() nogc { int[2] arr = [5,4]; arr[].sort!((a, b) => a > b); }
May 27 2016
On Friday, 27 May 2016 at 10:34:38 UTC, Kagamin wrote:On Thursday, 26 May 2016 at 18:53:35 UTC, Iakh wrote:Yeah. It doesn't capture any context. But once it does it would be an error.void g() nogc { catch scope(void); int[N] arr = [/*...*/]; arr[].sort!((a, b) => a > b); }This compiles just fine and doesn't allocate: void g() nogc { int[2] arr = [5,4]; arr[].sort!((a, b) => a > b); }
May 28 2016
On 05/28/2016 09:58 PM, Iakh wrote:Yeah. It doesn't capture any context. But once it does it would be an error.Custom allocators are not very suitable for things like closures because of undefined lifetime. Even if it was allowed to replace allocator, you would be limited to either GC or RC based one anyway to keep things safe.
May 29 2016
On Sunday, 29 May 2016 at 11:16:57 UTC, Dicebot wrote:On 05/28/2016 09:58 PM, Iakh wrote:Maybe an interface for a ref counting allocator (that leverages Andrei's idea to use AffixAllocator's interface for storing RC metadata) can be used, provided that the interface is in druntime and the compiler knows how to use it. BTW, AffixAllocator's interface abstracts whether the metadata is stored next to the allocation or in a separate area, but the current design needs to be fixed w.r.t to shared-ness, because it breaks the type system: http://forum.dlang.org/post/bscksxwxuvzefymbiemg forum.dlang.orgYeah. It doesn't capture any context. But once it does it would be an error.Custom allocators are not very suitable for things like closures because of undefined lifetime. Even if it was allowed to replace allocator, you would be limited to either GC or RC based one anyway to keep things safe.
May 29 2016
On Sunday, 29 May 2016 at 11:16:57 UTC, Dicebot wrote:On 05/28/2016 09:58 PM, Iakh wrote:Yes. It's better to pass something like memory management strategy instead of just allocator like rc ptr or uniquePtrYeah. It doesn't capture any context. But once it does it would be an error.Custom allocators are not very suitable for things like closures because of undefined lifetime. Even if it was allowed to replace allocator, you would be limited to either GC or RC based one anyway to keep things safe.
May 30 2016