Handle in Programming
We would see the term “handle” very frequently in programming languages such as C and C++, and this term can be confusing to the developers who have not implemented a handle previously.
In this blog post, I would like to discuss what handle is in programming.
What is a handle?
In computer programming, a handle is an abstract reference to a resource.
It is abstracted because there is no explicit convention about what exactly the true type name of the reference should be for a handle. It can be a pointer, a pointer to pointer, a reference to an object, a small object, an index value to an array, a string key value to to a hash map, etc., you name it. The exact true type name of the reference, which can be very long and complicated, is deliberately masked and simplified by having a usually short alias type name. There are accompanying functions defined in the same library to do a variety of things with the resource that the handle references.
Why do we create an alias handle type name?
Given there is a specific true type name for a handle, why do we create an alias handle type name? The motivation of having a shorter alias handle type name does not seem to be sufficient to justify, because there are always people, such as me, who like typing long variable type names. Instead, the major motivation of having an alias handle type name is because the handle type implementer does not want the user to know what exactly the true handle type name is.
The handle typename and the class of the object that the handle references are implementation details which are subject to change in the future. If the user knows what exactly the true handle type name is, the user might do some type specific or hacky operations which will become invalidated as the implementation of the resource class changes resulting in code break in the future. Especially for open source libraries, it is very straightforward to find the exact true type name of the handle, the declaration and the implementation of resource class. So instead of using the handle and the accompanying functions to access the object, the user can access the object in a different way that is compatible with the true handle type name. For example, suppose we have a class
Foo, the true type name of the handle
Foo*, and the handle alias type name is
FooHandle. The class
Foo has an
int attribute which can be accessed by member function
Foo::bar(). The corresponding handle accompanying function to get the attribute is
int get_bar(FooHandle foo_handle). In principle, the user should not know
Foo*. Even if the user knows that the true handle type name of
Foo*, the user should not access the attribute by
foo_handle->get_bar(), even though it compiles. Otherwise, later, when the
foo_handle->get_bar() implementation is used a million times in the program and the exact type name of
FooHandle is changed from
Foo&, the code will be broken and the user would have to fix the code in at least a million places.
When do we create an alias handle type name?
For any resouce class that we want to hide the details from the user, the reference to that class resource needs an alias handle type name. For the following types in a library whose resource will be created and used by user explicitly, they are almost 100% necessary to have an alias handle type name.
- The resource type whose type name consists of more than one type name. For example,
- The resource type whose declaration and definition have never been deliberatively exposed to the user.
How do we create an alias handle type name?
In C and C++, just do
typedef. For example, the CUDA stream handle type
cudaStream_t that CUDA programmers commonly use has a true type name of
CUstream_st * which is a pointer to a
CUstream_st class whose declaration and definition have never been publicly exposed.
typedef CUstream_st * cudaStream_t
Handle in Programming