el->kq = -1; /* So destructor can be used before kqueue() provides us with fd */
talloc_set_destructor(el, _event_list_free);
- el->times = fr_lst_talloc_alloc(el, fr_event_timer_cmp, fr_event_timer_t, lst_id);
+ el->times = fr_lst_talloc_alloc(el, fr_event_timer_cmp, fr_event_timer_t, lst_id, 0);
if (!el->times) {
fr_strerror_const("Failed allocating event lst");
error:
}
#ifdef LOCAL_PID
- el->pids = fr_lst_talloc_alloc(el, fr_event_pid_cmp, fr_event_pid_t, lst_id);
+ el->pids = fr_lst_talloc_alloc(el, fr_event_pid_cmp, fr_event_pid_t, lst_id, 0);
if (!el->pids) {
fr_strerror_const("Failed allocating PID lst");
goto error;
RCSID("$Id$")
#include <freeradius-devel/util/lst.h>
+#include <freeradius-devel/util/misc.h>
#include <freeradius-devel/util/rand.h>
#include <freeradius-devel/util/strerror.h>
#define INITIAL_CAPACITY 2048
#define INITIAL_STACK_CAPACITY 32
+#define is_power_of_2(_n) ((_n) && (((_n) & ((_n) - 1)) == 0))
+
typedef unsigned int stack_index_t;
typedef struct {
* The index is visible for the size and length functions, since they need
* to know the subtree they're working on.
*/
-static inline CC_HINT(always_inline, nonnull)
-bool is_bucket(fr_lst_t *lst, stack_index_t idx)
+static inline CC_HINT(always_inline, nonnull) bool is_bucket(fr_lst_t *lst, stack_index_t idx)
{
return lst_length(lst, idx) == 1;
}
s->data[idx] = new_value;
}
-fr_lst_t *_fr_lst_alloc(TALLOC_CTX *ctx, fr_lst_cmp_t cmp, char const *type, size_t offset)
+fr_lst_t *_fr_lst_alloc(TALLOC_CTX *ctx, fr_lst_cmp_t cmp, char const *type, size_t offset, fr_lst_index_t init)
{
fr_lst_t *lst;
pivot_stack_t *s;
+ if (!init) {
+ init = INITIAL_CAPACITY;
+ } else if (!is_power_of_2(init)) {
+ init = 1 << fr_high_bit_pos(init);
+ }
+
/*
* Pre-allocate stack memory as it is
* unlikely to need to grow in practice.
lst = talloc_zero_pooled_object(ctx, fr_lst_t, 3, (INITIAL_STACK_CAPACITY * sizeof(fr_lst_index_t)));
if (unlikely(!lst)) return NULL;
- lst->capacity = INITIAL_CAPACITY;
+ lst->capacity = init;
lst->p = talloc_array(lst, void *, lst->capacity);
if (unlikely(!lst->p)) {
cleanup:
* @param[in] _cmp Comparator used to compare elements.
* @param[in] _type Of elements.
* @param[in] _field to store LST indexes in.
+ * @param[in] _init initial capacity (0 for default initial size);
+ * the capacity will be rounded up to a power of two.
+ * @return
+ * - A pointer to the new LST.
+ * - NULL on error
*/
-#define fr_lst_alloc(_ctx, _cmp, _type, _field) \
- _fr_lst_alloc(_ctx, _cmp, NULL, (size_t)offsetof(_type, _field))
+#define fr_lst_alloc(_ctx, _cmp, _type, _field, _init) \
+ _fr_lst_alloc(_ctx, _cmp, NULL, (size_t)offsetof(_type, _field), _init)
/** Creates an LST that verifies elements are of a specific talloc type
*
* @param[in] _cmp Comparator used to compare elements.
* @param[in] _talloc_type of elements.
* @param[in] _field to store heap indexes in.
+ * @param[in] _init initial capacity (0 for default initial size);
+ * the capacity will be rounded up to a power of two.
* @return
* - A pointer to the new LST.
* - NULL on error.
*/
-#define fr_lst_talloc_alloc(_ctx, _cmp, _talloc_type, _field) \
- _fr_lst_alloc(_ctx, _cmp, #_talloc_type, (size_t)offsetof(_talloc_type, _field))
+#define fr_lst_talloc_alloc(_ctx, _cmp, _talloc_type, _field, _init) \
+ _fr_lst_alloc(_ctx, _cmp, #_talloc_type, (size_t)offsetof(_talloc_type, _field), _init)
-fr_lst_t *_fr_lst_alloc(TALLOC_CTX *ctx, fr_lst_cmp_t cmp, char const *type, size_t offset) CC_HINT(nonnull(2));
+fr_lst_t *_fr_lst_alloc(TALLOC_CTX *ctx, fr_lst_cmp_t cmp, char const *type, size_t offset, fr_lst_index_t init) CC_HINT(nonnull(2));
/** Check if an entry is inserted into an LST.
*
fr_lst_t *lst;
lst_thing values[NVALUES];
- lst = fr_lst_alloc(NULL, lst_cmp, lst_thing, idx);
+ lst = fr_lst_alloc(NULL, lst_cmp, lst_thing, idx, NVALUES);
TEST_CHECK(lst != NULL);
populate_values(values, NUM_ELEMENTS(values));
TEST_CHECK(value != NULL);
TEST_CHECK(!fr_lst_entry_inserted(value->idx));
TEST_CHECK(value->data == i);
+ TEST_MSG("iteration %u, popped %u", i, value->data);
}
talloc_free(lst);
}
done_init = true;
}
- lst = fr_lst_alloc(NULL, lst_cmp, lst_thing, idx);
+ lst = fr_lst_alloc(NULL, lst_cmp, lst_thing, idx, 0);
TEST_CHECK(lst != NULL);
values = calloc(LST_TEST_SIZE, sizeof(lst_thing));
done_init = true;
}
- lst = fr_lst_alloc(NULL, lst_cmp, lst_thing, idx);
+ lst = fr_lst_alloc(NULL, lst_cmp, lst_thing, idx, 0);
TEST_CHECK(lst != NULL);
hp = fr_heap_alloc(NULL, lst_cmp, lst_thing, idx, 0);
array = calloc(BURN_IN_OPS, sizeof(lst_thing));
for (unsigned int i = 0; i < BURN_IN_OPS; i++) array[i].data = rand() % 65537;
- lst = fr_lst_alloc(NULL, lst_cmp, lst_thing, idx);
+ lst = fr_lst_alloc(NULL, lst_cmp, lst_thing, idx, 0);
for (unsigned int i = 0; i < BURN_IN_OPS; i++) {
lst_thing *ret_thing = NULL;
done_init = true;
}
- lst = fr_lst_alloc(NULL, lst_cmp, lst_thing, idx);
+ lst = fr_lst_alloc(NULL, lst_cmp, lst_thing, idx, 0);
TEST_CHECK(lst != NULL);
values = calloc(LST_CYCLE_SIZE, sizeof(lst_thing));
lst_thing values[NVALUES], *data;
- lst = fr_lst_alloc(NULL, lst_cmp, lst_thing, idx);
+ lst = fr_lst_alloc(NULL, lst_cmp, lst_thing, idx, 0);
TEST_CHECK(lst != NULL);
populate_values(values, NUM_ELEMENTS(values));
populate_values(values, count);
start_alloc = fr_time();
- lst = fr_lst_alloc(NULL, lst_cmp, lst_thing, idx);
+ lst = fr_lst_alloc(NULL, lst_cmp, lst_thing, idx, 0);
end_alloc = fr_time();
TEST_CHECK(lst != NULL);