Collections
PBArrayprovides dynamically-growable arrays (aka buffers)PBHashTableprovides building blocks for dictionaries and setsPBPoolandPBSlotTablemaps data to dense indices
Define an array type with PBArrayType(ElementType) and operate on it via "method" macros.
Example use:
typedef struct {
int a, b;
} Foo;
typedef PBArrayType(Foo) FooArray;
Type generated by PBArrayType(T):
struct {
T* nullable v;
usize len;
usize cap;
}
Predefined array types:
PBI8Arraywith element typei8PBI16Arraywith element typei16PBI32Arraywith element typei32PBI64Arraywith element typei64PBU8Arraywith element typeu8PBU16Arraywith element typeu16PBU32Arraywith element typeu32PBU64Arraywith element typeu64PBF32Arraywith element typef32PBF64Arraywith element typef64PBPtrArraywith element typevoid*
PBI8Array
typedef PBArrayType(i8) PBI8Array;
PBI16Array
typedef PBArrayType(i16) PBI16Array;
PBI32Array
typedef PBArrayType(i32) PBI32Array;
PBI64Array
typedef PBArrayType(i64) PBI64Array;
PBU8Array
typedef PBArrayType(u8) PBU8Array;
PBU16Array
typedef PBArrayType(u16) PBU16Array;
PBU32Array
typedef PBArrayType(u32) PBU32Array;
PBU64Array
typedef PBArrayType(u64) PBU64Array;
PBF32Array
typedef PBArrayType(f32) PBF32Array;
PBF64Array
typedef PBArrayType(f64) PBF64Array;
PBPtrArray
typedef PBArrayType(void*) PBPtrArray;
PBArrayStructStaticAssertLayout
PBArrayStructStaticAssertLayout is a helper for custom-defined array structs that need to be ABI compatible with PBArray functions. Example: typedef struct { const void* nullable ptr; usize len; usize cap; } MyArray; PBArrayStructStaticAssertLayout(MyArray);
PBAnyArray
typedef PBArrayType(void*) PBAnyArray;
PBAnyArray represents "an array of unknown/any type" The field name is intentionally different from other types to catch mistakes.
PBAnyArrayResize
bool PBAnyArrayResize(PBAnyArray* a,
usize elemSize,
PBMem ma,
usize newCap,
u32 maFlags);
PBAnyArrayResize resizes capacity to hold at least newCap elements.
If newCap is smaller than current length, length is truncated.
PBAnyArrayRemove
void PBAnyArrayRemove(PBAnyArray* arg,
usize elemSize,
usize start,
usize len);
PBAnyArrayRemove removes len elements starting at index start.
PBAnyArrayAlloc
void* PBAnyArrayAlloc(PBAnyArray* arg,
usize elemSize,
PBMem arg,
usize len);
PBAnyArrayAlloc appends len uninitialized elements and returns pointer to the first one.
- Returns: NULL if capacity growth fails or if
len==0.
PBAnyArrayAllocAt
void* PBAnyArrayAllocAt(PBAnyArray* arg,
usize elemSize,
PBMem arg,
usize i,
usize len);
PBAnyArrayAllocAt inserts len uninitialized elements at index i.
- Returns: NULL if capacity growth fails.
PBAnyArrayReserve
bool PBAnyArrayReserve(PBAnyArray* arg,
usize elemSize,
PBMem arg,
usize nitems);
PBAnyArrayReserve ensures at least nitems spare capacity beyond current length.
PBAnyArrayReserveExact
bool PBAnyArrayReserveExact(PBAnyArray* arg,
usize elemSize,
PBMem arg,
usize nitems);
PBAnyArrayReserveExact grows capacity to satisfy nitems spare slots without geometric extra growth.
PBAnyArrayGrow
bool PBAnyArrayGrow(PBAnyArray* a,
usize elemSize,
PBMem ma,
usize minavail);
PBAnyArrayGrow grows by at least minavail additional slots.
PBAnyArrayFree
void PBAnyArrayFree(PBAnyArray* a,
usize elemSize,
PBMem ma);
PBAnyArrayFree releases backing storage for a.
PBAnyArrayInsert
bool PBAnyArrayInsert(PBAnyArray* arg,
usize elemSize,
PBMem ma,
usize i,
const void* src,
usize len);
PBAnyArrayInsert inserts len elements copied from src at index i.
elemSize: size of one element. Must be>0.ma: memory allocator to use in case array needs to grow. Must be same allocator used for all memory operations on this array.i: Index at which to insert elements.i=0means "insert at beginning",i=lenmeans insert at end. Value must be<=len.src: Pointer to elements to copy into the arraylen: Number of element atsrc. Must be>0.- Returns: true on success, false on allocation failure.
PBAnyArrayMove
macro void PBAnyArrayMove(PBAnyArray* a, usize elemSize, usize dst, usize start, usize end)
PBAnyArrayRot
void PBAnyArrayRot(usize stride,
void* v,
usize first,
usize mid,
usize last);
PBAnyArrayRot rotates range [first,last) around pivot mid for elements of size stride bytes.
PBAnyArrayRot32
void PBAnyArrayRot32(const u32* v,
usize first,
usize mid,
usize last);
PBAnyArrayRot32 rotates range [first,last) around mid for arrays of u32 elements.
PBAnyArrayRot64
void PBAnyArrayRot64(const u64* v,
usize first,
usize mid,
usize last);
PBAnyArrayRot64 rotates range [first,last) around mid for arrays of u64 elements.
PBAnyArray_INIT_WITH_STORAGE
macro void PBAnyArray_INIT_WITH_STORAGE(T* structPtr, NAME arrayField, NAME storageField)
PBAnyArray_INIT_WITH_STORAGE allows initializing struct-member arrays with external storage. This is particularly useful when the common case is know up front and space can be allocated ahead of time. When the array needs to grow, the array implementation will check for storage pointing to directly before itself to determine if it owns that memory or not.
Initial storage must be located directly before the array struct. The array implementation relies on this to avoid free'ing your storage as the array grows.
Example:
struct MyThing {
int x;
};
struct MyThings {
MyThing thingsStorage[4];
PBArrayType(MyThing) things;
};
void example(void) {
MyThings m = { 0 };
PBAnyArray_INIT_WITH_STORAGE(&m, things, thingsStorage);
}
PBArrayInit
macro void PBArrayInit(ArrayType* array)
Initializes array to zero in preparation for use.
PBArrayFrom
macro ArrayType PBArrayFrom(ArrayType, PBMem ma, T* src, usize len)
- Returns: an instance of
ArrayTypepre-populated withlenitems pointed to bysrc.
PBArrayFree
macro void PBArrayFree(ArrayType* array, PBMem ma)
Frees the backing memory associated with the array instance pointed to by array.
PBArrayClear
macro void PBArrayClear(ArrayType* array)
Resets length of the array pointed to by array to zero.
PBArrayAt
macro T PBArrayAt(ArrayType* array, usize at)
- Returns: a copy of the item stored in
arrayatindexat.
PBArrayRefAt
macro T* PBArrayRefAt(ArrayType* array, usize at)
- Returns: a pointer to the item stored in
arrayatindexat.
PBArrayPush
macro bool PBArrayPush(ArrayType* array, PBMem ma, T item)
Pushes item onto the end of the array pointed to by array.
- Returns:
falseif capacity growth fails.
PBArrayPop
macro T PBArrayPop(ArrayType* array)
Removes the last item in the array.
- Returns: the last item in the
array.
PBArrayAlloc
macro T* PBArrayAlloc(ArrayType* array, PBMem ma, usize len)
Appends len uninitialized elements to the array pointed to by array.
- Returns: NULL if capacity growth fails, otherwise a pointer to first new item.
PBArrayAllocAt
macro T* PBArrayAllocAt(ArrayType* array, PBMem ma, usize at, usize len)
Inserts len uninitialized elements into the array pointed to by array at index at.
- Returns: NULL if capacity growth fails, otherwise a pointer to first new item.
PBArrayResize
macro bool PBArrayResize(ArrayType* array, PBMem ma, usize newCap, u32 maFlags)
Resizes capacity to hold at least newCap elements. If newCap is smaller than current length, length is truncated.
- Returns:
falseif capacity growth fails.
PBArrayReserve
macro bool PBArrayReserve(ArrayType* array, PBMem ma, usize nItems)
Ensures at least nItems spare capacity beyond current length.
- Returns:
falseif capacity growth fails.
PBArrayReserveExact
macro bool PBArrayReserveExact(ArrayType* array, PBMem ma, usize nItems)
Grows capacity to satisfy nItems spare slots without geometric extra growth.
- Returns:
falseif capacity growth fails.
PBArrayShrinkwrap
macro bool PBArrayShrinkwrap(ArrayType* array, PBMem ma)
Resizes memory so that cap=len. Note that cap>len might still be true depending on the memory allocator's implementation.
- Returns:
falseon failure.
PBArrayAppend
macro bool PBArrayAppend(ArrayType* array, PBMem ma, T* src, usize srcLen)
Pushes srcLen items from src to the end of the array pointed to by array.
- Returns:
falseon failure.
PBArrayInsert
macro bool PBArrayInsert(ArrayType* array, PBMem ma, usize at, T* src, usize srcLen)
Inserts srcLen items from src into the array pointed to by array starting at index at.
- Returns:
falseon failure.
PBArrayRemove
macro void PBArrayRemove(ArrayType* array, usize start, usize len)
Removes len items from the array pointed to by array starting at index start.
PBArrayMove
macro void PBArrayMove(ArrayType* array, usize dstPos, usize start, usize end)
Moves the items within the array pointed at by array between [start, end) to the new index dstPos.
PBArrayEq
macro bool PBArrayEq(ArrayType* array, T* ptr, usize ptrLen)
- Returns: true if
ptrLenequalsarray's length and all the bytes in the array equal those pointed to byptr.
PBArrayCmp
macro int PBArrayCmp(ArrayType* array, T* ptr, usize ptrLen)
- Returns: <0 if the contents of
arrayis bytewise less than the contents ofptr, >1 ifptr<array, 0 ifarray==ptr.
PBArrayFromSlice
macro ArrayType PBArrayFromSlice(ArrayType, PBMem ma, SliceType slice)
- Returns: a new array of type
ArrayTypewith a copy of the items inslice.
PBArraySlice
macro SliceType PBArraySlice(SliceType, ArrayType* array, usize start, usize rangeLen)
- Returns: a new slice of type
SliceTypereferencing the items inarraystarting at indexstartand withrangeLenlength.
PBBuf
typedef PBArrayType(u8) PBBuf;
PBBuf is a growable byte buffer, binary compatible with PBU8Array
PBBufFromStrSlice
PBBuf PBBufFromStrSlice(PBMem ma,
PBStrSlice source);
PBBufCStr
char* PBBufCStr(PBBuf* buf,
PBMem ma);
PBBufCStr inserts a trailing \0, but does not increment len. Thus, the \0 byte will be overwritten by future modifications.
- Returns: a pointer to
buf->v, or NULL if memory could not be allocated.
PBBufAppendHex
bool PBBufAppendHex(PBBuf* buf,
PBMem ma,
const u8* bytes,
usize len);
PBBufAppendHex appends hexadecimal encoding of bytes to buf. buf->len will be extended by len * 2.
- Returns: true on success, false if memory could not be allocated
PBBufOf
PBBuf PBBufOf(PBMem ma,
const void* value,
...);
PBBufOf allocates a copy of value using memory allocator ma.
It's implemented as a generic macro, with the following effective signature:
PBBuf PBBufOf<T is PBStrSlice|PBStr|PBBuf|const char*>(T v[, usize start, [usize len]])
The caller should check for OOM, e.g.
if (buf.len == 0 && from.len > 0)
panic("OOM");
PBBufEq
PBBufEq is implemented as a generic macro, with the following effective signature:
bool PBBufEq<A is convertible to PBStrSlice, B is convertible to PBStrSlice>(A a, B b)
- Returns: true if a is equal to b.
PBBuf_INIT_WITH_STORAGE
void PBBuf_INIT_WITH_STORAGE(T* structPtr, NAME bufField, NAME storageField)
PBBuf_INIT_WITH_STORAGE allows initializing struct-member buffer with external storage. This is particularly useful when the common case is know up front and space can be allocated ahead of time. When the buffer needs to grow, the buffer implementation will check for storage pointing to directly before itself to determine if it owns that memory or not.
Initial storage storageField must be located directly before the PBBuf bufField in your struct. The buffer implementation relies on this to avoid free'ing your storage as the buffer grows.
Example:
struct MyFormatter {
u8 bufStorage[64];
PBBuf buf;
};
void example(void) {
MyFormatter formatter = { 0 };
PBAnyArray_INIT_WITH_STORAGE(&formatter, buf, bufStorage);
}
PBRingBuf
typedef struct PBRingBuf {
u8* nullable v;
usize cap;
usize off;
usize len;
} PBRingBuf;
PBRingBufEnsureWriteCapacity
bool PBRingBufEnsureWriteCapacity(PBRingBuf* rb,
PBMem ma,
usize minLen,
usize align);
PBRingBufWriteReserve
u8* PBRingBufWriteReserve(PBRingBuf* rb,
PBMem ma,
usize minLen,
usize align);
PBRingBufWriteReserve returns contiguous space for at least minLen bytes at the logical tail.
The caller must follow with PBRingBufProduce after writing bytes into the returned storage.
The returned pointer is aligned to align, which must be 0, 1, or a power of two.
- Returns: NULL on allocation failure.
PBRingBufProduce
void PBRingBufProduce(PBRingBuf* rb,
usize n);
PBRingBufProduce makes n newly written bytes visible at the tail.
The caller must have previously reserved enough space with PBRingBufWriteReserve.
PBRingBufConsume
usize PBRingBufConsume(PBRingBuf* rb,
usize n);
PBRingBufConsume removes up to n bytes from the logical head.
- Returns: Number of bytes consumed.
#include <playbit/hashtable.h>
Fundamental hash table
PBHashTableEqFn
typedef bool (*PBHashTableEqFn)(const void * _Nonnull, const void * _Nonnull);
PBHashTableHashFn
typedef usize (*PBHashTableHashFn)(usize, const void * _Nonnull);
PBHashTable
typedef struct PBHashTable {
PBMem ma;
usize seed; // hash seed passed to hashfn
usize cap; // capacity
usize load; // current number of entries stored in the table
void* entries;
} PBHashTable;
PBHashTableInit
bool PBHashTableInit(PBHashTable* arg,
int ma,
usize entsize,
usize capHint);
PBHashTableInit initializes ht with capacity hint capHint.
- Returns: false on allocation failure.
PBHashTableFree
void PBHashTableFree(PBHashTable* ht);
PBHashTableFree releases all memory owned by ht.
PBHashTableClear
void PBHashTableClear(PBHashTable* ht,
usize entsize);
PBHashTableClear removes all entries from the hashtable
PBHashTableAssign
void* PBHashTableAssign(PBHashTable* ht,
usize entsize,
PBHashTableHashFn hashfn,
PBHashTableEqFn eqfn,
const void* keyEntry,
bool* added);
PBHashTableAssign returns a pointer to the entry, or NULL if out of memory. If an entry equivalent to keyent is found, *added is set to false. Otherwise a new entry is inserted and keyent is copied to it, *added is true.
PBHashTableLookup
void* PBHashTableLookup(const PBHashTable* ht,
usize entsize,
PBHashTableHashFn hashfn,
PBHashTableEqFn eqfn,
const void* keyEntry);
PBHashTableLookup returns a pointer to an entry equivalent to keyent, or NULL if not found.
PBHashTableDelete
bool PBHashTableDelete(PBHashTable* ht,
usize entsize,
PBHashTableHashFn hashfn,
PBHashTableEqFn eqfn,
const void* keyent);
PBHashTableDelete removes an entry equivalent to keyent.
Optimization detail: if keyent is a pointer to an entry in ht, for example from PBHashTableLookup, no additional lookup is performed internally.
- Returns: false if not found.
PBHashTableIter
PBHashTableIter iterates over entries of a hash table (in undefined order.)
To begin iteration, set entryp=NULL.
Example:
for (const MyEntry entry = NULL; PBHashTableIter(&ht, &entry);) {
print(">> %u", entry->value);
bool PBHashTableIter(const PBHashTable* ht, T** entryp)
PBHashTableIterx
bool PBHashTableIterx(const PBHashTable* ht,
usize entsize,
const void* entryp);
PBHashTableIterx advances iteration of ht in unspecified order.
Set *entryp = NULL before first call. Returns false when iteration is complete.
PBPool maps data to dense indices. It's like a slab allocator that uses u32 integers as addresses. Think "file descriptor allocator" rather than "virtual-memory allocator." Tries to be cache friendly by using the smallest free index during allocation.
Note: PBSlotTable (slot_table.h) may be a more fitting container if you need stable addresses (pointers) for entries. Pointers to entries of a PBPool are only valid until the next modification of the pool.
PBPool
typedef struct PBPool {
u32 cap; // capacity, a multiple of 64
u32 maxidx; // max allocated index
u64 freebm[]; // bitmap; bit=1 means entries[bit] is free
// TYPE entries[];
} PBPool;
PBPoolCreate
bool PBPoolCreate(PBPool* pp,
usize elemSize,
PBMem ma,
u32 cap);
PBPoolCreate creates a new pool. *pp is assumed to be NULL.
- Returns: false if memory could not be allocated.
PBPoolFree
void PBPoolFree(PBPool* p,
int ma);
PBPoolFree recycles the memory of p back to memory allocator ma.
PBPoolEntryAlloc
void* PBPoolEntryAlloc(PBPool* pp,
usize elemSize,
int ma,
u32* idxOut);
PBPoolEntryAlloc allocates an entry with the lowest index in the pool *pp. If the pool is full, the pool's memory at *pp is resized (and likely moved). The returned pointer (address) is valid until the next modification of the pool. Use PBPoolEntryFree to recycle an allocated entry.
- Returns: NULL if memory allocation failed.
PBPoolEntryAllocIfRoom
void* PBPoolEntryAllocIfRoom(PBPool* p,
usize elemSize,
int ma,
u32* idxOut);
PBPoolEntryAllocIfRoom allocates an entry with the lowest index in the pool *pp. The returned pointer (address) is valid until the next modification of the pool. Use PBPoolEntryFree to recycle an allocated entry.
- Returns: NULL if the pool is full (does not grow pool memory like
PBPoolEntryAlloc.)
PBPoolEntryFree
void PBPoolEntryFree(PBPool* p,
u32 idx);
PBPoolEntryFree frees the entry at idx. Panics if idx is out of bounds or points to an already free entry.
PBPoolEntryFreeAll
void PBPoolEntryFreeAll(PBPool* p);
PBPoolEntryFreeAll frees all entries of the pool in one very cheap operation.
PBPoolEntryIsFree
bool PBPoolEntryIsFree(const PBPool* p,
u32 idx);
PBPoolEntryIsFree returns true when idx currently refers to a free slot.
- Returns: false for
idx==0oridxbeyond current capacity.
PBPoolEntries
u8* PBPoolEntries(const PBPool* p);
PBPoolEntries returns a pointer to the array of entries. You can index directly into this with: MyEntry* entry = &((MyEntry*)PBPoolEntries(p))[idx-1] The returned array is valid until the next modification of the pool.
PBPoolEntry
void* PBPoolEntry(const PBPool* p,
usize elemSize,
u32 idx);
PBPoolEntry accesses entry with index idx.
Panics if idx is out of bounds.
- Returns: pointer to entry
idx. The returned pointer (address) is valid until the next modification of the pool.
PBPoolFindEntry
u32 PBPoolFindEntry(const PBPool* p,
usize elemSize,
const void* entryPtr);
PBPoolFindEntry performs a reverse lookup, finding the idx for an entry with identical bytes of memory as the memory at entryPtr. Basically a linear scan with memcmp.
- Returns: 0 when no matching entry exists.
PBPoolIdxIsDead
bool PBPoolIdxIsDead(const PBPool* p,
u32 idx);
PBPoolIdxIsDead reports whether idx has never been allocated in the current lifetime of p
#include <playbit/slot_table.h>
PBSlotTable maps data to dense indices. It's like a slab allocator that uses u32 integers as addresses. Think "file descriptor allocator" rather than "virtual-memory allocator."
Tries to be cache friendly by using the smallest free index during allocation.
PBSlotTable is an evolution of PBPool with the main difference being stable pointers, i.e. a pointer returned by PBSlotTableGet remains valid for the lifetime of the table, even when the table grows. PBPool does not have the same guarantee.
PBSlotTableCreate
PBSlotTableCreate creates a new table with initial capacity for cap entries of elemSize size.
Note that the table is implemented as a list of blocks of entries, each holding cap entries. This means that cap should be a reasonably large number. cap will be rounded up to the nearest multiple of 64.
PBSlotTable* nullable PBSlotTableCreate(type T, PBMem ma, u32 cap)
- Returns: NULL if memory could not be allocated.
PBSlotTableFree
void PBSlotTableFree(PBSlotTable* table,
PBMem ma);
PBSlotTableFree frees table back to memory allocator ma
PBSlotTableAdd
PBSlotTableAdd allocates an entry with the lowest index in the table.
On success, the returned memory region is zeroed and guaranteed to remain valid until either the entry is freed by a call to PBSlotTableDel, the table is cleared with PBSlotTableClear or the table is freed. I.e. even when the table grows, to accommodate more entires, the address of existing entries remain valid. This is a really useful invariant when you want to hold on to pointers.
T PBSlotTableAdd(type T, PBSlotTable* table, PBMem ma, u32* idxOut)
- Returns: NULL if memory allocation failed.
PBSlotTableDel
void PBSlotTableDel(PBSlotTable* table,
u32 idx);
PBSlotTableDel frees the entry at idx.
PBSlotTableGet
PBSlotTableGet accesses entry with index idx.
T* PBSlotTableGet(type T, PBSlotTable* table, u32 idx)
PBSlotTableIsUsed
bool PBSlotTableIsUsed(PBSlotTable* table,
u32 idx);
PBSlotTableIsUsed returns true if entry at idx is in use (i.e. is not free.)
Note: Returns true if idx is out of bounds (rather than panicing.)
PBSlotTableClear
void PBSlotTableClear(PBSlotTable* table);
PBSlotTableClear frees all entries in one efficient operation.
PBSlotTableBlock
struct PBSlotTableBlock {
PBSlotTableBlock* nullable next;
u8 entries[];
};
PBSlotTable
struct PBSlotTable {
u32 cap; // capacity of entire table
u32 blockCap; // capacity of one block
u32 maxidx; // max allocated index
u64* freebm; // bitmap; bit=1 means entries[bit] is free
PBSlotTableBlock block;
};
PBSlotTableCreate1
PBSlotTable* PBSlotTableCreate1(usize elemSize,
PBMem ma,
u32 cap);
PBSlotTableCreate1 is the size-based worker behind PBSlotTableCreate.
PBSlotTableAdd1
void* PBSlotTableAdd1(PBSlotTable* table,
usize elemSize,
PBMem ma,
u32* idxOut);
PBSlotTableAdd1 is the size-based worker behind PBSlotTableAdd.
PBSlotTableGet1
void* PBSlotTableGet1(PBSlotTable* table,
usize elemSize,
u32 idx);
PBSlotTableGet1 is the size-based worker behind PBSlotTableGet.
A ring buffer, aka circular buffer aka FIFO. Note: PBQueue is not thread safe; single producer, single consumer only.
PBQueueAny
typedef PBQueue(void) PBQueueAny;
PBQueueAnyInit
PBSysErr PBQueueAnyInit(PBQueueAny* q,
u32 entrySize,
PBMem ma,
u32 cap);
PBQueueAnyInit initializes q with usable capacity cap entries of size entrySize.
PBQueueAnyFree
void PBQueueAnyFree(PBQueueAny* q,
PBMem ma);
PBQueueAnyFree releases storage owned by q.
PBQueueAnyLen
u32 PBQueueAnyLen(const PBQueueAny* q);
PBQueueAnyLen returns number of queued entries currently available to pop/remove.
PBQueueAnyPushIfRoom
void* PBQueueAnyPushIfRoom(PBQueueAny* q,
u32 entrySize);
PBQueueAnyPushIfRoom reserves one entry slot at tail without growing q.
- Returns: NULL if queue is full.
PBQueueAnyPush
void* PBQueueAnyPush(PBQueueAny* q,
u32 entrySize,
PBMem ma);
PBQueueAnyPush reserves one entry slot at tail, growing q when necessary.
- Returns: NULL on allocation failure.
PBQueueAnyPop
void* PBQueueAnyPop(PBQueueAny* q,
u32 entrySize);
PBQueueAnyPop removes one entry from head and returns pointer to its storage.
- Returns: NULL if queue is empty.
PBQueueAnyPopMany
u32 PBQueueAnyPopMany(PBQueueAny* q,
u32 entrySize,
void* dst,
u32 dstCap);
PBQueueAnyPopMany pops up to dstCap entries from head into dst.
- Returns: Number of entries copied and removed.
PBQueueAnyRemove
u32 PBQueueAnyRemove(PBQueueAny* q,
u32 limit);
PBQueueAnyRemove removes up to limit newest entries from tail.
- Returns: Number of entries removed.
PBQueueIter
typedef struct PBQueueIter {
u32 i; // current index
u32 remaining; // entries left
} PBQueueIter;
PBQueueAnyIterCreate
PBQueueIter PBQueueAnyIterCreate(const PBQueueAny* q,
u32 entrySize);
PBQueueAnyIterCreate snapshots iteration state for q at this instant.
Later pushes or pops do not update this iterator; iteration walks the queued entries visible when the iterator was created.
PBQueueAnyIterNext
void* PBQueueAnyIterNext(const PBQueueAny* q,
PBQueueIter* it,
u32 entrySize);
Multi-dimensional vector types with SIMD acceleration.
These types are special N dimensional vector types which directly maps to target-CPU-agnostic SIMD types. They enables efficient SIMD operations and is usable in general-purpose code.
Vector types may not be available for all compilation targets: PB_HAS_VECTOR_TYPES is set to 1 if vector types are supported, 0 if not.
These types allow element access via:
- the array subscript operator
[index] sNwhereNis a hexadecimal valuex,y,z,wfor graphics-style indexing
StaticExpect(PB_HAS_VECTOR_TYPES, "vector type support");
PBF32x4 v = {1.1, 2.2, 3.3, 4.4};
expect(v.x == 1.1f); expect(v[0] == 1.1f);
expect(v.y == 2.2f); expect(v[1] == 2.2f);
expect(v.z == 3.3f); expect(v[2] == 3.3f);
expect(v.w == 4.4f); expect(v[3] == 4.4f);
Note that all these types have at least 16 byte alignment. Use alignof(T or expr) to access actual alignment.
PBU16x4
typedef u16 __attribute__((ext_vector_type(4))) PBU16x4;
PBF32x2
typedef f32 __attribute__((ext_vector_type(2))) PBF32x2;
PBF32x3
typedef f32 __attribute__((ext_vector_type(3))) PBF32x3;
PBF32x4
typedef f32 __attribute__((ext_vector_type(4))) PBF32x4;
PBF32x6
typedef f32 __attribute__((ext_vector_type(6))) PBF32x6;
PBF32x8
typedef f32 __attribute__((ext_vector_type(8))) PBF32x8;
PBF32x16
typedef f32 __attribute__((ext_vector_type(16))) PBF32x16;
PBF32x32
typedef f32 __attribute__((ext_vector_type(32))) PBF32x32;
PBF32x64
typedef f32 __attribute__((ext_vector_type(64))) PBF32x64;
PBF16x2
typedef f16 __attribute__((ext_vector_type(2))) PBF16x2;
PBF16x3
typedef f16 __attribute__((ext_vector_type(3))) PBF16x3;
PBF16x4
typedef f16 __attribute__((ext_vector_type(4))) PBF16x4;
PBF16x6
typedef f16 __attribute__((ext_vector_type(6))) PBF16x6;
PBF16x8
typedef f16 __attribute__((ext_vector_type(8))) PBF16x8;
PBF16x16
typedef f16 __attribute__((ext_vector_type(16))) PBF16x16;
PBF16x32
typedef f16 __attribute__((ext_vector_type(32))) PBF16x32;
PBF16x64
typedef f16 __attribute__((ext_vector_type(64))) PBF16x64;
PBF16x128
typedef f16 __attribute__((ext_vector_type(128))) PBF16x128;