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

Reply via email to