How to implement this?

Ali Çehreli acehreli at yahoo.com
Fri Apr 8 05:18:38 UTC 2022


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



More information about the Digitalmars-d-learn mailing list