Handmade Network»Forums
Simon Anciaux
1341 posts
Advice on manual memory management scheme
I don't have a real example, but time could be a factor in your application.

If you have 1 GB of 64 bits integer that's 134217728 integers. Assuming that computations on that amount of data takes a lot of time, more than you are prepare to wait for in your use case, you might say that you want to cap the memory at 1GB or less. Knowing that you could then say that you don't ever modify approximations, you push a new version at the end of a stack and fix the pointers because you know that you'll have enough of memory.
24 posts
Advice on manual memory management scheme
Edited by AlexKindel on
AlexKindel
On the other hand, functions that do return something that contains one or more Integers would take a pointer to the memory pointer, so that they could increment the caller's pointer to the end of the last array that the return value references. Often, generating the return value requires allocating additional Integers that are not themselves part of the return value. Ideally, the caller's memory pointer would not be incremented in such a way that the heap memory for these temporary values falls before the pointer, preventing the caller from overwriting it. If an upper bound on the size of the return value's heap data is known a priori, this could be done by leaving an empty block of that size at the initial location of the memory pointer before allocating the local values. If no such bound is known, all Integer heap data could be allocated in the order that it's needed for the calculation, and then the parts that are needed for the return value could be copied to the initial location of the memory pointer.


A cleaner way to handle this: a function that needs arena memory both for its return value and for scratch work in generating that return value should take two arena parameters - an output_arena that is a pointer to a pointer to memory, so that the inner pointer can be incremented to the end of the region used for the output, and a scratch_arena, which is a pointer to memory so that the incrementing of the pointer that happens within the function isn't reflected on the caller's end. If a function that takes both arenas calls another function that takes both, if the result of the called function is to be part of the caller's return value, the caller would pass its output_arena and scratch_arena as the called function's parameters of the same names, while if the result of the called function is to be part of the caller's scratch calculations, the caller would pass &scratch_arena for the output_arena parameter and *output_arena for the scratch_arena one.