digitalmars.D - scoped allocations
- Namespace (142/142) Nov 26 2013 First of all: I apologize for my bad english.
- Namespace (2/5) Nov 26 2013 Should be "[...] of unknown lengths at compile time".
- Andrea Fontana (4/9) Nov 27 2013 If you call it something other than "Temp" maybe it sounds better.
- =?UTF-8?B?U8O2bmtlIEx1ZHdpZw==?= (3/17) Nov 27 2013 + (I think that) std.container.Array does exactly the desired thing
- Namespace (11/23) Nov 27 2013 It was just an example, but you're right. But even auto arr =
- Denis Shelomovskij (9/12) Nov 28 2013 You can use `unstd.memory.allocation.tempAlloc` [1]. Also there is
- Namespace (34/47) Nov 28 2013 Currently I use something like:
First of all: I apologize for my bad english. In the last few weeks I searched for a way to allocate nicely temporary buffer of unknown lengths. Since D has no VLA's like C (and alloca works only partial for some strange reason: https://d.puremagic.com/issues/show_bug.cgi?id=3753), malloc / free was obiously the solution, but you have only two choices: 1. Allocate them (and maybe slice them) and free the ptr at the end of the scope (or use scope(exit)). But: Make sure that your array has not been taken over by the GC, because you made a mistake [1]. Example: ---- int* ptr = .malloc(N * int.sizeof); /// N is a runtime lengths int[] arr = ptr[0 .. N]; /// optional slice scope(exit) .free(ptr); // or more dangerous: free(arr.ptr); ---- Fail example: ---- int[] arr = (cast(T*) .malloc(N * int.sizeof))[0 .. N]; arr ~= 42; /// <-- [1] scope(exit) .free(arr.ptr); /* * Because you don't thought about that 'arr' is a full filled array and nothing you can append to, * the GC takes over the memory and you don't have a chance to get the right C pointer to free your C memory: memory leak [A -nogc flag would maybe help here] */ ---- 2. Use a struct. ---- struct Temp(T) { T* ptr; alias ptr this; this(size_t N) { this.arr = cast(T*) .malloc(N * T.sizeof); } ~this() { .free(this.ptr); } } Temp!int arr = Temp!int(512); /// arr is destroyed at the end of the scope ---- But that does not look very nice (especially because Temp!int does not indicate that it holds an array). Something like: ---- int[] arr = new int[512]; ---- Looks nicer and more intuitive. But: it is controlled by the GC. If you want to destroy it, you have to call GC.free manually. So we have the same problems/options to destroy it as with malloc/free. During the std.allocator thread I had made the suggestion to use this allocators for such temporary arrays (See also Andrej Mitrovic post: http://forum.dlang.org/thread/l4btsk$5u8$1 digitalmars.com?page=2#post-mailman.2478.1382651916.1719.digitalmars-d:40puremagic.com) For example: ---- Mallocator m; with (m) { int[] arr; arr ~= 42; /// use Mallocator m for memory allocation [Question is: when it is freed? At the end of the scope? Maybe we need a (Temp|Scope)Alloc] } ---- Or, even better. ---- with (Mallocator) { int[] arr; arr ~= 42; /// use Mallocator for memory allocation [Same question] } ---- Yet another idea of mine was: ---- int[] arr; arr.use(Mallocator); ---- Or something better: "use" blocks: ---- use (Mallocator) { int[] arr; } arr ~= 42; /// use Mallocator for memory allocation [Same question] ---- But both would bring the introduction of a new keywords with them. Over the last few days I had a few other ideas, besides the nice stuff from std.allocator. One of them was to use scope: ---- scope int[] arr = new int[42]; /// arr is freed at the end of the scope ---- The compiler could rewrite this e.g. with: ---- struct scoped(A : T[], T) { T[] arr; ~this() { GC.free(arr.ptr); } } scoped!(int[]) arr = new int[42]; /// arr is freed as far as scoped's DTor is called. ---- In this case we have no need to introduce a new keyword: scope is already there. Or, to use UDA's (but they must be improved): ---- struct temp { void* ptr; ~this() { GC.free(this.ptr); } } temp int[] arr = new int[42]; /// arr is freed as far as temp's DTor is called ( -> if temp leaves the scope) ---- The code above would be simply rewritten to: ---- int[] arr = new int[42]; temp __udatmp = temp(arr.ptr); /// temp's DTor free the whole array [Need compiler magic] ---- Another suggestion would be DIP 46 (http://wiki.dlang.org/DIP46) with a few improvements: ---- gc_push(Mallocator); int[] arr; arr ~= 42; gc_pop(); /// arr is freed (maybe it would make sense if gc_pop would be automatically inserted at the end of the scope). ---- That's it so far. Any thoughts/further suggestions?
Nov 26 2013
On Tuesday, 26 November 2013 at 23:33:59 UTC, Namespace wrote:First of all: I apologize for my bad english. In the last few weeks I searched for a way to allocate nicely temporary buffer of unknown lengths.Should be "[...] of unknown lengths at compile time".
Nov 26 2013
On Tuesday, 26 November 2013 at 23:33:59 UTC, Namespace wrote:Temp!int arr = Temp!int(512); /// arr is destroyed at the end of the scope ---- But that does not look very nice (especially because Temp!int does not indicate that it holds an array).If you call it something other than "Temp" maybe it sounds better. auto arr = ScopedArray!int(512); Makes sense for me.
Nov 27 2013
Am 27.11.2013 09:54, schrieb Andrea Fontana:On Tuesday, 26 November 2013 at 23:33:59 UTC, Namespace wrote:+ (I think that) std.container.Array does exactly the desired thing (haven't used it so far).Temp!int arr = Temp!int(512); /// arr is destroyed at the end of the scope ---- But that does not look very nice (especially because Temp!int does not indicate that it holds an array).If you call it something other than "Temp" maybe it sounds better. auto arr = ScopedArray!int(512); Makes sense for me.
Nov 27 2013
On Wednesday, 27 November 2013 at 08:55:01 UTC, Andrea Fontana wrote:On Tuesday, 26 November 2013 at 23:33:59 UTC, Namespace wrote:It was just an example, but you're right. But even auto arr = ScopedArray!int(512); doesn't look very nice. Some syntax sugar like e.g. scope int[] arr = new int[512]; would be much nicer + more intuitive. And with some of the other examples, like the DIP 46 variant, D could keep his promise to work even without a GC. Currently you can disable it, but then you have very little benefit of the most basic things, such as strings, arrays, etc. With an exchangeable GC this would be different.Temp!int arr = Temp!int(512); /// arr is destroyed at the end of the scope ---- But that does not look very nice (especially because Temp!int does not indicate that it holds an array).If you call it something other than "Temp" maybe it sounds better. auto arr = ScopedArray!int(512); Makes sense for me.
Nov 27 2013
27.11.2013 3:33, Namespace пишет:First of all: I apologize for my bad english. In the last few weeks I searched for a way to allocate nicely temporary buffer of unknown lengths.You can use `unstd.memory.allocation.tempAlloc` [1]. Also there is `unstd.c.string.tempCString` [2] for common case of temporary C strings. [1] http://denis-sh.bitbucket.org/unstandard/unstd.memory.allocation.html#tempAlloc [2] http://denis-sh.bitbucket.org/unstandard/unstd.c.string.html#tempCString -- Денис В. Шеломовский Denis V. Shelomovskij
Nov 28 2013
On Thursday, 28 November 2013 at 17:12:01 UTC, Denis Shelomovskij wrote:27.11.2013 3:33, Namespace пишет:Currently I use something like: ---- import std.stdio; import core.memory : GC; struct scoped(A : T[], T) { T[] arr; this(T[] arr) { this.arr = arr; writefln("Allocate %d %s's (ptr = %x)", arr.length, T.stringof, arr.ptr); } alias arr this; disable this(this); ~this() { writefln("Deallocate %d %s's (ptr = %x)", this.arr.length, T.stringof, this.arr.ptr); version(none) { GC.free(this.arr.ptr); } else { delete this.arr; } GC.minimize(); this.arr = null; } } void main() { scoped!(int[]) bytes = new int[100_000]; } ---- It's the nearest to scope int[] bytes = new int[100_000]; I could find.First of all: I apologize for my bad english. In the last few weeks I searched for a way to allocate nicely temporary buffer of unknown lengths.You can use `unstd.memory.allocation.tempAlloc` [1]. Also there is `unstd.c.string.tempCString` [2] for common case of temporary C strings. [1] http://denis-sh.bitbucket.org/unstandard/unstd.memory.allocation.html#tempAlloc [2] http://denis-sh.bitbucket.org/unstandard/unstd.c.string.html#tempCString
Nov 28 2013