D-Programming-Language/druntime — pull request #730 by Krox (2014-02-26 13:09:34+00:00)
Title: add new keep-alive flag to the garbage collector

I suggest (and implemented) a new memory block attribute for the gc: GC.BlkAttr.KEEP_ALIVE. When set, the associated block is not collected when the gc is run, even if the gc does not see any references to it anymore. In order to free the block, you can either do it explicitly, or simply clear the attribute.

The same effect can already be achieved with GC.addRoot/removeRoot, but those are implemented using a simple unordered array. Therefore they are extremely slow if you have a large number of roots. That could be fixed by using a more sophisticated data structure, but I think my approach is still superior because:
* much easier to implement
* it uses only one bit per block, in contrast to one pointer per block for GC.addRoot() (or 2-3 pointers if it is replaced by a sophisticated structure)
* the gc does not have to resolve root-pointers to their blocks, but instead the block itself is marked. This is more natural an possibly sligthly faster.
* when you free the block explicitly, it is impossible to forget the call to removeRoot

Another popular way to prevent the gc from collecting a block is to allocate it outside the gc heap (i.e. core.stdc.stdlib.malloc). But if the block contains pointers back into the gc heap, you have to use GC.addRange/removeRange, which suffers exactly the same problems as addRoot/removeRoot.