Re: Antipattern in core.memory.GC.addRange?

2017-09-23 Thread Steven Schveighoffer via Digitalmars-d

On 9/23/17 1:55 AM, Petar Kirov [ZombineDev] wrote:



How about adding a template wrapper function, along the lines of:
static void addRange(T)(const T[] arr)
{
     addRange(arr.ptr, T.sizeof * arr.length, typeid(T));
}


To core.memory.GC?


It sounds good. But will it be accepted?

Note, the true implementation should use integer overflow to reject 
invalid arrays.


-Steve


Re: Antipattern in core.memory.GC.addRange?

2017-09-23 Thread Steven Schveighoffer via Digitalmars-d

On 9/23/17 1:30 AM, safety0ff wrote:

On Friday, 22 September 2017 at 21:29:10 UTC, Steven Schveighoffer wrote:

GC.addRange has this signature:

static nothrow @nogc void addRange(in void* p, size_t sz, const 
TypeInfo ti = null);


I see a large problem with this. Let's say you malloc an array of 
struct pointers:


struct Foo { ... }

import core.stdc.stdlib;
auto ptrs = (cast(Foo *)malloc(Foo.sizeof * 10))[0 .. 10];

Now, you want to store GC pointers in that block, you need to add the 
range to the GC:


GC.addRange(ptrs.ptr, ptrs.length);

See the problem?


Yes, you forgot to multiply by Foo.sizeof.

Using the pattern from the example in the documentation,
the code would be:

size_t bytes = Foo.sizeof * 10;
auto ptrs = (cast(Foo *)malloc(bytes))[0 .. 10];
GC.addRange(ptrs.ptr, bytes);



Right, the problem is that the API accepts this without error, because 
of the implicit cast to void *.


The simple rule should be that if we can prevent something obviously 
wrong from compiling, we should do so.


-Steve


Re: Antipattern in core.memory.GC.addRange?

2017-09-23 Thread Petar via Digitalmars-d
On Friday, 22 September 2017 at 21:29:10 UTC, Steven 
Schveighoffer wrote:

GC.addRange has this signature:

static nothrow @nogc void addRange(in void* p, size_t sz, const 
TypeInfo ti = null);


I see a large problem with this. Let's say you malloc an array 
of struct pointers:


struct Foo { ... }

import core.stdc.stdlib;
auto ptrs = (cast(Foo *)malloc(Foo.sizeof * 10))[0 .. 10];

Now, you want to store GC pointers in that block, you need to 
add the range to the GC:


GC.addRange(ptrs.ptr, ptrs.length);

See the problem? Why would addRange work this way, when D has 
such a better mechanism for this? Can we fix it?


-Steve


How about adding a template wrapper function, along the lines of:
static void addRange(T)(const T[] arr)
{
addRange(arr.ptr, T.sizeof * arr.length, typeid(T));
}


To core.memory.GC?


Re: Antipattern in core.memory.GC.addRange?

2017-09-22 Thread safety0ff via Digitalmars-d
On Friday, 22 September 2017 at 21:29:10 UTC, Steven 
Schveighoffer wrote:

GC.addRange has this signature:

static nothrow @nogc void addRange(in void* p, size_t sz, const 
TypeInfo ti = null);


I see a large problem with this. Let's say you malloc an array 
of struct pointers:


struct Foo { ... }

import core.stdc.stdlib;
auto ptrs = (cast(Foo *)malloc(Foo.sizeof * 10))[0 .. 10];

Now, you want to store GC pointers in that block, you need to 
add the range to the GC:


GC.addRange(ptrs.ptr, ptrs.length);

See the problem?


Yes, you forgot to multiply by Foo.sizeof.

Using the pattern from the example in the documentation,
the code would be:

size_t bytes = Foo.sizeof * 10;
auto ptrs = (cast(Foo *)malloc(bytes))[0 .. 10];
GC.addRange(ptrs.ptr, bytes);