Hello,
Thanks for taking the time to read. I work on a team with a custom game engine. The engine itself has been in dev for over a decade, and a handful of games have been released on it, but we only recently added an AngelScript layer.
I mention that, because the issue I am having deals with the AngelScript memory management/ref counting system, and I suspect the issue I am about to describe has to do with how AngelScript has been integrated to play nice with our existing game object system.
Our engine uses fixed width object entity pools, and we use AngelScript in such a way that treats inline memory buffers (inside of the fixed width entity pool) as object instances in AngelScript. So imagine something like, I have a buffer that's 16kb, that's divided into 1k “slots”, and one of those slots can be passed to the AS context and used as the “this” pointer for a method call inside of AS.
We tried a few approaches for this, among them trying a custom allocator. But due to the fact that the custom allocation functions cannot discern the intent for the memory they are allocating, we could not solve this in a targeted enough way with a custom allocator. We also did not want to make any custom changes to AS internals in order to provide additional context to the allocator.
What we ended up doing was, at scene load time there is a “prototype” instance for each registered script type, which is constructed normally in AS. The memory for it is kept around throughout the scene, but those prototype instances are never updated or used as live objects. For objects that run in game, the scene loader memcpy's the prototype instance of the associated class into the desired memory slot in the fixed width pool, and changes around a few other metadata parameters needed to identify each unique instance.
This works well enough to treat each slot as a unique AS instance in our own object system. Each resulting slot stamped out from the prototype instance can be run in an AS context and the script will behave as expected.
However, I am almost certain this is running afoul of the expected reference counting behavior in AS… I half expect someone on this forum to be like “>:| y would u do dis?” Unfortunately the fixed object slot thing is non-negotiable, and we chose AngelScript because it pretty much works within these constraints.
Anyway, we are using config groups to manage the AS engine state. There are 3: Engine (for engine side always-there stuff), Logic (for game side always-there stuff), and Scene (for scripts which get included on a per scene basis). As one might infer, the Scene config group is begun as the scene is loading its referenced scripts then ended after that. When you load a new scene, the existing scene config group is removed (unloading the outgoing scripts), and a new one is begun to load the incoming scene's scripts. This works as expected most of the time.
I should add that all of our native binding types have reference counting turned off. We are also using asEP_ALLOW_UNSAFE_REFERENCES.
The issue we are having occurs when somebody uses object function delegates in a script. We would like to be able to use them, because they are very convenient for implementing state machines. But, if somebody creates a function delegate that points to a method on an object that exists inside the fixed width pools (read: an AS object which did not originate from within the AS engine itself), it seems like that function delegate is given refcounts that can never be resolved by the GC. Then, when the scene config group removal is attempted, the operation fails because there are still live references. At that point, it becomes basically impossible to reconcile the state between the game engine and the AS engine without fully tearing down and rebuilding the AS engine.
So, what I'm wondering is… is there a way I can still do this crazy fixed slot memory thing, and still register that memory in such a way that plays nice with the AngelScript GC? Or is there I can make the function delegates not require reference tracking?
Sorry for the extra long read, and thanks to anyone who can point me in the right direction!