Who write programs that create data structures and supply an handler for each one experience the problem to keep data safe from handlers misuse.
This small library helps on this issue.
Safe handles uses a table of corrispondence handle->memory pointer.
SafeHandles is thread safe. you can create handles concurrently in different threads while the library take care to avoid handles generation conflicts!
The size of the table is determined by the number of bits used for entries SAFEHANDLEENTRIESBITS. The you can change it depending on how many entries you want. Max allowed values is 16 bits. On 64 bits systems this limit can be as bigger as 32 bits. Larger the entries number less safe is the unique key that repeats more often.
A safe handle is an hashing like method to address data blocks, normally generated dinamically, avoiding memory conflicts and data corruption. Safehandles permits to define a type field that is encoded in the handle allowing distinction of data type just looking at the handle (think about GDI objects).
SafeHandles creates a memory table that stores key/data pairs. The size of the table is user defined. SafeHandles have 3 main parts:
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Unique key | Type | Table Ptr |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
The layout above is for a 32bits machine having up to 256 handles (8 bits), 16 types (4 bits) and 20bits of key. If MEMSAFE symbol is defined the handle will always have the MSBit set to address invalid memory. This prevents the use of handler to address memory, hiding any erroneous access to the real data.
The key changes for each new handle created, and wraps around when the max count for key bits is reached. This add safety for reused handles and should be safe enaugh for many applications. However the compiler will issue a message about the key enforcement, it is considered weak if the number of key bits is less than 8 times the table size.
Withstanding all these characteristics the access to the data is very fast and sanity check is strightforward.
To modify the default building of SafeHandles you can define preprocessor values:
- SAFEHANDLEENTRIESBITS Set to the number of bits to be used for table indexing. Max value is 16 for 32bits machines and 32 for 64 bits machines.
- SAFEHANDLETYPESBITS You can reserve bits to identify type of handle in programs where different objects are referenced. Default compile don't use types. Max value 8 for 32bits machines and 16 for 64 bits machines.
- SAFEHANDLEMEMSAFE Define this variable to 1 to protect memory invalid access. Each generated handle will have the MSBit set. In this case using a safe handle to address memory will trigger a memory access exception. The cost is the loss of one bit on unique key.
- SAFEHANDLEDYNMEM Define this variable to 1 to create table in dynamic memory. This is preferable when working with large tables
The test program check and stresses all functionalities.
The code is write to fit 32-64 bits machines, but the 64bits version has not been tested. Glad if someone would do this job...
EDIT: The final release is available on
CodeProject.