www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - safe nogc memory allocation

reply =?UTF-8?B?Ik5vcmRsw7Z3Ig==?= <per.nordlow gmail.com> writes:
I would like my radix sort function radixSortImpl() at

https://github.com/nordlow/justd/blob/master/intsort.d

to not use the GC. However, when I tag with  nogc I get the error:

intsort.d(195,47): Error:  nogc function 
'isort.radixSortImpl!(byte[], "a", false).radixSortImpl' cannot 
call non- nogc function 'std.array.uninitializedArray!(byte[], 
immutable(ulong)).uninitializedArray'

Is there an alternative to

std.array: uninitializedArray
Elem[] y = uninitializedArray!(Elem[])(n);

that neither use the GC and nor preinitialize the data?

Could the recent DMD pull optimization to scope here

https://github.com/D-Programming-Language/dmd/commit/abc7033bf9cf7f7224a47e45096efc48a21b5ab8

be used?

/Per
May 28 2014
parent reply "monarch_dodra" <monarchdodra gmail.com> writes:
On Wednesday, 28 May 2014 at 19:43:53 UTC, Nordlöw wrote:
 I would like my radix sort function radixSortImpl() at

 https://github.com/nordlow/justd/blob/master/intsort.d

 to not use the GC. However, when I tag with  nogc I get the 
 error:

 intsort.d(195,47): Error:  nogc function 
 'isort.radixSortImpl!(byte[], "a", false).radixSortImpl' cannot 
 call non- nogc function 'std.array.uninitializedArray!(byte[], 
 immutable(ulong)).uninitializedArray'

 Is there an alternative to

 std.array: uninitializedArray
 Elem[] y = uninitializedArray!(Elem[])(n);

 that neither use the GC and nor preinitialize the data?
malloc? There's no wrapper around it though, like there is for uninitializedArray. Keep in mind though that currently, you have to choose either of "pure" (GC) or "nogc" (malloc) if you need dynamic allocation :/
 Could the recent DMD pull optimization to scope here

 https://github.com/D-Programming-Language/dmd/commit/abc7033bf9cf7f7224a47e45096efc48a21b5ab8

 be used?

 /Per
I don't think scope can be used to create a dynamic array on the stack. I think it requires the object's type be statically known. I could be wrong though. If you know "n" has a max size, you could you create a fixed size array, or attempt a "alloca" array?
May 28 2014
next sibling parent reply "safety0ff" <safety0ff.dev gmail.com> writes:
I think malloc isn't  safe and alloca doesn't work if your 
function can throw.
May 28 2014
parent "monarch_dodra" <monarchdodra gmail.com> writes:
On Wednesday, 28 May 2014 at 20:00:17 UTC, safety0ff wrote:
 I think malloc isn't  safe and alloca doesn't work if your 
 function can throw.
Yeah, uninitializedArray is also *only* trusted if the type in question has no indirections. I've heard of several bugs with alloca, but I don't know the exact list.
May 28 2014
prev sibling parent reply =?UTF-8?B?Ik5vcmRsw7Z3Ig==?= <per.nordlow gmail.com> writes:
 malloc? There's no wrapper around it though, like there is for 
 uninitializedArray.
Is the fact that malloc() can't be pure when new is a limitiation in the type system? Do we need a yet another code tag for this? /Per
May 28 2014
parent reply "Dicebot" <public dicebot.lv> writes:
On Wednesday, 28 May 2014 at 20:51:08 UTC, Nordlöw wrote:
 malloc? There's no wrapper around it though, like there is for 
 uninitializedArray.
Is the fact that malloc() can't be pure when new is a limitiation in the type system? Do we need a yet another code tag for this? /Per
It is also because `malloc` can return null when out of memory and `new` will throw an Error. Wrapper around `malloc` that throws `OutOfMemoryError` on null can be considered of same purity class as `new`.
May 28 2014
next sibling parent reply "bearophile" <bearophileHUGS lycos.com> writes:
Dicebot:

 It is also because `malloc` can return null when out of memory 
 and `new` will throw an Error. Wrapper around `malloc` that 
 throws `OutOfMemoryError` on null can be considered of same 
 purity class as `new`.
One wrapper should have a template argument to specify the type of the items, to avoid the need of a cast. And instead of throwing an error it could also return a Nullable (the sizeof of such Nullable is the same as a pointer). Nullable!(Titem*, null) talloc(Titem)(in size_t nItems); Bye, bearophile
May 28 2014
parent "Dicebot" <public dicebot.lv> writes:
On Wednesday, 28 May 2014 at 21:09:26 UTC, bearophile wrote:
 Dicebot:

 It is also because `malloc` can return null when out of memory 
 and `new` will throw an Error. Wrapper around `malloc` that 
 throws `OutOfMemoryError` on null can be considered of same 
 purity class as `new`.
One wrapper should have a template argument to specify the type of the items, to avoid the need of a cast. And instead of throwing an error it could also return a Nullable (the sizeof of such Nullable is the same as a pointer). Nullable!(Titem*, null) talloc(Titem)(in size_t nItems); Bye, bearophile
I don't think wrapper with Nullable can be pure as it will possibly return two different object values (and not just different pointers) when called with same argument list. Throwing an Error is crucial here.
May 28 2014
prev sibling parent reply =?UTF-8?B?Ik5vcmRsw7Z3Ig==?= <per.nordlow gmail.com> writes:
 It is also because `malloc` can return null when out of memory 
 and `new` will throw an Error. Wrapper around `malloc` that 
 throws `OutOfMemoryError` on null can be considered of same 
 purity class as `new`.
Does this mean that I should write and use such a wrapper for malloc? /Per
May 28 2014
parent reply "Dicebot" <public dicebot.lv> writes:
On Wednesday, 28 May 2014 at 21:31:41 UTC, Nordlöw wrote:
 It is also because `malloc` can return null when out of memory 
 and `new` will throw an Error. Wrapper around `malloc` that 
 throws `OutOfMemoryError` on null can be considered of same 
 purity class as `new`.
Does this mean that I should write and use such a wrapper for malloc? /Per
I don't know. I believe within current language semantics even considering `new` pure is broken, there was a very recent thread discussing it in digitalmars.D group. If you can be sure that your code won't break basic sanity requirements (never comparing allocated immutable pointer identity, only pointed values) it should work fine. But I have never done it in my code and not aware of possible pitfalls.
May 28 2014
parent "safety0ff" <safety0ff.dev gmail.com> writes:
On Wednesday, 28 May 2014 at 23:57:40 UTC, Dicebot wrote:
 I believe within current language semantics even considering 
 `new` pure is broken, there was a very recent thread discussing 
 it in digitalmars.D group.

 If you can be sure that your code won't break basic sanity 
 requirements (never comparing allocated immutable pointer 
 identity, only pointed values) it should work fine. But I have 
 never done it in my code and not aware of possible pitfalls.
You also have to make sure your calls to malloc wont be considered strongly pure and memoized. e.g.: int* a = cast(int*)malloc(4); // 4 should be considered immutable int* b = cast(int*)malloc(4); // a == b if memoized // a != b otherwise (unless out of memory) Perhaps the wrapper function should take a pointer reference as a parameter (note: not immutable,) this also means that it can use type inference.
May 28 2014