Re: Managing malloced memory

2021-10-12 Thread anon via Digitalmars-d-learn
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

2021-10-11 Thread anon via Digitalmars-d-learn
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

2021-10-06 Thread anon via Digitalmars-d-learn
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

2021-10-06 Thread anon via Digitalmars-d-learn

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

2021-10-06 Thread anon via Digitalmars-d-learn

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

2021-10-06 Thread anon via Digitalmars-d-learn
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

2020-04-26 Thread anon via Digitalmars-d-learn
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

2016-03-28 Thread Anon via Digitalmars-d-learn

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

2016-03-28 Thread Anon via Digitalmars-d-learn

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

2016-03-28 Thread Anon via Digitalmars-d-learn

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?

2016-03-08 Thread Anon via Digitalmars-d-learn

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?

2016-03-05 Thread Anon via Digitalmars-d-learn

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

2016-01-15 Thread Anon via Digitalmars-d-learn

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

2015-11-25 Thread Anon via Digitalmars-d-learn

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

2015-07-02 Thread Anon via Digitalmars-d-learn

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

2015-04-29 Thread Anon via Digitalmars-d-learn

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.

2015-03-07 Thread anon via Digitalmars-d-learn

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.

2015-03-06 Thread anon via Digitalmars-d-learn

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.

2015-01-21 Thread anon via Digitalmars-d-learn

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.

2015-01-21 Thread anon via Digitalmars-d-learn
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.

2015-01-21 Thread anon via Digitalmars-d-learn

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.

2015-01-21 Thread anon via Digitalmars-d-learn
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

2014-12-26 Thread anon via Digitalmars-d-learn

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

2014-12-19 Thread anon via Digitalmars-d-learn

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.