Search code examples
c#cpinvokesafehandle

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


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...


Solution

  • 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.