According to erl_driver documentation for driver_async_port_key
function,
Before OTP-R16, the actual port id could be used as a key with proper casting, but after the rewrite of the port subsystem, this is no longer the case. With this function, you can achieve the same distribution based on port id's as before OTP-R16.
What is this proper casting?
The ErlDrvPort
type is a typedef of a pointer to a struct. To obtain an unsigned int
async key type in older driver applications, you need to convert this pointer type to unsigned int
. One way to achieve this is to cast it through the C99 uintptr_t
type, which is guaranteed to be large enough to hold a pointer value:
#include <stdint.h>
#include "erl_driver.h"
unsigned int my_port_key(ErlDrvPort port)
{
return (unsigned int) (uintptr_t) port;
}
You can write a portable function to return an async key using driver API versioning information available in erl_driver.h
. The driver_async_port_key
function was introduced in driver API version 2.2, so we can call driver_async_port_key
when using version 2.2 or newer, or fall back to the casting approach for older versions:
#include <stdint.h>
#include "erl_driver.h"
unsigned int my_port_key(ErlDrvPort port)
{
#if ERL_DRV_EXTENDED_MAJOR_VERSION > 2 || \
(ERL_DRV_EXTENDED_MAJOR_VERSION == 2 && ERL_DRV_EXTENDED_MINOR_VERSION >= 2)
return driver_async_port_key(port);
#else
return (unsigned int) (uintptr_t) port;
#endif
}