HOME BLOG ARCHIVE TAGS

Another take on programming handles

March 22, 2015

Last week I struggled with a nasty low-level library, badly designed as building block for higher-level stuff (e.g., MS CryptoAPI CSPs). Its handles were implemented as usual, in terms of opaque ptrs to dynamically allocated structures. Like this [0]:

1
typedef void *handle_t;

When designing a low-level API, sometimes it’s nice to provide a way for programmers to associate state with returned handles. A couple of helpers may be enough:

1
2
3
4
5
//
// extra ptr used by external callers/consumers;
//
void *get_ex_ptr(handle_t h);
void  set_ex_ptr(handle_t h, void *p);

It seems silly wasting a few bytes inside the underlying data [1], but this provisioned ptr is actually a winning strategy for more complex layers.

Astute readers may argue that two dynamic allocations are necessary in any case; callers will probably use aggregation, comprised of other variables and one of your handles:

1
2
3
4
5
struct something_
{
    // (...) whatever;
    handle_t h;
};

But what if the price of having extra state doesn’t need to be paid? Further dynamic allocations would be made in vain, incurring more memory management work (translating to worse heap fragmentation, and additional contention on multithreaded apps).

Many known APIs employ this pattern: cURL has CURLOPT_PRIVATE option, Win32 offers GWLP_USERDATA for window handles, and OpenSSL supports ex-data everywhere.

It’s like those extra void ptrs in callback functions. Always good to have around.


Notes:
[0] - “_t” suffix is POSIX/implementation reserved;
[1] - sometimes space is not even wasted; reordering declarations may be enough to avoid memory alignment padding (that would be present in any case);