One thing while I think of it.
A "handle" is, in data structure parlance, a doubly indirect reference. Somewhere, behind the scenes, is a structure which holds the data:
| struct device_context {
// some stuff
};
|
An indirect reference to one of these structures might be a pointer. A doubly indirect reference could be a pointer to a pointer:
| typedef struct device_context** HDC;
void DoSomethingWithDC(HDC hDC)
{
struct device_context* dc = *hDC;
if (!dc) {
// Null pointer
return;
}
// Do stuff
}
|
Or, more commonly, an index into an array (or other collection) of pointers:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 | #define MAX_HANDLES some_number
struct device_context* DCHandleTable[MAX_HANDLES];
typedef uint32_t HDC;
void DoSomethingWithDC(HDC hDC)
{
struct device_context* dc = DCHandleTable[hDC];
if (!dc) {
// Null pointer
return;
}
// Do stuff
}
|
So why would you bother using a doubly-indirect reference, as opposed to just a pointer?
One reason is safety. If you're in the habit of freeing objects (Casey isn't, but Windows is), then this gives you a pointer which points to free memory. Attempting to write to it would corrupt the heap.
Using handles lets you free an object, but still ensure that nobody knows about a bad pointer:
| void DeleteDC(HDC hDC) {
free(DCHandleTable[hDC]);
DCHandleTable[hDC] = 0;
}
|
(It's possible that handles could get reused, and there are steps you can take to mitigate that, but it will still point to a valid object even if it's not the right valid object.)
Another reason is security, and this is why operating systems use them a lot. You don't want the user to be able to manufacture a handle to an object for which it has no permissions. All sufficiently modern operating systems have them; Unix-like operating systems, for example, have process ids and file handles.
Managing handles and the objects they point to is the central thing that the Windows kernel does. To ntoskrnl, pretty much everything is an object referenced by a handle.
I mention all this because "big" game engines often use handles to manage game entities, especially for multiplayer games where you can't transport pointers across a network. Handmade Hero very likely won't, of course. But handles are ubiquitous, and it's worth understanding what they are.