/** * Copyright (C) Mellanox Technologies Ltd. 2001-2013. ALL RIGHTS RESERVED. * * See file LICENSE for terms. */ #ifndef PTR_ARRAY_H_ #define PTR_ARRAY_H_ #include #include /* * Array element layout: * * 64 32 1 0 * +-----------------+----------------+---+ * free: | placeholder | next index | 1 | * +-----------------+----------------+---+ * used: | user pointer | 0 | * +-----------------+----------------+---+ * * */ typedef uint64_t ucs_ptr_array_elem_t; /** * A sparse array of pointers. * Free slots can hold 32-bit placeholder value. */ typedef struct ucs_ptr_array { uint32_t init_placeholder; ucs_ptr_array_elem_t *start; unsigned freelist; unsigned size; #if ENABLE_MEMTRACK char name[64]; #endif } ucs_ptr_array_t; /* Flags added to lower bits of the value */ #define UCS_PTR_ARRAY_FLAG_FREE ((unsigned long)0x01) /* Slot is free */ #define UCS_PTR_ARRAY_PLCHDR_SHIFT 32 #define UCS_PTR_ARRAY_PLCHDR_MASK (((ucs_ptr_array_elem_t)-1) & ~UCS_MASK(UCS_PTR_ARRAY_PLCHDR_SHIFT)) #define UCS_PTR_ARRAY_NEXT_SHIFT 1 #define UCS_PTR_ARRAY_NEXT_MASK (UCS_MASK(UCS_PTR_ARRAY_PLCHDR_SHIFT) & ~UCS_MASK(UCS_PTR_ARRAY_NEXT_SHIFT)) #define UCS_PTR_ARRAY_SENTINEL (UCS_PTR_ARRAY_NEXT_MASK >> UCS_PTR_ARRAY_NEXT_SHIFT) #define __ucs_ptr_array_is_free(_elem) \ ((uintptr_t)(_elem) & UCS_PTR_ARRAY_FLAG_FREE) /** * Initialize the array. * * @param init_placeholder Default placeholder value. */ void ucs_ptr_array_init(ucs_ptr_array_t *ptr_array, uint32_t init_placeholder, const char *name); /** * Cleanup the array. * All values should already be removed from it. */ void ucs_ptr_array_cleanup(ucs_ptr_array_t *ptr_array); /** * Insert a pointer to the array. * * @param value Pointer to insert. Must be 8-byte aligned. * @param placeholder Filled with placeholder value. * @return The index to which the value was inserted. * * Complexity: amortized O(1) * * Note: The array will grow if needed. */ unsigned ucs_ptr_array_insert(ucs_ptr_array_t *ptr_array, void *value, uint32_t *placeholder_p); /** * Remove a pointer from the array. * * @param index Index to remove from. * @param placeholder Value to put in the free slot. * * Complexity: O(1) */ void ucs_ptr_array_remove(ucs_ptr_array_t *ptr_array, unsigned index, uint32_t placeholder); /** * Replace pointer in the array * @param index index of slot * @param new_val value to put into slot given by index * @return old value of the slot */ void *ucs_ptr_array_replace(ucs_ptr_array_t *ptr_array, unsigned index, void *new_val); /** * Retrieve a value from the array. * * @param index Index to retrieve the value from. * @param value Filled with the value. * @return Whether the value is present and valid. * * Complexity: O(1) */ #define ucs_ptr_array_lookup(_ptr_array, _index, _var) \ (((_index) >= (_ptr_array)->size) ? \ (UCS_V_INITIALIZED(_var), 0) : \ !__ucs_ptr_array_is_free(_var = (void*)((_ptr_array)->start[_index]))) /** * Iterate over all valid elements in the array. */ #define ucs_ptr_array_for_each(_var, _index, _ptr_array) \ for (_index = 0; _index < (_ptr_array)->size; ++_index) \ if (!__ucs_ptr_array_is_free(_var = (void*)((_ptr_array)->start[_index]))) \ #endif /* PTR_ARRAY_H_ */