Re: Managing malloced memory
On Wednesday, 6 October 2021 at 18:29:34 UTC, Steven Schveighoffer wrote: ```d struct GCWrapped(T) { private T *_val; this(T* val) { _val = val; } ref T get() { return *_val; } alias get this; // automatically unwrap ~this() { free(_val); _val = null; } @disable this(this); // disable copying to avoid double-free } GCWrapped!T *wrap(T)(T *item) { return new GCWrapped!T(item); } // usage auto wrapped = wrap(cFunction()); // use wrapped wherever you need to access a T. ``` RE: @disable this(this); I noticed that std.typecons.RefCounted only works on structs if you set this line. How is that? Is RefCounted catching an exception and working around it, or does the compiler treat strcuts like GCWrapped with postblit disabled differently and use other operations for them automatically, when it would otherwise had copied it. My guess: OpAssign gets converted to a move constructor automatically
Re: Managing malloced memory
On Thursday, 7 October 2021 at 11:55:35 UTC, Steven Schveighoffer wrote: The GC is technically not required to free any blocks ever. But in general, it does. When it does free a struct, as long as you allocated with `new`, it should call the dtor. In practice when I played around with it, destructor always got called by GC. But: https://dlang.org/spec/class.html#destructors says at point 6: The garbage collector is not guaranteed to run the destructor for all unreferenced objects. Is it the same for structs or are these destructors guaranteed to be called? Would it be suitable to clean up tempfiles with GC-managed structs? Just FYI, you should reply to the posts that you quote, or at least copy the "X Y wrote" line so people understand the thread. Alright. If I want to reply to multiple people, should I post twice or quote both in the same post? The destructor is called once per copy. This is why disabling copy prevents double freeing. There are cases where the compiler avoids calling the destructor because the instance is moved. Such as returning a newly constructed item (typically referred to as an "rvalue"), or passing a newly constructed item into a parameter. The parameter will be destroyed, but the call-site constructed item will not. e.g.: ```d struct S { int x; ~this() { writeln("destructor called"); } } void foo(S s) { // destructor for s called here } S makeS(int x) { return S(x); // no destructor called here. } void main() { foo(S(1)); // no destructor called for this rvalue auto s = makeS(1); // destructor for s called here. foo(makeS(1)); // only one destructor called at the end of foo } ``` Is there any reference for exactly how these rules apply, or is this implementation defined? The [specification](https://dlang.org/spec/struct.html#struct-destructor) says that destructors are called when objects go out of scope. Your examples seem to suggest that this is untrue in some cases.
Re: Managing malloced memory
I found https://dlang.org/library/std/typecons/unique.html , which I think solves my problem by disabling copying. Thanks for the help.
Re: Managing malloced memory
Sorry for messed up post, fixed it. On Wednesday, 6 October 2021 at 18:29:34 UTC, Steven Schveighoffer wrote: You can return this thing and pass it around, and the GC will keep it alive until it's not needed. Then on collection, the value is freed. Is the gc required to call ~this() on the struct? I remember it being implementation defined. Probably doesn't matter for my usecase, just curious. Why is it a problem that it calls the dtor? I thought the whole point of refcounting is for the dtor to decrement the refcount, and free the malloc'd object only when the refcount has actually reached 0. Yes I'm afraid of double freeing. How do I pass existing struct to refcounted without the already existing copy calling destructed on function exit.
Re: Managing malloced memory
Thanks for the help. On Wednesday, 6 October 2021 at 18:29:34 UTC, Steven Schveighoffer wrote: You can return this thing and pass it around, and the GC will keep it alive until it's not needed. Then on collection, the value is freed. Is the gc required to call ~this() on the struct? I remember it being implementation defined. Probably doesn't matter for my usecase, just curious. Why is it a problem that it calls the dtor? I thought the whole point of refcounting is for the dtor to decrement the refcount, and free the malloc'd object only when the refcount has actually reached 0. Yes I'm afraid of double freeing.
Managing malloced memory
I interface to a C library that gives me a malloced object. How can I manage that pointer so that it gets freed automatically. What I've thought of so far: * scope(exit): not an option because I want to return that memory * struct wrapper: Doesn't work because if I pass it to another function, they also destroy it (sometimes). Also same problem as with scope(exit) * struct wrapped in automem/ refcounted: The struct still leaves original scope and calls the destructor
Re: Idiomatic way to write a range that tracks how much it consumes
To implement your option A you could simply use std.range.enumerate. Would something like this work? import std.algorithm.iteration : map; import std.algorithm.searching : until; import std.range : tee; size_t bytesConsumed; auto result = input.map!(a => a.yourTransformation ) .until!(stringTerminator) .tee!(a => bytesConsumed++); // bytesConsumed is automatically updated as result is consumed
Re: char array weirdness
On Monday, 28 March 2016 at 23:06:49 UTC, Anon wrote: Any because you're using ranges, *And because you're using ranges,
Re: char array weirdness
On Monday, 28 March 2016 at 22:49:28 UTC, Jack Stouffer wrote: On Monday, 28 March 2016 at 22:43:26 UTC, Anon wrote: On Monday, 28 March 2016 at 22:34:31 UTC, Jack Stouffer wrote: void main () { import std.range.primitives; char[] val = ['1', '0', 'h', '3', '6', 'm', '2', '8', 's']; pragma(msg, ElementEncodingType!(typeof(val))); pragma(msg, typeof(val.front)); } prints char dchar Why? Unicode! `char` is UTF-8, which means a character can be from 1 to 4 bytes. val.front gives a `dchar` (UTF-32), consuming those bytes and giving you a sensible value. But the value fits into a char; The compiler doesn't know that, and it isn't true in general. You could have, for example, U+3042 in your char[]. That would be encoded as three chars. It wouldn't make sense (or be correct) for val.front to yield '\xe3' (the first byte of U+3042 in UTF-8). a dchar is a waste of space. If you're processing Unicode text, you *need* to use that space. Any because you're using ranges, it is only 3 extra bytes, anyway. It isn't going to hurt on modern systems. Why on Earth would a different type be given for the front value than the type of the elements themselves? Unicode. A single char cannot hold a Unicode code point. A single dchar can.
Re: char array weirdness
On Monday, 28 March 2016 at 22:34:31 UTC, Jack Stouffer wrote: void main () { import std.range.primitives; char[] val = ['1', '0', 'h', '3', '6', 'm', '2', '8', 's']; pragma(msg, ElementEncodingType!(typeof(val))); pragma(msg, typeof(val.front)); } prints char dchar Why? Unicode! `char` is UTF-8, which means a character can be from 1 to 4 bytes. val.front gives a `dchar` (UTF-32), consuming those bytes and giving you a sensible value.
Re: Is it safe to use 'is' to compare types?
On Tuesday, 8 March 2016 at 20:26:04 UTC, Yuxuan Shui wrote: On Monday, 7 March 2016 at 16:13:45 UTC, Steven Schveighoffer wrote: On 3/4/16 4:30 PM, Yuxuan Shui wrote: On Friday, 4 March 2016 at 15:18:55 UTC, Steven Schveighoffer wrote: [...] Thanks for answering. But I still don't understand why TypeInfo would need to be allocated. Aren't typeid() just returning references to the __DxxTypeInfo___initZ symbol? You misunderstood, I meant the typeinfo *for* an allocated object, not that the typeinfo was allocated. In some cases, 2 different objects allocated from different libraries (usually DLL-land) may reference TypeInfo from different segments, even though the TypeInfo is identical. -Steve Hmm... Does that mean each DLL will have their own TypeInfo symbols for the same type? [Note: I phrase my answer in terms of Linux shared libraries (*.so) because D doesn't actually have proper Windows DLL support yet. The same would apply to DLLs, it just feels wrong describing functionality that doesn't exist.] They can, mostly due to templated types. Consider modules `common`, `foo`, and `bar` (all built as shared libraries), and `main` (built as an executable). module common; // => common.so struct List(T) { // ... } module foo; // => foo.so, links to common.so import common; List!int getList() { // ... } module bar; // => bar.so, links to common.so import common void processList(List!int a) { // ... } module main; // => main, links to foo.so, bar.so, and common.so import foo, bar; void main() { processList(getList()); } No part of List!int is instantiated in common, so no part of it is actually present in common.so. Instead, it is instantiated in foo and bar, and thus separate copies of List!int are present in foo.so and bar.so, along with TypeInfo for List!int. If you were to statically link instead (using .a or .lib files), the linker would keep only one copy of List!int and its TypeInfo, but the linker can't eliminate either of them when dealing with shared libraries. So, yes, I think the string comparison is needed, as awkward as it may seem in many circumstances.
Re: If stdout is __gshared, why does this throw / crash?
On Saturday, 5 March 2016 at 14:18:31 UTC, Atila Neves wrote: With a small number of threads, things work as intended in the code below. But with 1000, on my machine it either crashes or throws an exception: import std.stdio; import std.parallelism; import std.range; void main() { stdout = File("/dev/null", "w"); foreach(t; 1000.iota.parallel) { writeln("Oops"); } } Note that `1000.iota.parallel` does *not* run 1000 threads. `parallel` just splits the work of the range up between the worker threads (likely 2, 4, or 8, depending on your CPU). I see the effect you describe with any parallel workload. Smaller numbers in place of 1000 aren't necessarily splitting things off to additional threads, which is why smaller numbers avoid the multi-threaded problems you are encountering. I get, depending on the run, "Bad file descriptor", "Attempting to write to a closed file", or segfaults. What am I doing wrong? Atila `File` uses ref-counting internally to allow it to auto-close. `stdout` and friends are initialized in a special way such that they have a high initial ref-count. When you assign a new file to stdout, the ref count becomes one. As soon as one of your threads exits, this will cause stdout to close, producing the odd errors you are encountering on all the other threads. I would avoid reassigning `stdout` and friends in favor of using a logger or manually specifying the file to write to if I were you.
Re: Voldemort Type Construction Error
On Friday, 15 January 2016 at 14:04:50 UTC, Nordlöw wrote: What have I missed? In line 126, `static struct Result()` is a template. Either drop the parens there, or change the call on line 187 to `Result!()(haystack, needles)`.
Re: switch with enum
On Wednesday, 25 November 2015 at 21:26:09 UTC, Meta wrote: On Wednesday, 25 November 2015 at 20:47:35 UTC, anonymous wrote: Use `final switch`. Ordinary `switch`es need an explicit default case. `final switch`es have to cover all possibilities individually. Implicit default cases are not allowed. Ordinary `switch`es need an explicit default case Since when? Non-final switch without a default case was deprecated in 2011: http://dlang.org/changelog/2.054.html
Re: bigint compile time errors
On Friday, 3 July 2015 at 02:37:00 UTC, Paul D Anderson wrote: The following code fails to compile and responds with the given error message. Varying the plusTwo function doesn't work; as long as there is an arithmetic operation the error occurs. This works for me on OSX 10.10 (Yosemite) using DMD64 D Compiler v2.067.1. It seems to mean that there is no way to modify a BigInt at compile time. This seriously limits the usability of the type. enum BigInt test1 = BigInt(123); enum BigInt test2 = plusTwo(test1); public static BigInt plusTwo(in bigint n) Should be plusTwo(in BigInt n) instead. { return n + 2; } void main() { }
Re: ldc std.getopt
On Wednesday, 29 April 2015 at 19:43:44 UTC, Laeeth Isharc wrote: I get the following errors under LDC (this is LDC beta, but same problem under master) although the code compiles fine under DMD. Am I doing something wrong? The help generating feature of std.getopt is new in 2.067. Use branch merge-2.067 for that. Otherwise, don't use std.getopt's help generation just yet.
Re: Initializing defaults based on type.
On Friday, 6 March 2015 at 16:04:33 UTC, Benjamin Thaut wrote: On Friday, 6 March 2015 at 15:36:47 UTC, anon wrote: Hi, I can't figure this out. struct Pair(T) { T x; T y; alias x c; alias y r; } What would like is that the x and y to be initialized to different values depending on type eg: struct Container { Pair!double sample1; // This will initialize sample1 with 0 for both x and y Pair!intsample2; // This will initialize sample2 with 1 for both x and y } currently I'm using two different struct one with doubles and the other with ints and initialized with default value but was wondering if its possible to do the above. anon struct Pair(T) { static if(is(T == int)) enum int initValue = 1; else enum T initValue = 0; T x = initValue; T y = initValue; alias x c; alias y r; } Thanks
Initializing defaults based on type.
Hi, I can't figure this out. struct Pair(T) { T x; T y; alias x c; alias y r; } What would like is that the x and y to be initialized to different values depending on type eg: struct Container { Pair!double sample1; // This will initialize sample1 with 0 for both x and y Pair!intsample2; // This will initialize sample2 with 1 for both x and y } currently I'm using two different struct one with doubles and the other with ints and initialized with default value but was wondering if its possible to do the above. anon
How can I convert the following C to D.
I have the following C code, how can I do the same in D. Info **info; info = new Info*[hl + 2]; int r; for(r = 0; r hl; r++) { info[r] = new Info[vl + 2]; } info[r] = NULL; anon
Re: How can I convert the following C to D.
On Wednesday, 21 January 2015 at 23:59:34 UTC, ketmar via Digitalmars-d-learn wrote: On Wed, 21 Jan 2015 23:50:59 + anon via Digitalmars-d-learn digitalmars-d-learn@puremagic.com wrote: On Wednesday, 21 January 2015 at 23:47:46 UTC, ketmar via Digitalmars-d-learn wrote: On Wed, 21 Jan 2015 23:44:49 + anon via Digitalmars-d-learn digitalmars-d-learn@puremagic.com wrote: I have the following C code, how can I do the same in D. Info **info; info = new Info*[hl + 2]; int r; for(r = 0; r hl; r++) { info[r] = new Info[vl + 2]; } info[r] = NULL; anon this is not C. Your right its c++ so the answer to your question is very easy: just type in any gibberish. as C cannot compile C++ code, the final result is to get the code that cannot be compiled. any gibberish will do. Great answer. Anyway the code isn't mine I just wanted to know how to handle what the author wrote. I got it working with. auto info = new Info[][](hl, vl); and changing the logic so as not check for the NULL. No need on being picky it was just a question. anon
Re: How can I convert the following C to D.
On Thursday, 22 January 2015 at 00:16:23 UTC, bearophile wrote: anon: I have the following C code, how can I do the same in D. Info **info; info = new Info*[hl + 2]; int r; for(r = 0; r hl; r++) { info[r] = new Info[vl + 2]; } info[r] = NULL; I suggest you to ignore ketmar, he's not helping :-) Is your code initializing info[r+1]? This is roughly a D translation (untested): void main() @safe { import std.stdio; enum uint hl = 5; enum uint vl = 7; static struct Info {} auto info = new Info[][](hl + 2); foreach (ref r; info[0 .. hl]) r = new Info[vl + 2]; writefln([\n%(%s,\n%)\n], info); } Output: [ [Info(), Info(), Info(), Info(), Info(), Info(), Info(), Info(), Info()], [Info(), Info(), Info(), Info(), Info(), Info(), Info(), Info(), Info()], [Info(), Info(), Info(), Info(), Info(), Info(), Info(), Info(), Info()], [Info(), Info(), Info(), Info(), Info(), Info(), Info(), Info(), Info()], [Info(), Info(), Info(), Info(), Info(), Info(), Info(), Info(), Info()], [], [] ] Is this what you look for? Bye, bearophile Hi Bearophile, It looks like what I need. Thanks, anon
Re: How can I convert the following C to D.
On Wednesday, 21 January 2015 at 23:47:46 UTC, ketmar via Digitalmars-d-learn wrote: On Wed, 21 Jan 2015 23:44:49 + anon via Digitalmars-d-learn digitalmars-d-learn@puremagic.com wrote: I have the following C code, how can I do the same in D. Info **info; info = new Info*[hl + 2]; int r; for(r = 0; r hl; r++) { info[r] = new Info[vl + 2]; } info[r] = NULL; anon this is not C. Your right its c++
Re: D language manipulation of dataframe type structures
On Wednesday, 25 September 2013 at 04:35:57 UTC, lomereiter wrote: I thought about it once but quickly abandoned the idea. The primary reason was that D doesn't have REPL and is thus not suitable for interactive data exploration. https://github.com/MartinNowak/drepl https://drepl.dawg.eu/
Re: Loops versus ranges
On Friday, 19 December 2014 at 10:41:04 UTC, bearophile wrote: A case where the usage of ranges (UFCS chains) leads to very bad performance: import std.stdio: writeln; import std.algorithm: map, join; uint count1, count2; const(int)[] foo1(in int[] data, in int i, in int max) { count1++; if (i max) { typeof(return) result; foreach (immutable n; data) result ~= foo1(data, i + 1, max); return result; } else { return data; } } const(int)[] foo2(in int[] data, in int i, in int max) { count2++; if (i max) { return data.map!(n = foo2(data, i + 1, max)).join; } else { return data; } } void main() { const r1 = foo1([1, 2, 3, 4, 5], 1, 7); writeln(count1); // 19531 const r2 = foo2([1, 2, 3, 4, 5], 1, 7); writeln(count2); // 111 assert(r1 == r2); // Results are equally correct. } Can you tell why? :-) Bye, bearophile Changed to return data.map!(n = foo2(data, i + 1, max)).cache.joiner.array; then it produced the same result as array version. `map.cache.join` resulted in 597871.