How can I prevent the same unmanaged pointer from being encapsulated in two different SafeHandles?

179 views Asked by At

I am writing a managed wrapper for a game engine written in C to challenge myself. I have started to wrap unmanaged pointers in SafeHandle derivatives, but it donned on me that calls to the unmanaged functions that could return the same pointer will probably create new SafeHandles, and if one of them gets disposed, the rest of them will become invalid.

How can I prevent this from happening efficiently? I doubt the marshaller automagically tracks duplicates...

2

There are 2 answers

1
Ajay Brahmakshatriya On BEST ANSWER

You are trying to tackle the problem which most managed pointers and non garbage collecting techniques try to answer. Depending on the use case, there are multiple solutions to this -

  1. You can use reference counts - You basically maintain a count of number of Handles holding a particular pointer and overload (in C use function calls instead of assignments) operators to update the counts on assignments. You then free the pointer only after the count has reached 0. This approach although accurate has significant overheads and also is susceptible to cycles and hence can leak memory. This is a reference count ownership model.

  2. You can create a unique_ptr. What this basically means that at any time only 1 handle holds the reference to a particular pointer. This means if you do something like -

    a = b 
    

    The pointer will be copied from b to a and b will automatically become invalid (more of a contract of the API, rather than implementation). This means the user has to build the code around these constraints. Here the free is done when any object holding a reference goes out of scope. This is a exclusive ownership model.

There are other approaches too(like weak_ptr) and you can read about them in any C++ reference.

1
sonicbhoc On

Though this answer was to another question, it would work in this case.

I could make a factory class that calls out to managed functions for me, then creates the SafeHandles manually in a Constrained Execution Region, like the marhsaller does. This factory class can keep track of the unmanaged pointers and, if a SafeHandle was already created, return it instead of making a new one.