www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Avoid GC with closures

reply Iakh <iaktakh gmail.com> writes:
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
next sibling parent reply bpr <brogoff gmail.com> writes:
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
parent Iakh <iaktakh gmail.com> writes:
On Thursday, 26 May 2016 at 21:10:30 UTC, bpr wrote:
 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.
Didn't know about "scope". It solves problem partially.
 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
prev sibling parent reply Kagamin <spam here.lot> writes:
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
parent reply Iakh <iaktakh gmail.com> writes:
On Friday, 27 May 2016 at 10:34:38 UTC, Kagamin wrote:
 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); }
Yeah. It doesn't capture any context. But once it does it would be an error.
May 28 2016
parent reply Dicebot <public dicebot.lv> writes:
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
next sibling parent ZombineDev <petar.p.kirov gmail.com> writes:
On Sunday, 29 May 2016 at 11:16:57 UTC, Dicebot wrote:
 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.
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.org
May 29 2016
prev sibling parent Iakh <iaktakh gmail.com> writes:
On Sunday, 29 May 2016 at 11:16:57 UTC, Dicebot wrote:
 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.
Yes. It's better to pass something like memory management strategy instead of just allocator like rc ptr or uniquePtr
May 30 2016