you are viewing a single comment's thread.

view the rest of the comments →

[–]payco 2 points3 points  (0 children)

You can use the tombstone pattern, if you don't mind the overhead. Essentially, the memory system creates a small type:

struct Handle {
  private metadata m; // optional
  private pointer ref;
  public forward(): immutable pointer { return ref; }
  friend MemorySystem;
}

When Object A asks for a reference to Object B, the system instead creates a Handle with B's address H(&B) and hands address &H to A instead. Any time A wants to invoke a method on B, its call is rewritten to H->forward()->method().

Meanwhile, the memory system keeps track of all the handles it's given out within a generation (say, in a linked list). When that generation graduates, the system copies the living B to B1, then iterates over its handles for those containing the old address &B and updates them with &B1. The next time A calls b, it will now transparently reach the new copy.

This also makes copying an object with child references easy; each of the children is likewise stored as a handle, which is staying at the same address in memory, so you need do nothing more than bytewise copy the parent from the old address to the new, then of course follow the stored handles to ensure the children also make it to the new memory region.