Goals

GrimoireGrimoire
The book is always better.
>

Non-goals

  • Text or XML format
  • Cross-endianness compatibility
<
>

Proper constructor

To reinstate the virtual method table pointer, where required, a method called do_construct is called on the global static object of type VTypeHandler<YourTypeHere>. To ascertain this object’s unicity across compilation units, call DEFINE_SPEC(YourTypeHere); in global scope. If furthermore you specialize VTypeHandler to override do_construct, the method should use ‘src’ to construct an object at ‘dst’ of the YourTypeHere type, which defaults to copy-construction. Ideally, the heuristic used should expect src and dst to possibly point at the same address, and not modify any state. A move constructor could be viable too, possibly moving to self. The reader is advised that wrapping a member into its own anonymous union { } evades default construction by all constructors.

Modus operandi

  • Register types in default (omit argument) or user-defined ‘serial context’. (Only those types which will both be serialized as well as have virtual methods, or types you want to message).
  • Construct any number of memory_resource subclasses and assign unique id's to identify each.
  • Use the template class thin_pointer instead of plain pointers. (Note: very soon we will release rel::unique_ptr, rel::shared_ptr and rel::weak_ptr with the expected behavior.)
  • Replace new-expressions involving registered types with vnew-expressions. (Guide)
  • Done
<

Extensible

  • We defined an interface to which memory_resource subclasses can additionally adhere, that enables the memory they allocate to partake in all functionality this library offers. We implemented all the basic std::pmr memory_resource subclasses the standard offers, only to be able to accommodate the added functionality. We also offer namespace rel:: which holds an adapted version of each container template the standard prescribes. Care has been taken to be fully standard compliant.
  • Additionally, there is a memory_resource subclass, fully of our own logic, called x10se_pool, which maximizes the space between requested allocations, and thus also maximizes the probability that a currently held allocation will be able to be extended (‘grown’) at the front or the back, useful for making copies unnecessary when resizing contiguous containers.
<
>

thin_pointer<T>

What is a thin pointer?

A thin_pointer is a fancy pointer, but it comprises only an actual pointer. There is the option of storing more than one pointer: simply pass multiple types to the template. Also accepted are arrays of some type, which are converted by the implementation to arrays of the specified dimension, but of pointers to the element type. The grouping of multiple pointers into the same object reduces the memory footprint, as well as serialization size, since at most one pointer is added per thin_pointer instance.

A thin_pointer of a single type: use as a plain pointer to the single type.

A thin_pointer of multiple types: use std::get<> to select a pointer element (elements can also be arrays of pointers).

A thin_pointer of a single array: just index the thin_pointer to select the pointer array element directly.

Why thin_pointer?

The constructors and destructors register and unregister the object’s this pointer as holding n pointers. When serializing an object, the system will be able to query any stored pointers, and overwrite the serialization at the correct offset, effectively replacing the stored address (which might not be correct at time and place of deserialization) with the offset within the serialization where the object that was originally referenced will be serialized in its own right.

Types that are additionally used with vnew-expressions, are then known to be of a certain size. This means the integral collection of objects can be traced out: all pointers can be traversed which are in the region of an object’s size, recurse until complete graph is charted. See memcontour.

<
>

Pointerless design

– relative_pointer<T>

Memory chunk bookkeeping makes a good use case for a relative_pointer class. The chunks used throughout this library can all be serialized in their entirety if so requested, but we can avoid using thin_pointers in any case where we have a this pointer functioning as the origin vector. The chunks’ this pointer may change, and along with it the this pointer of relative_pointer instances, but their relative position will never change. And so, neither will the relative addresses pointed to.

<

Memmap

Writing to and reading from file use the POSIX mmap() system call. The only place in the code where this call is made, is in the 'memmap' class, which can easily be ported to non-POSIX systems (such as Windows) by implementing this class using the corresponding system call (such as CreateFileMapping on Windows).

The library no longer needs any modification to work properly within WSL.

In absence of a memory-map equivalent, the memmap class only needs to provide a void* to the start of the complete file contents for reading, or write a complete buffer to disk. This is trivial.

>
<
<