Advertisement

Scott Bilas Generic Handle-Based Resource Manager

Started by January 24, 2021 12:30 PM
14 comments, last by Shaarigan 3 years, 9 months ago

Option 2 is quite how the C# Garbadge Collector works. Memory is managed in an indirection, so instead of providing a pointer to the real data in heap, C# provides a pointer (aka object) that refers to a small fixed size section of memory. This section contains data that has for example the TypeId, reference count and lock-bit of an object but also a pointer to the raw object data. So the GC is able to move stuff around in the heap without fthe need to fix a lot of references.

In your case it depends, a resource as CPU related data needs the pointer to the content while a GPU related resource has for example the TextureHandle you got from the graphics API. If you instead give all your handles a pointer to this small “resource header” memory location, you're able to operate on the ref-count using for example atomic increment/decrement without the need to call the manager and the manager will be able to iterate through all of these headers and can clean those not used/referenced anymore

Do you know of any examples of the “resource header” shared memory idea? It sounds like I would need to use an allocator, maybe a pool allocator and then have each handle request a piece of memory from it. Then the handle manager would iterate through each memory pool. Each pool would be an object of a class containing a pointer to the actual texture data. I would also need to make the allocator available to the manager and all classes that could use handles.

Am I on the right track?

Advertisement

A generic memory management solution is however a good idea to setup other systems on top but a simple linked list would also do the trick. Have a block of heap memory to store N resource headers, then if needed allocate another block and append it to the first one and so on. It isn't necessary in my opinion, to have an Allocator everywhere or something, this depends on your design model.

I'm sorry I can't strip our solution down to post it in here

@Shaarigan No problem about not posting your solution. I'm just having some trouble understanding the differences of this approach from the manager giving the handle a pointer to itself.

It sounds like the manager creates the linked list (of objects wrapping the pointer to the real data) on the heap and would then need to pass its address to each handle, as the handle is created?

Yes, you're right.

The difference is that your manager in one scenario needs to provide full control over the resource data in the background. You have for example to define an interface to allow handles to increase the ref-count on copy, decrease it on destruction, give access to the data location. This involves the manager as a mandatory authority that needs to be present everywhere and do the work, which may lead to some extra overhead but could also be a benefit that your manager exactly knows when to clean-up and just uses the computation time from the last thread that disposed the handle. Again, design decision …

On the other hand using the approach to pass the memory pointer instead you are free to create your headers ina any way you like and roundtrip times are even shorter because you already have the memory and calling some InterlockedIncrement32 on the ref-counter is simply one atomic instruction. Also you can specify how data is interpreted from the handle, for example if your struct contains a union between an integer and a pointer

This topic is closed to new replies.

Advertisement