#include <dpa/utils/bo.h>
This header provides types and functions related to buffer objects and tagged buffer object pointers. The intent is to make memory management easier, minimize copying of data if not necessary, and providing a means to create identifiers that are unique and can be compared in O(1).
dpa_u_a_bo_any_t | The BO can refer to any kind of data, and can have any valid tag |
---|---|
dpa_u_a_bo_gc_t | The BO can contain unique, refcounted and static data |
dpa_u_a_bo_unique_t | This tagged BO pointer has an unique value. Data smaller than 8 bytes will be inlined. Unused bytes will be 0. |
dpa_u_a_bo_refcounted_t | This BO has a refcount. But it can not be a unique bo, because a unique bo may be an inline bo, and an inline bo has no refcount. |
dpa_u_a_bo_hashed_t | This BO is pre-hashed. This usually isn't all that useful, consider using dpa_u_a_bo_unique_t instead. |
enum dpa_u_bo_type_flags | |
---|---|
DPA_U_BO_SIMPLE | If this tag is set, the pointer points to a dpa_u_bo_t object. Except for inlined data, this is always the case. |
DPA_U_BO_STATIC | The data has static lifetime. The data will never be freed. The BO object may not have static lifetime though. |
DPA_U_BO_REFCOUNTED | The data has a reference count. This is never an inline BO. The BO object itself is not refcounted. |
DPA_U_BO_UNIQUE |
The data of this BO is unique. The BO itself is refcounted. The BO and it's data are immutable, they
will not change. The data may or may not have it's own refcount, and it may or may not store it's hash, and this may change depending on the data and between implementations. |
DPA_U_BO_HASHED | The BO is pre-hashed. |
All dpa_u_a_bo_* objects represent either tagged BO pointers, or inlined data.
Inlined data can be at most 7 bytes big. The first byte is reserved for the tag of the tagged BO pointer. The tag
contains information about the type of object it points to, and the lifetime of the data the BO refers to,
but the lifetime of the BO object itself may differ from that. The tag also contains the length of inline data
if it is an inline BO.
If a tagged BO pointer is dereferenced, the resulting BO object will be const qualified.
A tagged BO pointer without any tags represents an error value. An error value is an inline BO object which is not marked as unique. In other words, it can be safely dereferenced, and then contains the name of the error. However, it is recommended to actually check if a tagged BO pointer is an error object, using the dpa_u_bo_is_error function.
Currently, only the simple dpa_u_bo_t type is implemented.
There are internal types for hashed and refcounted BOs, but there are no plans to expose them as of now.
This is because there is no way to define a hashed refcounted bo in such a way that a pointer to it can be
converted to both, a hashed bo and a refcounted bo, without type-punning, which would be UB.
There are tagged pointers for hashed and refcounted BOs, and functions for creating them in the current block
scope, as well as functions for getting the refcount and the hash.
Type | Name | Description |
---|---|---|
size | The size of the BO. | |
data | A pointer to the data |
The lifetime of BO objects may be shorter than that of the data. The only exception are inline BOs.
The lifetime of an inline BO always matches that of the tagged BO pointer value itself.
Special care must be taken when passing a refcounted BO which is not a unique BO to another function, or when
storing it in a shared object. In that case only the data is refcounted, and multiple refcounted BO objects
referencing the same data with shorter lifetimes could exist. Unlike with unique BOs, incrementing the refcount
is insufficient in this case, BO objects of sufficient lifetime must be created.
A BO pointer tagged as static has statically allocated data, but the BO may not be statically allocated.
This is similar to refcounted BOs.
When storing, for example, a dpa_u_a_bo_gc_t in a shared object, when it is not known if the BO has a sufficient lifetime, a new BO Object needs to be allocated. The functions dpa_u_bo_copy_maybe and dpa_u_bo_copy_bo_maybe exist to help with that.
As a convention, functions will assume that the BOs tagged pointers point to, and their data, are immutable. They may store them under that assumption. However, this doesn't always have to be the case. If the BO or it's data is not immutable, it may be necessarey to copy it in that case. The function dpa_u_bo_needs_copy can be used to force a BO to be copied later if necessary.
Takes a tagged BO pointer and tags from dpa_u_bo_type_flags. The tags should be ORed. Returns true if the tagged pointer has any of the flags.
Takes a tagged BO pointer and tags from dpa_u_bo_type_flags. The tags should be ORed. Returns true if the tagged pointer has all of the flags.
Takes a tagged BO pointer and tags from dpa_u_bo_type_flags. The tags should be ORed. Returns true if the tagged pointer has all of the flags.
If the BO is a unique BO, this function just increments the BOs refcount. Otherwise a new BO object is allocated. The refcount of the data of a refcounted BO is also incremented, in addition to a new BO object being allocated. If a BO is neither unique, nor refcounted, nor static, the data is also copied.
Unlike dpa_u_bo_copy_maybe, this function does not copy the BOs data, nor increment it's refcount. Everything else is the same. Only use this function if the data is known to have a sufficient lifetime.
If it is a unique BO, only the unique BOs refcount is incremented. Otherwise the datas refcount is incremented. If there is no refcount, nothing happens. This function is thread safe.
If it is a unique BO, only the unique BOs refcount is decremented. Otherwise the datas refcount is decremented. If the refcount hits 0, the data is freed. If it is a unique BO, the unique BO is removed from the set of unique BOs, and the refcount of the data is decremented if there is one, and freed once nothing references it anymore. This function is thread safe.
This takes a tagged pointer and frees the BO it points to. It does not free the data the BO points to. If it is a unique bo, it does nothing.
Takes a tagged BO pointer. If it is an error object, returns true. Otherwise, it returns false.
Takes an errno value, returns a dpa_u_a_bo_unique_t. The BO object will not be a unique bo, though, but an error object.
Takes an error object. If it corrensponds to a known errno value, that value is returned. Otherwiese, -1 is returned.
Returns true if the BOs are the same object. If it's a tagged pointer, the pointer without the tags are compared. If it's a BO object, it is referenced and the resulting pointer is compared.
Returns true if the BOs have the same size & data, false otherwise. Error BOs are never considered equal to other BOs.
Returns 0 if the BOs have the same size & data. Returns a positive or negative value otherwise. If both BOs are unique BOs, only the pointers are compared. Otherwise, the size and data is compared. This function can be used for sorting BOs, so long as unique and non-unique BOs are not mixed. If there are unique and non-unique BOs, use dpa_u_bo_compare_data instead. Error BOs are never considered equal to other BOs.
Returns 0 if the BOs have the same size & data. Returns a positive or negative value otherwise. Can be used for sorting. It first compares the size, then the data using memcmp, that is the order a sort is going to have. Error BOs are never considered equal to other BOs.
The dpa_u_to_bo_* functions just converts between tagged BO pointers.
The dpa_u_make_bo_* allocate a BO object in the current scope. They allow to create various
BO types whose struct type is not meant to be used directly. This way this library does not have to convert
between them, which avoids the incompatibility issue between refcounted, hashed and refcounted + hashed BOs..
dpa_u_alloc_bo_* functions exist for every The dpa_u_make_bo_*
functions. They do the same, but allocate the BO using malloc. They have to be freed using
dpa_u_bo_free.
Interns a BO. Returns a unique BO. If the data is refcounted or static, it may not copy it, but just increment the refcount instead. When passing a refcounted BO to this function, make sure it's data is immutable. To force the data to be copied, use the dpa_u_bo_untag_gc function. This function is thread safe.
Returns an a dpa_u_bo_t. This may be an rvalue. Note, the other conversion functions can take an rvalue, but beware of objects with temporary storage duration when converting them to tagged pointers, thus referencing the rvalue.
Returns a dpa_u_a_bo_any_t to the specified BO.
Returns a dpa_u_a_bo_any_t to the specified BO. It is tagged as a static BO.
Returns a dpa_u_a_bo_gc_t to the specified BO. If the conversion isn't allowed at runtime, an error object will be returned. The BO to be converted must be refcounted, static, inline, unique, or a combination of those things.
Takes a dpa_u_bo_t. Returns a dpa_u_a_bo_gc_t to the specified BO. It is tagged as a static BO.
Takes a tagged BO pointer.
Returns a dpa_u_a_bo_hashed_t to the specified BO.
If the conversion isn't allowed at runtime, an error object will be returned.
The BO to be converted must be pre-hashed.
Converting unique BOs is not recommended, they are often small and not pre-hashed. Also, this function
will not take a dpa_u_a_bo_unique_t
However, you can use
dpa_u_make_bo_hashed_do_hash or
dpa_u_alloc_bo_hashed_do_hash, they create a new hashed bo, hashing a BO is always
possible.
Takes a tagged BO pointer. Returns a dpa_u_a_bo_refcounted_t to the specified BO. If the conversion isn't allowed at runtime, an error object will be returned. The BO to be converted must be refcounted or static and can can't be a unique BO.
Takes a dpa_u_bo_t and a pointer to a dpa_u_refcount_freeable_t. Creates a new BO object in the current block scope with a pointer to a refcount. If the refcount is static, the BO pointer is tagged as static. Returns a dpa_u_a_bo_any_t*.
Takes a dpa_u_bo_t and a uint64_t containing the hash. The hash must be the same as would have been calculated using the dpa_u_bo_get_hash function. Creates a new BO object in the current block scope with a hash. Returns a dpa_u_a_bo_any_t*.
Takes a dpa_u_bo_t and a uint64_t containing the hash. The hash must be the same as would have been calculated using the dpa_u_bo_get_hash function. Creates a new BO object in the current block scope with a hash. The tagged BO pointer has the static flag set. Returns a dpa_u_a_bo_any_t*.
Takes a BO object or a tagged BO pointer. Creates a new BO object in the current block scope. Returns a dpa_u_a_bo_any_t*.
Takes a BO object or a tagged BO pointer. The bo will be hashed, unless it already is hashed. Creates a new BO object in the current block scope with a hash. Returns a dpa_u_a_bo_any_t*.
Takes a dpa_u_bo_t. Creates a new BO object in the current block scope with. The tagged BO pointer has the static flag set. Returns a dpa_u_a_bo_any_t*.
Takes a dpa_u_bo_t. The bo will be hashed. Creates a new BO object in the current block scope with a hash. The tagged BO pointer has the static flag set. Returns a dpa_u_a_bo_any_t*.
Takes a dpa_u_bo_t, a pointer to a dpa_u_refcount_freeable_t and a uint64_t containing the hash. The hash must be the same as would have been calculated using the dpa_u_bo_get_hash function. Creates a new BO object in the current block scope with a pointer to a refcount and a hash. If the refcount is static, the BO pointer is tagged as static. Returns a dpa_u_a_bo_any_t*.
Takes a dpa_u_bo_t, a pointer to a dpa_u_refcount_freeable_t. The bo will be hashed. Creates a new BO object in the current block scope with a pointer to a refcount and a hash. If the refcount is static, the BO pointer is tagged as static. Returns a dpa_u_a_bo_any_t*.
Takes a tagged BO pointer. Creates a new BO object in the current block scope. If the conversion isn't allowed at runtime, an error object will be returned. Returns a dpa_u_a_bo_gc_t.
Takes a dpa_u_bo_t and a pointer to a dpa_u_refcount_freeable_t. Creates a new BO object in the current block scope with a pointer to a refcount. If the refcount is static, the BO pointer is tagged as static. Returns a dpa_u_a_bo_gc_t.
Takes a dpa_u_bo_t and a uint64_t containing the hash. The hash must be the same as would have been calculated using the dpa_u_bo_get_hash function. Creates a new BO object in the current block scope with a hash. The tagged BO pointer has the static flag set. Returns a dpa_u_a_bo_gc_t.
Takes a BO object or a tagged BO pointer. The bo will be hashed, unless it already is hashed. Creates a new BO object in the current block scope with a hash. If the conversion isn't allowed at runtime, an error object will be returned. Returns a dpa_u_a_bo_gc_t.
Takes a BO object. The bo will be hashed. Creates a new BO object in the current block scope with a hash. The tagged BO pointer has the static flag set. If the conversion isn't allowed at runtime, an error object will be returned. Returns a dpa_u_a_bo_gc_t.
Takes a dpa_u_bo_t, a pointer to a dpa_u_refcount_freeable_t and a uint64_t containing the hash. The hash must be the same as would have been calculated using the dpa_u_bo_get_hash function. Creates a new BO object in the current block scope with a pointer to a refcount and a hash. If the refcount is static, the BO pointer is tagged as static. Returns a dpa_u_a_bo_gc_t.
Takes a dpa_u_bo_t and a pointer to a dpa_u_refcount_freeable_t. The bo will be hashed. Creates a new BO object in the current block scope with a pointer to a refcount and a hash. If the refcount is static, the BO pointer is tagged as static. Returns a dpa_u_a_bo_gc_t.
Takes a tagged BO pointer. Creates a new BO object in the current block scope with a pointer to a refcount. If the conversion isn't allowed at runtime, an error object will be returned. Returns a dpa_u_a_bo_refcounted_t.
Takes a dpa_u_bo_t. Creates a new BO object in the current block scope with a pointer to a refcount. Returns a dpa_u_a_bo_refcounted_t with the static flag set.
Takes a dpa_u_bo_t and a pointer to a dpa_u_refcount_freeable_t. Creates a new BO object in the current block scope with a pointer to a refcount. If the refcount is static, the BO pointer is tagged as static. Returns a #dpa_u_a_bo_refcounted_t.
Takes a dpa_u_bo_t, a pointer to a dpa_u_refcount_freeable_t and a uint64_t containing the hash. The hash must be the same as would have been calculated using the dpa_u_bo_get_hash function. Creates a new BO object in the current block scope with a pointer to a refcount and a hash. If the refcount is static, the BO pointer is tagged as static. Returns a dpa_u_a_bo_refcounted_t.
Takes a tagged BO pointer. The bo will be hashed if it isn't already. Creates a new BO object in the current block scope with a pointer to a refcount and a hash. If the conversion isn't allowed at runtime, an error object will be returned. Returns a dpa_u_a_bo_refcounted_t.
Takes a dpa_u_bo_t, a pointer to a dpa_u_refcount_freeable_t. The bo will be hashed. Creates a new BO object in the current block scope with a pointer to a refcount and a hash. If the refcount is static, the BO pointer is tagged as static. Returns a dpa_u_a_bo_refcounted_t.
Takes a dpa_u_bo_t and a uint64_t containing the hash. The hash must be the same as would have been calculated using the dpa_u_bo_get_hash function. Creates a new BO object in the current block scope with a hash. Returns a dpa_u_a_bo_hashed_t*.
Takes a dpa_u_bo_t and a uint64_t containing the hash. The hash must be the same as would have been calculated using the dpa_u_bo_get_hash function. Creates a new BO object in the current block scope with a hash. The tagged BO pointer has the static flag set. Returns a dpa_u_a_bo_hashed_t*.
Takes a dpa_u_bo_t, a pointer to a dpa_u_refcount_freeable_t and a uint64_t containing the hash. The hash must be the same as would have been calculated using the dpa_u_bo_get_hash function. Creates a new BO object in the current block scope with a pointer to a refcount and a hash. If the refcount is static, the BO pointer is tagged as static. Returns a dpa_u_a_bo_hashed_t*.
Takes a BO object or a tagged BO pointer. The bo will be hashed, unless it already is hashed. Creates a new BO object in the current block scope with a hash. Returns a dpa_u_a_bo_hashed_t*.
Takes a dpa_u_bo_t. The bo will be hashed. Creates a new BO object in the current block scope with a hash. The tagged BO pointer has the static flag set. Returns a dpa_u_a_bo_hashed_t*.
Takes a dpa_u_bo_t and a pointer to a dpa_u_refcount_freeable_t. The bo will be hashed. The hash must be the same as would have been calculated using the dpa_u_bo_get_hash function. Creates a new BO object in the current block scope with a pointer to a refcount and a hash. If the refcount is static, the BO pointer is tagged as static. Returns a dpa_u_a_bo_hashed_t*.
Takes a dpa_u_bo_t and a pointer to a dpa_u_refcount_freeable_t. Allocates a new BO with a pointer to a refcount. If the refcount is static, the BO pointer is tagged as static. This BO must be freed later using dpa_u_bo_free. Returns a dpa_u_a_bo_any_t*.
Takes a dpa_u_bo_t and a uint64_t containing the hash. The hash must be the same as would have been calculated using the dpa_u_bo_get_hash function. Allocates a new BO with a hash. This BO must be freed later using dpa_u_bo_free. Returns a dpa_u_a_bo_any_t*.
Takes a dpa_u_bo_t and a uint64_t containing the hash. The hash must be the same as would have been calculated using the dpa_u_bo_get_hash function. Allocates a new BO with a hash. This BO must be freed later using dpa_u_bo_free. The tagged BO pointer has the static flag set. Returns a dpa_u_a_bo_any_t*.
Takes a BO object or a tagged BO pointer. Allocates a new BO. Returns a dpa_u_a_bo_any_t*.
Takes a BO object or a tagged BO pointer. Allocates a new BO. The bo will be hashed, unless it already is hashed. Returns a dpa_u_a_bo_any_t*.
Takes a dpa_u_bo_t. Allocates a new BO. The tagged BO pointer has the static flag set. Returns a dpa_u_a_bo_any_t*.
Takes a dpa_u_bo_t. Allocates a new BO. The bo will be hashed. The tagged BO pointer has the static flag set. Returns a dpa_u_a_bo_any_t*.
Takes a dpa_u_bo_t, a pointer to a dpa_u_refcount_freeable_t and a uint64_t containing the hash. The hash must be the same as would have been calculated using the dpa_u_bo_get_hash function. Allocates a new BO with a pointer to a refcount and a hash. If the refcount is static, the BO pointer is tagged as static. This BO must be freed later using dpa_u_bo_free. Returns a dpa_u_a_bo_any_t*.
Takes a dpa_u_bo_t, a pointer to a dpa_u_refcount_freeable_t. The bo will be hashed. Allocates a new BO with a pointer to a refcount and a hash. If the refcount is static, the BO pointer is tagged as static. Returns a dpa_u_a_bo_any_t*.
Takes a tagged BO pointer. Allocates a new BO. If the conversion isn't allowed at runtime, an error object will be returned. Returns a dpa_u_a_bo_gc_t.
Takes a dpa_u_bo_t and a pointer to a dpa_u_refcount_freeable_t. Allocates a new BO with a pointer to a refcount. If the refcount is static, the BO pointer is tagged as static. This BO must be freed later using dpa_u_bo_free. Returns a dpa_u_a_bo_gc_t.
Takes a dpa_u_bo_t and a uint64_t containing the hash. The hash must be the same as would have been calculated using the dpa_u_bo_get_hash function. Allocates a new BO with a hash. This BO must be freed later using dpa_u_bo_free. The tagged BO pointer has the static flag set. Returns a dpa_u_a_bo_gc_t.
Takes a BO object or a tagged BO pointer. The bo will be hashed, unless it already is hashed. Allocates a new BO with a hash. If the conversion isn't allowed at runtime, an error object will be returned. Returns a dpa_u_a_bo_gc_t.
Takes a BO object. The bo will be hashed. Allocates a new BO with a hash. The tagged BO pointer has the static flag set. If the conversion isn't allowed at runtime, an error object will be returned. Returns a dpa_u_a_bo_gc_t.
Takes a dpa_u_bo_t, a pointer to a dpa_u_refcount_freeable_t and a uint64_t containing the hash. The hash must be the same as would have been calculated using the dpa_u_bo_get_hash function. Allocates a new BO with a pointer to a refcount and a hash. If the refcount is static, the BO pointer is tagged as static. This BO must be freed later using dpa_u_bo_free. Returns a dpa_u_a_bo_gc_t.
Takes a dpa_u_bo_t and a pointer to a dpa_u_refcount_freeable_t. The bo will be hashed. Allocates a new BO with a pointer to a refcount and a hash. If the refcount is static, the BO pointer is tagged as static. Returns a dpa_u_a_bo_gc_t.
Takes a tagged BO pointer. Allocates a new BO with a pointer to a refcount. If the refcount is static, the BO pointer is tagged as static. If the conversion isn't allowed at runtime, an error object will be returned. This BO must be freed later using dpa_u_bo_free. Returns a #dpa_u_a_bo_refcounted_t.
Takes a dpa_u_bo_t. Allocates a new BO with a pointer to a refcount. This BO must be freed later using dpa_u_bo_free. Returns a #dpa_u_a_bo_refcounted_t tagged as static.
Takes a dpa_u_bo_t and a pointer to a dpa_u_refcount_freeable_t. Allocates a new BO with a pointer to a refcount. If the refcount is static, the BO pointer is tagged as static. This BO must be freed later using dpa_u_bo_free. Returns a #dpa_u_a_bo_refcounted_t.
Takes a dpa_u_bo_t, a pointer to a dpa_u_refcount_freeable_t and a uint64_t containing the hash. The hash must be the same as would have been calculated using the dpa_u_bo_get_hash function. Allocates a new BO with a pointer to a refcount and a hash. If the refcount is static, the BO pointer is tagged as static. This BO must be freed later using dpa_u_bo_free. Returns a dpa_u_a_bo_refcounted_t.
Takes a dpa_u_bo_t, a pointer to a dpa_u_refcount_freeable_t. The bo will be hashed. Allocates a new BO with a pointer to a refcount and a hash. If the refcount is static, the BO pointer is tagged as static. Returns a dpa_u_a_bo_refcounted_t.
Takes a tagged BO pointer. The bo will be hashed if it isn't already. Allocates a new BO with a pointer to a refcount and a hash. If the refcount is static, the BO pointer is tagged as static. If the conversion isn't allowed at runtime, an error object will be returned. Returns a dpa_u_a_bo_refcounted_t.
Takes a dpa_u_bo_t and a uint64_t containing the hash. The hash must be the same as would have been calculated using the dpa_u_bo_get_hash function. Allocates a new BO with a hash. This BO must be freed later using dpa_u_bo_free. Returns a dpa_u_a_bo_hashed_t*.
Takes a dpa_u_bo_t and a uint64_t containing the hash. The hash must be the same as would have been calculated using the dpa_u_bo_get_hash function. Allocates a new BO with a hash. This BO must be freed later using dpa_u_bo_free. The tagged BO pointer has the static flag set. Returns a dpa_u_a_bo_hashed_t*.
Takes a dpa_u_bo_t, a pointer to a dpa_u_refcount_freeable_t and a uint64_t containing the hash. The hash must be the same as would have been calculated using the dpa_u_bo_get_hash function. Allocates a new BO with a pointer to a refcount and a hash. If the refcount is static, the BO pointer is tagged as static. This BO must be freed later using dpa_u_bo_free. Returns a dpa_u_a_bo_hashed_t*.
Takes a BO object or a tagged BO pointer. The bo will be hashed, unless it already is hashed. Allocates a new BO with a hash. Returns a dpa_u_a_bo_hashed_t*.
Takes a dpa_u_bo_t. The bo will be hashed. Allocates a new BO with a hash. The tagged BO pointer has the static flag set. Returns a dpa_u_a_bo_hashed_t*.
Takes a dpa_u_bo_t and a pointer to a dpa_u_refcount_freeable_t. The bo will be hashed. The hash must be the same as would have been calculated using the dpa_u_bo_get_hash function. Allocates a new BO with a pointer to a refcount and a hash. If the refcount is static, the BO pointer is tagged as static. Returns a dpa_u_a_bo_hashed_t*.
Takes a dpa_u_a_bo_unique_t, returns a uint64_t. This uint64_t can be turned back into a dpa_u_a_bo_unique_t using dpa_u_bo_unique_from_uint. Think of it as casting the tagged pointer to a uint64_t. Although, the tagged BO pointers are actually implemented using a uint64_t, so nothing is really converted.
This turns a uint64_t back into a dpa_u_a_bo_unique_t. This is the reverse of the dpa_u_bo_unique_to_uint function.
In case of a dpa_u_a_bo_unique_t, this does nothing, the same pointer is returned. Otherwise, it removes refcounted and static BO pointer tags, and returns a dpa_u_a_bo_any_t tag. This is useful if the BO may change later, but the function it is passed to may store it but shouldn't be affected by the changes to the BO. Removing these tags forces the BO to be copied in that case if necessary.
Returns a pointer to the BOs data.
Get the size of the BO.
Get the hash of the BO. If the BO doesn't have a hash pre-calculated, it calculates the hash.
Returns a pointer to a dpa_u_refcount_freeable_t. If it is a unique BO, this is the refcount of the BO object. Otherwise, it is only the refcount of the data. If there is no refcount, it returns dpa_u_refcount_v_static, which is a global refcount which will never reach 0.