[−][src]Module ffi_support::handle_map
This module provides a [Handle
] type, which you can think of something
like a dynamically checked, type erased reference/pointer type. Depending on
the usage pattern a handle can behave as either a borrowed reference, or an
owned pointer.
They can be losslessly converted to and
from a 64 bit integer, for ease of passing over the FFI
(and they implement [IntoFfi
] using these primitives for this purpose).
The benefit is primarially that they can detect common misuse patterns that would otherwise be silent bugs, such as use-after-free, double-free, passing a wrongly-typed pointer to a function, etc.
Handles are provided when inserting an item into either a [HandleMap
] or a
[ConcurrentHandleMap
].
Comparison to types from other crates
[HandleMap
] is similar to types offered by other crates, such as
slotmap
, or slab
. However, it has a number of key differences which make
it better for our purposes as compared to the types in those crates:
- Unlike
slab
(but likeslotmap
), we implement versioning, detecting ABA problems, which allows us to detect use after free. - Unlike
slotmap
, we don't have theT: Copy
restriction. - Unlike either, we can detect when you use a Key in a map that did not
allocate the key. This is true even when the map is from a
.so
file compiled separately. - Our implementation of doesn't use any
unsafe
(at the time of this writing).
However, it comes with the following drawbacks:
slotmap
holds its version information in au32
, and so it takes 231 colliding insertions and deletions before it could potentially fail to detect an ABA issue, wheras we use au16
, and are limited to 215.- Similarly, we can only hold 216 items at once, unlike
slotmap
's 232. (Considering these items are typically things like database handles, this is probably plenty). - Our implementation is slower, and uses slightly more memory than
slotmap
(which is in part due to the lack ofunsafe
mentioned above)
The first two issues seem exceptionally unlikely, even for extremely
long-lived HandleMap
, and we're still memory safe even if they occur (we
just might fail to notice a bug). The third issue also seems unimportant for
our use case.
Structs
ConcurrentHandleMap |
|
Entry | |
HANDLE_MAP_ID_COUNTER | |
Handle | A Handle we allow to be returned over the FFI by implementing [ |
HandleMap |
|
Enums
EntryState | |
HandleError | An error representing the ways a |
Constants
HANDLE_MAGIC | |
MAX_CAPACITY | The maximum capacity of a [ |
MIN_CAPACITY |
Functions
next_handle_map_id | |
to_u16 |