www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - How to implement this?

reply Elvis Zhou <elvis.x.zhou gmail.com> writes:
struct A {}
struct B { A a; }
struct C { A a; }

A*[] structs;

B b;
init(&b);
structs ~= cast(A*)&b;
//Error: copying `cast(A*)& b` into allocated memory escapes a 
reference to local variable `b`

C c;
init(&c);
structs ~= cast(A*)&c;
//Error: copying `cast(A*)& c` into allocated memory escapes a 
reference to local variable `c`

batch_process(structs);
Apr 07 2022
next sibling parent reply Era Scarecrow <rtcvb32 yahoo.com> writes:
On Friday, 8 April 2022 at 04:31:45 UTC, Elvis Zhou wrote:
 B b;
 init(\&b);
 structs ~= cast(A*)\&b;
 //Error: copying `cast(A*)\& b` into allocated memory escapes a 
 reference to local variable `b`
Maybe it should be `cast(A*) \&b.a`?
Apr 07 2022
parent Era Scarecrow <rtcvb32 yahoo.com> writes:
On Friday, 8 April 2022 at 04:54:35 UTC, Era Scarecrow wrote:
 Maybe it should be `cast(A*) &b.a`?
Confusing HTML entities bit on here. Probably just ignore it. Maybe you are doing it backwards. What if you had ```d struct B { A* a; } A[] arraylist; ``` then in the init append a new item to A's array list, before doing: ```d arraylist ~= A(); a = &arraylist[$-1]; ``` Alternately, add a static list and have the batch function access both lists? ```d struct B { static A[] list; int a_index=-1; } a_index=list.length; list ~= A(); ``` then reference the item by list[a_index] or something similar.
Apr 07 2022
prev sibling next sibling parent =?UTF-8?Q?Ali_=c3=87ehreli?= <acehreli yahoo.com> writes:
On 4/7/22 21:31, Elvis Zhou wrote:
 struct A {}
 struct B { A a; }
 struct C { A a; }

 A*[] structs;

 B b;
 init(&b);
 structs ~= cast(A*)&b;
 //Error: copying `cast(A*)& b` into allocated memory escapes a reference
 to local variable `b`
If that really is the case, you want to place the objects on memory that will not go away. Dynamic arrays provide "memory" that is owned by the GC. The following program emplaces alternating Bs and Cs into a buffer and then batch_process'es them: struct A { int i; } struct B { A a; } struct C { A a; } A*[] structs; void append(T, Args...)(ref ubyte[] structs, Args args) { import std.conv : emplace; structs.length += sizeWithPadding!T; auto where = cast(T*)(&structs[$ - sizeWithPadding!T]); emplace(where, args); } void main() { ubyte[] structs; foreach (i; 0 .. 10) { if (i % 2) { structs.append!B(A(i)); } else { structs.append!C(A(i)); } } batch_process(structs); } auto process(T)(const(ubyte)[] structs) { import std.stdio : writeln; writeln(*cast(T*)structs.ptr); return structs[sizeWithPadding!T..$]; } void batch_process(const(ubyte)[] structs) { import std.range : empty; for (size_t i = 0; !structs.empty; i++) { if (i % 2) { structs = structs.process!B(); } else { structs = structs.process!C(); } } } T * nextAlignedAddress(T)(T * candidateAddr) { import std.traits; static if (is (T == class)) { const alignment = classInstanceAlignment!T; } else { const alignment = T.alignof; } const result = (cast(size_t)candidateAddr + alignment - 1) / alignment * alignment; return cast(T*)result; } void * nextAlignedAddress(T)(void * candidateAddr) { return nextAlignedAddress(cast(T*)candidateAddr); } size_t sizeWithPadding(T)() { static if (is (T == class)) { const candidateAddr = __traits(classInstanceSize, T); } else { const candidateAddr = T.sizeof; } return cast(size_t)nextAlignedAddress(cast(T*)candidateAddr); } I copied nextAlignedAddress() and sizeWithPadding() functions from this chapter: http://ddili.org/ders/d.en/memory.html Everything I did in the program above is explained there. Ali
Apr 07 2022
prev sibling parent reply Elvis Zhou <elvis.x.zhou gmail.com> writes:
On Friday, 8 April 2022 at 04:31:45 UTC, Elvis Zhou wrote:
 struct A {}
 struct B { A a; }
 struct C { A a; }

 A*[] structs;

 B b;
 init(&b);
 structs ~= cast(A*)&b;
 //Error: copying `cast(A*)& b` into allocated memory escapes a 
 reference to local variable `b`

 C c;
 init(&c);
 structs ~= cast(A*)&c;
 //Error: copying `cast(A*)& c` into allocated memory escapes a 
 reference to local variable `c`

 batch_process(structs);
I know where the issue comes from, dynamic array is GCed and save the reference of a local variable in GCed memory is not allowed, but here structs is assumed to not escape, it can be simply achieved by using a fixed-size array instead, ie A*[32] structs; int i = 0; structs[i++] = cast(A*)&b; However I wonder if there be a stack allocated array with max capacity limits, which can be concated like with normal dynamic one.
Apr 07 2022
parent reply Elvis Zhou <elvis.x.zhou gmail.com> writes:
On Friday, 8 April 2022 at 05:46:56 UTC, Elvis Zhou wrote:
 On Friday, 8 April 2022 at 04:31:45 UTC, Elvis Zhou wrote:
 [...]
I know where the issue comes from, dynamic array is GCed and save the reference of a local variable in GCed memory is not allowed, but here structs is assumed to not escape, it can be simply achieved by using a fixed-size array instead, ie A*[32] structs; int i = 0; structs[i++] = cast(A*)&b; However I wonder if there be a stack allocated array with max capacity limits, which can be concated like with normal dynamic one.
like, assumeNoEscapeOrWhatever!DynamicArray structs; structs ~= cast(A*)&b; is it possible?
Apr 07 2022
parent reply Stanislav Blinov <stanislav.blinov gmail.com> writes:
On Friday, 8 April 2022 at 05:53:03 UTC, Elvis Zhou wrote:

 assumeNoEscapeOrWhatever!DynamicArray structs;
 structs ~= cast(A*)&b;

 is it possible?
That's what ` trusted` is for. And that's also why it should be used with care, and on the smallest code possible. ```d struct A {} struct B { A a; } struct C { A a; } void main() { A*[] structs; B b; C c; () trusted { structs ~= cast(A*)&b; structs ~= cast(A*)&c; } (); } ```
Apr 08 2022
parent Elvis Zhou <elvis.x.zhou gmail.com> writes:
On Friday, 8 April 2022 at 09:08:07 UTC, Stanislav Blinov wrote:
 On Friday, 8 April 2022 at 05:53:03 UTC, Elvis Zhou wrote:

 assumeNoEscapeOrWhatever!DynamicArray structs;
 structs ~= cast(A*)&b;

 is it possible?
That's what ` trusted` is for. And that's also why it should be used with care, and on the smallest code possible. ```d struct A {} struct B { A a; } struct C { A a; } void main() { A*[] structs; B b; C c; () trusted { structs ~= cast(A*)&b; structs ~= cast(A*)&c; } (); } ```
Thank you, this is exactly what I'm looking for! But why this doesn't work? void func() trusted { A*[] structs; B b; structs ~= cast(A*)&b; // still error }
Apr 08 2022