DAP-Utils - Buffer Object (BO)

Types

Tagged BO pointers - dpa_u_a_bo_*

The following tagged poiter types exist:
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.
The tag of a tagged BO Pointer consists of a set of types, and in the case of an inline BO, the size of the data.
The following Tags exist:
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.

BO Types - dpa_u_bo_*

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.

dpa_u_bo_t

TypeNameDescription
size_tsizeThe size of the BO.
const char*dataA pointer to the data

Object lifetimes

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.

Functions

dpa_u_bo­_copy­_maybe

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.

dpa_u_bo­_copy­_bo­_maybe

Unlike dpa_u_bo­_copy­_maybe, this function does not copy the BOs data. Everything else is the same. Only use this function if the data is known to have a sufficient lifetime.

dpa_u_bo­_ref

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.

dpa_u_bo­_put

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.

dpa_u_bo­_is_error

Takes a tagged BO pointer. If it is an error object, returns true. Otherwise, it returns false.

dpa_u_bo­_error

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.

dpa_u_bo­_error­_to_errno

Takes an error object. If it corrensponds to a known errno value, that value is returned. Otherwiese, -1 is returned.

dpa_u_bo­_is­_same

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.

dpa_u_bo­_is­_equal

Returns true if the BOs have the same size & data, false otherwise.

dpa_u_bo­_compare

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.

dpa_u_bo­_compare_data

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 qa sort is going to have.

Conversion Functions

dpa_u_bo­_intern

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.

dpa_u_to_bo

Returns an lvalue reference to the BO.

dpa_u_to_bo_any

Returns a dpa_u_a_bo­_any_t to the specified BO.

dpa_u_to_bo_any_static

Returns a dpa_u_a_bo­_any_t to the specified BO. It is tagged as a static BO.

dpa_u_to_bo_gc

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.

dpa_u_to_bo_gc_static

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.

dpa_u_make_bo_any_with_refcount

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*.

dpa_u_make_bo_any_with_hash

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*.

dpa_u_make_bo_any_static_with_hash

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*.

dpa_u_make_bo_any_with_refcount_hash

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*.

dpa_u_make_bo_gc_with_refcount

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*.

dpa_u_make_bo_gc_static_with_hash

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*.

dpa_u_make_bo_gc_with_refcount_hash

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*.

dpa_u_alloc_bo_any_with_refcount

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*.

dpa_u_alloc_bo_any_with_hash

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*.

dpa_u_alloc_bo_any_static_with_hash

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*.

dpa_u_alloc_bo_any_with_refcount_hash

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*.

dpa_u_alloc_bo_gc_with_refcount

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*.

dpa_u_alloc_bo_gc_static_with_hash

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*.

dpa_u_alloc_bo_gc_with_refcount_hash

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*.

dpa_u_bo­_unique­_to­_uint

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.

dpa_u_bo­_unique_from_uint

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.

Pointer tagging functions

dpa_u_bo_needs_copy

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.

Member access Functions

dpa_u_bo_get_data

Returns a pointer to the BOs data.

dpa_u_bo_get_size

Get the size of the BO.

dpa_u_bo_get_hash

Get the hash of the BO. If the BO doesn't have a hash pre-calculated, it calculates the hash.

dpa_u_bo_get_refcount

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. Returns 0 if there is no refcount, including if there is a unique BO.