Handles are a neat way to hide implementation details away from the library user.
There is a nice overview in ‘Handles are the better pointers’
A handle just needs to be an integar with enough bits to hold the information you want to store. At a minimum, the handle will contain a magic number, and an index.
Internally you will have an array of objects. The index from the handle is used to retrieve the correct element from the array.
The magic number is to prevent handle clashes. For instance, The user has a handle, which is then released. The underlying object then has a new handle assigned. Without the magic number, it is not possible to distinguish between the old and new handles.
Verifying the validity of a handle can be done by storing a copy of the current handle in the internal object. The supplied user handle and object handle are then compared, with failure indicating that the provided handle is stale.
Packing the handle with the magic and index is done through bit operations. This is much the same as the way flags are often implemented.
Reference counting can prevent the underlying object been released whilst it is in use.
The update of the reference count should be atomic. Use an atomic integar for the count variable. The count should be incremented whilst using the object, and decremented after.
When updating the count, you must check that the value is updated as expected. An atomic weak compare exchange should be used. This will prevent any issues from multiple threads updating the count concurrently.
When releasing the owning object, first ensure that nothing else is accessing the objet by checking the count. Then set the count to a value to indicate that the object was released. The increment should check for this known value, and return an error to the callee.tags: programming