aboutsummaryrefslogtreecommitdiffstats
path: root/hicn-light/src/hicn/base
diff options
context:
space:
mode:
Diffstat (limited to 'hicn-light/src/hicn/base')
-rw-r--r--hicn-light/src/hicn/base/bitmap.h126
-rw-r--r--hicn-light/src/hicn/base/common.h4
-rw-r--r--hicn-light/src/hicn/base/pool.c89
-rw-r--r--hicn-light/src/hicn/base/pool.h19
-rw-r--r--hicn-light/src/hicn/base/test/test-bitmap.cc122
-rw-r--r--hicn-light/src/hicn/base/test/test-pool.cc140
-rw-r--r--hicn-light/src/hicn/base/test/test-vector.cc96
-rw-r--r--hicn-light/src/hicn/base/vector.c43
-rw-r--r--hicn-light/src/hicn/base/vector.h52
9 files changed, 516 insertions, 175 deletions
diff --git a/hicn-light/src/hicn/base/bitmap.h b/hicn-light/src/hicn/base/bitmap.h
index 8fd9fcd70..4a78af567 100644
--- a/hicn-light/src/hicn/base/bitmap.h
+++ b/hicn-light/src/hicn/base/bitmap.h
@@ -23,7 +23,12 @@
#ifndef UTIL_BITMAP_H
#define UTIL_BITMAP_H
+#include <assert.h>
#include <string.h>
+#include <sys/param.h> // MIN, MAX
+
+#include <hicn/util/log.h>
+
#include "common.h"
#include "vector.h"
@@ -37,8 +42,9 @@ typedef uint_fast32_t bitmap_t;
* @param[in,out] bitmap Bitmap to allocate and initialize
* @param[in] max_size Bitmap max_size
*/
-#define bitmap_init(bitmap, max_size) \
- vector_init(bitmap, next_pow2(max_size / BITMAP_WIDTH(bitmap)))
+#define bitmap_init(bitmap, init_size, max_size) \
+ vector_init(bitmap, next_pow2(init_size / BITMAP_WIDTH(bitmap)), \
+ max_size == 0 ? 0 : next_pow2(max_size / BITMAP_WIDTH(bitmap)))
/*
* @brief Ensures a bitmap is sufficiently large to hold an element at the
@@ -51,7 +57,13 @@ typedef uint_fast32_t bitmap_t;
* - This function should always be called before writing to a bitmap element
* to eventually make room for it (the bitmap will eventually be resized).
*/
-#define bitmap_ensure_pos(bitmap, pos) vector_ensure_pos(bitmap, pos / BITMAP_WIDTH(bitmap))
+static inline
+int
+bitmap_ensure_pos(bitmap_t * bitmap, off_t pos)
+{
+ size_t offset = pos / BITMAP_WIDTH(bitmap);
+ return vector_ensure_pos(bitmap, offset);
+}
/**
* @brief Retrieve the state of the i-th bit in the bitmap.
@@ -59,7 +71,15 @@ typedef uint_fast32_t bitmap_t;
* @param[in] bitmap The bitmap to access.
* @param[in] i The bit position.
*/
-#define bitmap_get(bitmap, i) (((bitmap)[(i) / BITMAP_WIDTH(bitmap)] & (1 << ((i) % BITMAP_WIDTH(bitmap)))) >> ((i) % BITMAP_WIDTH(bitmap)))
+static inline
+int
+bitmap_get(const bitmap_t * bitmap, off_t i)
+{
+ size_t offset = i / BITMAP_WIDTH(bitmap);
+ size_t pos = i % BITMAP_WIDTH(bitmap);
+ size_t shift = BITMAP_WIDTH(bitmap) - pos - 1;
+ return (bitmap[offset] >> shift) & 1;
+}
/*
* @brief Returns whether the i-th bit is set (equal to 1) in a bitmap.
@@ -70,6 +90,7 @@ typedef uint_fast32_t bitmap_t;
* @return bool
*/
#define bitmap_is_set(bitmap, i) (bitmap_get((bitmap), (i)) == 1)
+#define bitmap_is_unset(bitmap, i) (bitmap_get((bitmap), (i)) == 0)
/*
* @brief Returns whether the i-th bit is unset (equal to 0) in a bitmap.
@@ -79,19 +100,94 @@ typedef uint_fast32_t bitmap_t;
*
* @return bool
*/
-#define bitmap_is_unset(bitmap, i) (bitmap_get((bitmap), (i)) == 0)
+static inline
+int
+bitmap_set(bitmap_t * bitmap, off_t i)
+{
+ if (bitmap_ensure_pos(bitmap, i) < 0)
+ return -1;
+ size_t offset = i / BITMAP_WIDTH(bitmap);
+ size_t pos = i % BITMAP_WIDTH(bitmap);
+ size_t shift = BITMAP_WIDTH(bitmap) - pos - 1;
+ bitmap[offset] |= 1ul << shift;
+ return 0;
+}
+
+static inline
+int
+bitmap_unset(bitmap_t * bitmap, off_t i)
+{
+ if (bitmap_ensure_pos(bitmap, i) < 0)
+ return -1;
+ size_t offset = i / BITMAP_WIDTH(bitmap);
+ size_t pos = i % BITMAP_WIDTH(bitmap);
+ size_t shift = BITMAP_WIDTH(bitmap) - pos - 1;
+ bitmap[offset] &= ~ (1ul << shift);
+ return 0;
+}
+
+
+static inline
+int
+bitmap_set_range(bitmap_t * bitmap, off_t from, off_t to)
+{
+ assert(from <= to);
+ ssize_t offset_from = from / BITMAP_WIDTH(bitmap);
+ ssize_t offset_to = to / BITMAP_WIDTH(bitmap);
+ size_t pos_from = from % BITMAP_WIDTH(bitmap);
+ size_t pos_to = to % BITMAP_WIDTH(bitmap);
+
+
+ /*
+ * First block initialization is needed if <from> is not aligned with the
+ * bitmap element size or if to is within the same one.
+ */
+ if ((pos_from != 0) || ((offset_to == offset_from) && (pos_to != BITMAP_WIDTH(bitmap) - 1))) {
+ size_t from_end = MIN(to, (offset_from + 1) * BITMAP_WIDTH(bitmap));
+ for (size_t k = from; k < from_end; k++) {
+ if (bitmap_set(bitmap, k) < 0)
+ goto END;
+ }
+ }
+
+ /*
+ * Second block is needed if <to> is not aligned with the bitmap element
+ * size
+ */
+ if ((pos_to != BITMAP_WIDTH(bitmap) - 1) && (offset_to != offset_from)) {
+ size_t to_start = MAX(from, offset_to * BITMAP_WIDTH(bitmap));
+ for (size_t k = to_start; k < to; k++) {
+ if (bitmap_set(bitmap, k) < 0)
+ goto END;
+ }
+ }
+
+ if (pos_from != 0)
+ offset_from += 1;
+ if (pos_to != BITMAP_WIDTH(bitmap) - 1)
+ offset_to -= 1;
+
+ /*
+ * We need to cover both elements at position offset_from and offset_to
+ * provided that offset_from is not bigger
+ */
+ if (offset_to >= offset_from) {
+ memset(&bitmap[offset_from], 0xFF, (offset_to - offset_from + 1) * sizeof(bitmap[0]));
+ }
+
+ return 0;
+
+END:
+ ERROR("Error setting bitmap range\n");
+ return -1;
+}
-#define bitmap_set(bitmap, i) bitmap[(i) / BITMAP_WIDTH(bitmap)] |= 1 << ((i) % BITMAP_WIDTH(bitmap))
+#define bitmap_set_to(bitmap, to) bitmap_set_range((bitmap), 0, (to))
-#define bitmap_unset(bitmap, i) bitmap[(i) / BITMAP_WIDTH(bitmap)] &= ~ (1 << ((i) % BITMAP_WIDTH(bitmap)))
+#define bitmap_free(bitmap) vector_free(bitmap)
-#define bitmap_set_to(bitmap, pos) \
-do { \
- size_t offset = (pos / BITMAP_WIDTH(bitmap) + 1); \
- memset(bitmap, 0xFF, pos * sizeof(bitmap[0])); \
- size_t set_bits = offset * BITMAP_WIDTH(bitmap); \
- for (unsigned i = pos; i < set_bits; i++) \
- bitmap_unset(bitmap, i); \
-} while(0);
+#ifdef WITH_TESTS
+#define bitmap_get_alloc_size(bitmap) vector_get_alloc_size(bitmap)
+#endif /* WITH_TESTS */
#endif /* UTIL_BITMAP_H */
diff --git a/hicn-light/src/hicn/base/common.h b/hicn-light/src/hicn/base/common.h
index 996050308..9ba426bb8 100644
--- a/hicn-light/src/hicn/base/common.h
+++ b/hicn-light/src/hicn/base/common.h
@@ -46,7 +46,7 @@ uint32_t __inline __builtin_clz(uint32_t value) {
return 32;
}
-uint32_t __inline __builtin_clzll(uint64_t value) {
+uint32_t __inline __builtin_clzl2(uint64_t value) {
uint32_t leading_zero = 0;
if (_BitScanReverse64(&leading_zero, value))
return 63 - leading_zero;
@@ -57,6 +57,6 @@ uint32_t __inline __builtin_clzll(uint64_t value) {
#define __builtin_clzl __builtin_clzll
#endif
-#define next_pow2(x) (x == 1 ? 1 : 1<<(64-__builtin_clzl(x-1)))
+#define next_pow2(x) (x <= 1 ? 1 : 1ul <<(64-__builtin_clzl(x-1)))
#endif /* UTIL_COMMON_H */
diff --git a/hicn-light/src/hicn/base/pool.c b/hicn-light/src/hicn/base/pool.c
index 0f5f728e3..31abb13f1 100644
--- a/hicn-light/src/hicn/base/pool.c
+++ b/hicn-light/src/hicn/base/pool.c
@@ -30,36 +30,52 @@
#include "common.h"
#include "pool.h"
+#include <stdio.h> // XXX
+
void
-_pool_init(void ** pool_ptr, size_t elt_size, size_t max_size)
+_pool_init(void ** pool_ptr, size_t elt_size, size_t init_size, size_t max_size)
{
assert(pool_ptr);
assert(elt_size);
- pool_hdr_t * ph = calloc(POOL_HDRLEN + elt_size * max_size, 1);
- if (!ph) {
- *pool_ptr = NULL;
- return;
- }
+ init_size = next_pow2(init_size);
+
+ if (max_size && init_size > max_size)
+ goto ERR_MAX_SIZE;
+
+ /* The initial pool size is rounded to the next power of two */
+ size_t alloc_size = next_pow2(init_size);
+
+ pool_hdr_t * ph = calloc(POOL_HDRLEN + alloc_size * elt_size, 1);
+ if (!ph)
+ goto ERR_MALLOC;
ph->elt_size = elt_size;
+ ph->alloc_size = alloc_size;
ph->max_size = max_size;
/* Free indices */
off_t * free_indices;
- vector_init(free_indices, max_size);
- for(unsigned i = 0; i < max_size; i++)
- free_indices[i] = (max_size - 1) - i;
- vector_len(free_indices) = max_size;
+ vector_init(free_indices, init_size, max_size);
+ for(unsigned i = 0; i < init_size; i++)
+ free_indices[i] = (init_size - 1) - i;
+ vector_len(free_indices) = init_size;
ph->free_indices = free_indices;
/* Free bitmap */
uint_fast32_t * fb = ph->free_bitmap;
- bitmap_init(fb, max_size);
- bitmap_set_to(fb, max_size);
+ bitmap_init(fb, init_size, max_size);
+ bitmap_set_to(fb, init_size);
ph->free_bitmap = fb;
*pool_ptr = (uint8_t*)ph + POOL_HDRLEN;
+
+ return;
+
+ERR_MALLOC:
+ERR_MAX_SIZE:
+ *pool_ptr = NULL;
+ return;
}
void
@@ -73,42 +89,59 @@ void
_pool_resize(void ** pool_ptr, size_t elt_size)
{
pool_hdr_t * ph = pool_hdr(*pool_ptr);
- size_t old_elts = ph->max_size;
- size_t new_elts = old_elts * 2;
+ size_t old_size = ph->alloc_size;
+ size_t new_size = old_size * 2;
+
+ if (ph->max_size && new_size > ph->max_size)
+ goto ERR_MAX_SIZE;
/* Double pool storage */
- ph = realloc(ph, POOL_HDRLEN + new_elts * elt_size);
- if (!ph) {
- *pool_ptr = NULL;
- return;
- }
+ ph = realloc(ph, POOL_HDRLEN + new_size * elt_size);
+ if (!ph)
+ goto ERR_REALLOC;
ph->elt_size = elt_size;
- ph->max_size = new_elts;
+ ph->alloc_size = new_size;
/*
- * After resize, the pool will have old_elts free indices, ranging from
- * old_elts to (new_elts - 1)
+ * After resize, the pool will have new free indices, ranging from
+ * old_size to (new_size - 1)
*/
- off_t * free_indices = ph->free_indices;
- vector_ensure_pos(free_indices, old_elts);
- for (unsigned i = 0; i < old_elts; i++)
- free_indices[i] = new_elts - 1 - i;
+ vector_ensure_pos(ph->free_indices, old_size);
+ for (unsigned i = 0; i < old_size; i++)
+ ph->free_indices[i] = new_size - 1 - i;
+ vector_len(ph->free_indices) = old_size;
+
+ /* We also need to update the bitmap */
+ bitmap_ensure_pos(ph->free_bitmap, new_size - 1);
+ bitmap_set_range(ph->free_bitmap, old_size, new_size - 1);
/* Reassign pool pointer */
*pool_ptr = (uint8_t*)ph + POOL_HDRLEN;
+
+ return;
+
+ERR_REALLOC:
+ERR_MAX_SIZE:
+ *pool_ptr = NULL;
+ return;
}
-void
+off_t
_pool_get(void ** pool_ptr, void ** elt, size_t elt_size)
{
pool_hdr_t * ph = pool_hdr(*pool_ptr);
uint64_t l = vector_len(ph->free_indices);
- if (l == 0)
+ if (l == 0) {
_pool_resize(pool_ptr, elt_size);
+ ph = pool_hdr(*pool_ptr);
+ l = vector_len(ph->free_indices);
+ }
off_t free_id = ph->free_indices[l - 1];
vector_len(ph->free_indices)--;
+ bitmap_unset(ph->free_bitmap, free_id);
*elt = *pool_ptr + free_id;
memset(*elt, 0, sizeof(elt));
+ return free_id;
}
void
diff --git a/hicn-light/src/hicn/base/pool.h b/hicn-light/src/hicn/base/pool.h
index 8335c9bc5..57172192b 100644
--- a/hicn-light/src/hicn/base/pool.h
+++ b/hicn-light/src/hicn/base/pool.h
@@ -51,6 +51,7 @@
typedef struct {
size_t elt_size;
+ size_t alloc_size;
size_t max_size;
uint_fast32_t * free_bitmap; /* bitmap of free indices */
off_t * free_indices; /* vector of free indices */
@@ -76,7 +77,7 @@ typedef struct {
*
* NOTE: that an empty pool might be equal to NULL.
*/
-void _pool_init(void ** pool_ptr, size_t elt_size, size_t max_size);
+void _pool_init(void ** pool_ptr, size_t elt_size, size_t init_size, size_t max_size);
/**
* @brief Free a pool data structure (helper).
@@ -105,7 +106,7 @@ void _pool_resize(void ** pool_ptr, size_t elt_size);
* NOTES:
* - The memory chunk is cleared upon attribution
*/
-void _pool_get(void ** pool, void ** elt, size_t elt_size);
+off_t _pool_get(void ** pool, void ** elt, size_t elt_size);
/**
* @brief Put an element back into the pool data structure (helper).
@@ -127,8 +128,8 @@ void _pool_put(void ** pool, void ** elt, size_t elt_size);
*
* NOTE: that an empty pool might be equal to NULL.
*/
-#define pool_init(pool, max_size) \
- _pool_init((void**)&pool, sizeof(pool[0]), max_size);
+#define pool_init(pool, init_size, max_size) \
+ _pool_init((void**)&pool, sizeof(pool[0]), init_size, max_size);
/**
* @brief Free a pool data structure.
@@ -168,6 +169,8 @@ void _pool_put(void ** pool, void ** elt, size_t elt_size);
#define pool_validate_id(pool, id) \
bitmap_is_unset((pool_hdr(pool))->free_bitmap, (id))
+#define pool_get_free_indices_size(pool) vector_len(pool_hdr(pool)->free_indices)
+
/**
* @brief Returns the current length of the pool.
*
@@ -180,7 +183,7 @@ void _pool_put(void ** pool, void ** elt, size_t elt_size);
* size of the pool.
*/
#define pool_len(pool) \
- (pool_hdr(pool)->max_size - vector_len((pool_hdr(pool)->free_indices)))
+ (pool_hdr(pool)->alloc_size - pool_get_free_indices_size(pool))
/**
* @brief Enumerate elements from a pool.
@@ -226,4 +229,10 @@ do { \
pool_enumerate((pool), _pool_var(i), (eltp), BODY); \
} while(0)
+#ifdef WITH_TESTS
+#define pool_get_alloc_size(bitmap) pool_hdr(pool)->alloc_size
+#define pool_get_free_indices(pool) pool_hdr(pool)->free_indices
+#define pool_get_free_bitmap(pool) pool_hdr(pool)->free_bitmap
+#endif /* WITH_TESTS */
+
#endif /* UTIL_POOL_H */
diff --git a/hicn-light/src/hicn/base/test/test-bitmap.cc b/hicn-light/src/hicn/base/test/test-bitmap.cc
index d6ab94f3e..1a62edba3 100644
--- a/hicn-light/src/hicn/base/test/test-bitmap.cc
+++ b/hicn-light/src/hicn/base/test/test-bitmap.cc
@@ -24,60 +24,114 @@
#include <netinet/in.h>
extern "C" {
-#include <hicn/base/vector.h>
+#define WITH_TESTS
#include <hicn/base/bitmap.h>
}
+#define DEFAULT_SIZE 10
+
class BitmapTest : public ::testing::Test {
- protected:
- BitmapTest() {
- }
+protected:
+ BitmapTest() { }
- virtual ~BitmapTest() {
+ virtual ~BitmapTest() { }
- // You can do clean-up work that doesn't throw exceptions here.
- }
+ bitmap_t * bitmap;
+};
- // If the constructor and destructor are not enough for setting up
- // and cleaning up each test, you can define the following methods:
+/*
+ * TEST: bitmap allocation
+ */
+TEST_F(BitmapTest, BitmapAllocation)
+{
+ int rc;
- virtual void SetUp() {
- bitmap_init(bitmap, 1024);
- }
+ /*
+ * We take a value < 32 on purpose to avoid confusion on the choice of a 32
+ * or 64 bit integer for storage
+ */
+ size_t size_not_pow2 = DEFAULT_SIZE;
+ bitmap_init(bitmap, size_not_pow2, 0);
- virtual void TearDown() {
- free(bitmap);
- }
- uint32_t *bitmap;
-};
+ /*
+ * Bitmap should have been allocated with a size rounded to the next power
+ * of 2
+ */
+ EXPECT_EQ(bitmap_get_alloc_size(bitmap), 1);
+
+ /* By default, no element should be set */
+ EXPECT_FALSE(bitmap_is_set(bitmap, 0));
+ EXPECT_TRUE(bitmap_is_unset(bitmap, 0));
+
+ EXPECT_EQ(bitmap_get_alloc_size(bitmap), 1);
+
+ EXPECT_FALSE(bitmap_is_set(bitmap, size_not_pow2 - 1));
+ EXPECT_TRUE(bitmap_is_unset(bitmap, size_not_pow2 - 1));
+
+ /* Bitmap should not have been reallocated */
+ EXPECT_EQ(bitmap_get_alloc_size(bitmap), 1);
+
+ /* After setting a bit after the end, bitmap should have been reallocated */
+ bitmap_set(bitmap, sizeof(bitmap[0]) * 8 - 1);
+ EXPECT_EQ(bitmap_get_alloc_size(bitmap), 1);
+
+ /* After setting a bit after the end, bitmap should have been reallocated */
+ rc = bitmap_set(bitmap, sizeof(bitmap[0]) * 8);
+ EXPECT_GE(rc, 0);
+ EXPECT_EQ(bitmap_get_alloc_size(bitmap), 2);
+
+ rc = bitmap_set(bitmap, sizeof(bitmap[0]) * 8 + 1);
+ EXPECT_GE(rc, 0);
+ EXPECT_EQ(bitmap_get_alloc_size(bitmap), 2);
+
+ bitmap_free(bitmap);
+
+ size_t size_pow2 = 16;
+
+ /* Limiting test for allocation size */
+ bitmap_init(bitmap, size_pow2, 0);
+ EXPECT_EQ(bitmap_get_alloc_size(bitmap), 1);
+
+ bitmap_free(bitmap);
+}
TEST_F(BitmapTest, BitmapSet)
{
- bitmap_set(bitmap, 20);
- EXPECT_TRUE(bitmap_is_set(bitmap, 20));
- EXPECT_FALSE(bitmap_is_unset(bitmap, 20));
- EXPECT_FALSE(bitmap_is_set(bitmap, 19));
- EXPECT_TRUE(bitmap_is_unset(bitmap, 19));
+ bitmap_init(bitmap, DEFAULT_SIZE, 0);
+
+ bitmap_set(bitmap, 20);
+ EXPECT_TRUE(bitmap_is_set(bitmap, 20));
+ EXPECT_FALSE(bitmap_is_unset(bitmap, 20));
+ EXPECT_FALSE(bitmap_is_set(bitmap, 19));
+ EXPECT_TRUE(bitmap_is_unset(bitmap, 19));
+ bitmap_free(bitmap);
}
TEST_F(BitmapTest, BitmapUnSet) {
- bitmap_set(bitmap, 20);
- bitmap_set(bitmap, 19);
- bitmap_unset(bitmap, 20);
- EXPECT_FALSE(bitmap_is_set(bitmap, 20));
- EXPECT_TRUE(bitmap_is_unset(bitmap, 20));
- EXPECT_TRUE(bitmap_is_set(bitmap, 19));
- EXPECT_FALSE(bitmap_is_unset(bitmap, 19));
+ bitmap_init(bitmap, DEFAULT_SIZE, 0);
+
+ bitmap_set(bitmap, 20);
+ bitmap_set(bitmap, 19);
+ bitmap_unset(bitmap, 20);
+ EXPECT_FALSE(bitmap_is_set(bitmap, 20));
+ EXPECT_TRUE(bitmap_is_unset(bitmap, 20));
+ EXPECT_TRUE(bitmap_is_set(bitmap, 19));
+ EXPECT_FALSE(bitmap_is_unset(bitmap, 19));
+ bitmap_free(bitmap);
}
TEST_F(BitmapTest, BitmapSetTo) {
- bitmap_set_to(bitmap, 40);
- EXPECT_TRUE(bitmap_is_set(bitmap, 20));
- EXPECT_TRUE(bitmap_is_set(bitmap, 21));
- EXPECT_TRUE(bitmap_is_unset(bitmap, 41));
- EXPECT_TRUE(bitmap_is_unset(bitmap, 42));
+ bitmap_init(bitmap, DEFAULT_SIZE, 0);
+
+ bitmap_set_to(bitmap, 40);
+ EXPECT_TRUE(bitmap_is_set(bitmap, 20));
+ EXPECT_TRUE(bitmap_is_set(bitmap, 21));
+ EXPECT_TRUE(bitmap_is_unset(bitmap, 41));
+ EXPECT_TRUE(bitmap_is_unset(bitmap, 42));
+
+ bitmap_free(bitmap);
}
int main(int argc, char **argv)
diff --git a/hicn-light/src/hicn/base/test/test-pool.cc b/hicn-light/src/hicn/base/test/test-pool.cc
index 86c1c1270..1146ef2b7 100644
--- a/hicn-light/src/hicn/base/test/test-pool.cc
+++ b/hicn-light/src/hicn/base/test/test-pool.cc
@@ -24,45 +24,135 @@
#include <netinet/in.h>
extern "C" {
+#define WITH_TESTS
#include <hicn/base/pool.h>
}
+/*
+ * TODO
+ * - test max_size
+ */
+
+#define DEFAULT_SIZE 10
+
class PoolTest : public ::testing::Test {
- protected:
- PoolTest() {
- }
+protected:
+ PoolTest() { }
+ virtual ~PoolTest() { }
- virtual ~PoolTest() {
- // You can do clean-up work that doesn't throw exceptions here.
- }
+ int *pool;
+};
- // If the constructor and destructor are not enough for setting up
- // and cleaning up each test, you can define the following methods:
+TEST_F(PoolTest, PoolAllocation)
+{
+ int rc;
- virtual void SetUp() {
-
- }
+ pool_init(pool, DEFAULT_SIZE, 0);
- virtual void TearDown() {
- pool_free(pool);
- }
+ size_t pool_size = next_pow2(DEFAULT_SIZE);
- int *pool;
-};
+ EXPECT_EQ(pool_get_alloc_size(pool), pool_size);
+
+ /* Check that free indices and bitmaps are correctly initialize */
+ off_t * fi = pool_get_free_indices(pool);
+ EXPECT_EQ(vector_len(fi), pool_size);
+ EXPECT_EQ(fi[0], pool_size - 1);
+ EXPECT_EQ(fi[pool_size - 1], 0);
+
+ /* The allocated size of the underlying vector should be the next power of two */
+ EXPECT_EQ(vector_get_alloc_size(fi), pool_size);
+
+ bitmap_t * fb = pool_get_free_bitmap(pool);
+ EXPECT_TRUE(bitmap_is_set(fb, 0));
+ EXPECT_TRUE(bitmap_is_set(fb, pool_size - 2));
+ EXPECT_TRUE(bitmap_is_set(fb, pool_size - 1));
+ EXPECT_TRUE(bitmap_is_unset(fb, pool_size));
+
+ /* Getting elements from the pool should correctly update the free indices
+ * and bitmap */
+ int * elt;
+
+ rc = pool_get(pool, elt);
+ EXPECT_GE(rc, 0);
+ EXPECT_EQ(vector_len(fi), pool_size - 1);
+ EXPECT_TRUE(bitmap_is_unset(fb, 0));
+
+ rc = pool_get(pool, elt);
+ EXPECT_GE(rc, 0);
+ EXPECT_EQ(vector_len(fi), pool_size - 2);
+ EXPECT_TRUE(bitmap_is_unset(fb, 1));
+
+ for (unsigned i = 0; i < pool_size - 4; i++) {
+ rc = pool_get(pool, elt);
+ EXPECT_GE(rc, 0);
+ }
+
+ rc = pool_get(pool, elt);
+ EXPECT_GE(rc, 0);
+ EXPECT_EQ(vector_len(fi), 1);
+ EXPECT_TRUE(bitmap_is_unset(fb, pool_size - 2));
+
+ rc = pool_get(pool, elt);
+ EXPECT_GE(rc, 0);
+ EXPECT_EQ(vector_len(fi), 0);
+ EXPECT_TRUE(bitmap_is_unset(fb, pool_size - 1));
+ /*
+ * Getting elements within the allocated range should not have triggered a
+ * resize
+ */
+ EXPECT_EQ(pool_len(pool), pool_size);
+
+ /*
+ * Getting elements once the allocated range has been exceeded should
+ * trigger a resize
+ */
+ rc = pool_get(pool, elt);
+ EXPECT_GE(rc, 0);
+
+ EXPECT_EQ(pool_get_alloc_size(pool), pool_size * 2);
+
+ EXPECT_EQ(pool_len(pool), pool_size + 1);
+
+ /*
+ * Doubling the size, we should have again pool_size elements free, minus 1
+ */
+ EXPECT_EQ(pool_get_free_indices_size(pool), pool_size - 1);
+
+ /*
+ * NOTE: this is wrong as there has been a realloc and the old fi
+ * pointer is now invalid
+ */
+ //EXPECT_EQ(vector_len(fi), pool_size - 1);
+
+ /* And the bitmap should also be correctly modified */
+ fb = pool_get_free_bitmap(pool);
+ EXPECT_TRUE(bitmap_is_unset(fb, pool_size));
+
+ /* Check that surrounding values are also correct */
+ EXPECT_TRUE(bitmap_is_unset(fb, pool_size - 1));
+ EXPECT_TRUE(bitmap_is_set(fb, pool_size + 1));
+
+ /* Setting elements after should through */
+
+ /* Check that free indices and bitmaps are correctly updated */
+
+ pool_free(pool);
+}
+
+// XXX todo : check state after several get and put
TEST_F(PoolTest, PoolPut)
{
- pool_init(pool, 1024);
- int* elt;
- pool_get(pool, elt);
- *elt = 10;
+ pool_init(pool, DEFAULT_SIZE, 0);
+
+ int* elt;
+ pool_get(pool, elt);
+ *elt = 10;
printf("2\n");
- pool_put(pool, elt);
+ pool_put(pool, elt);
printf("3\n");
-
- //pool_get(pool)
- //loop_ = loop_create();
- //EXPECT_TRUE(loop_ != NULL);
+
+ pool_free(pool);
}
diff --git a/hicn-light/src/hicn/base/test/test-vector.cc b/hicn-light/src/hicn/base/test/test-vector.cc
index e5eeff910..59571b053 100644
--- a/hicn-light/src/hicn/base/test/test-vector.cc
+++ b/hicn-light/src/hicn/base/test/test-vector.cc
@@ -24,64 +24,90 @@
#include <netinet/in.h>
extern "C" {
+#define WITH_TESTS
#include <hicn/base/vector.h>
}
+/*
+ * TODO
+ * - test max_size
+ */
+
+#define DEFAULT_SIZE 10
+
class VectorTest : public ::testing::Test {
- protected:
- VectorTest() {
- }
+protected:
+ VectorTest() { }
+ virtual ~VectorTest() { }
- virtual ~VectorTest() {
- // You can do clean-up work that doesn't throw exceptions here.
- }
+ int *vector = NULL;
+};
- // If the constructor and destructor are not enough for setting up
- // and cleaning up each test, you can define the following methods:
+/* TEST: Vector allocation and initialization */
+TEST_F(VectorTest, VectorAllocate)
+{
+ vector_init(vector, DEFAULT_SIZE, 0);
- virtual void SetUp() {;
- vector_init(vector, 1024);
- }
+ /* Allocated size should be the next power of two */
+ EXPECT_EQ(vector_get_alloc_size(vector), 16);
- virtual void TearDown() {
- vector_free(vector);
- }
+ /* Setting elements within the allocated size should not trigger a resize */
+ vector_ensure_pos(vector, 15);
+ EXPECT_EQ(vector_get_alloc_size(vector), 16);
- int *vector = NULL;
+ /* Setting elements after should through */
+ vector_ensure_pos(vector, 16);
+ EXPECT_EQ(vector_get_alloc_size(vector), 32);
-};
+ /* Check that free indices and bitmaps are correctly updated */
+
+ vector_free(vector);
+}
TEST_F(VectorTest, VectorSize)
{
- vector_push(vector, 109);
- vector_push(vector, 109);
- int size = vector_len(vector);
- EXPECT_EQ(size, 2);
- vector_push(vector, 109);
- size = vector_len(vector);
- EXPECT_EQ(size, 3);
+ vector_init(vector, DEFAULT_SIZE, 0);
+
+ vector_push(vector, 109);
+ int size = vector_len(vector);
+ EXPECT_EQ(size, 1);
+ vector_push(vector, 109);
+ size = vector_len(vector);
+ EXPECT_EQ(size, 2);
+ vector_push(vector, 109);
+ size = vector_len(vector);
+ EXPECT_EQ(size, 3);
+ vector_free(vector);
}
TEST_F(VectorTest, VectorCheckValue)
{
- vector_push(vector, 109);
- vector_push(vector, 200);
- EXPECT_EQ(vector[0], 109);
- EXPECT_EQ(vector[1], 200);
+ vector_init(vector, DEFAULT_SIZE, 0);
+
+ vector_push(vector, 109);
+ vector_push(vector, 200);
+ EXPECT_EQ(vector[0], 109);
+ EXPECT_EQ(vector[1], 200);
+
+ vector_free(vector);
}
TEST_F(VectorTest, VectorEnsurePos)
{
- printf (" %p\n", vector);
- vector_ensure_pos(vector, 1025);
- for (int i = 0; i <1025; i++) {
- printf("i %d\n", i);
+ vector_init(vector, DEFAULT_SIZE, 0);
+
printf (" %p\n", vector);
- vector_push(vector, i);
- }
- int size = vector_len(vector);
- EXPECT_EQ(size, 1025);
+ vector_ensure_pos(vector, 1025);
+ for (int i = 0; i <1025; i++) {
+ //printf("i %d\n", i);
+ //printf (" %p\n", vector);
+ vector_push(vector, i);
+ }
+ int size = vector_len(vector);
+ EXPECT_EQ(size, 1025);
+
+ vector_free(vector);
}
int main(int argc, char **argv)
diff --git a/hicn-light/src/hicn/base/vector.c b/hicn-light/src/hicn/base/vector.c
index b994a4465..43110414a 100644
--- a/hicn-light/src/hicn/base/vector.c
+++ b/hicn-light/src/hicn/base/vector.c
@@ -28,9 +28,10 @@
#define DEFAULT_VECTOR_SIZE 64
void
-_vector_init(void ** vector_ptr, size_t elt_size, size_t init_size)
+_vector_init(void ** vector_ptr, size_t elt_size, size_t init_size, size_t max_size)
{
assert(vector_ptr);
+ assert(max_size == 0 || init_size < max_size);
if (init_size == 0)
init_size = DEFAULT_VECTOR_SIZE;
@@ -40,6 +41,7 @@ _vector_init(void ** vector_ptr, size_t elt_size, size_t init_size)
vector_hdr_t * vh = vector_hdr(*vector_ptr);
vh->cur_size = 0;
+ vh->max_size = max_size;
}
void
@@ -49,23 +51,42 @@ _vector_free(void ** vector_ptr)
*vector_ptr = NULL;
}
-bool
+int
_vector_resize(void ** vector_ptr, size_t elt_size, off_t pos)
{
- vector_hdr_t * vh = *vector_ptr ? vector_hdr(*vector_ptr) : NULL;
+ vector_hdr_t * vh;
- /*
- * Round the allocated size to the next power of 2 of the requested position
- */
- size_t new_elts = (pos > 0) ? next_pow2(pos) : vh->max_size * 2;
+ size_t old_size;
- vh = realloc(vh, VECTOR_HDRLEN + new_elts * elt_size);
+ if (*vector_ptr) {
+ vh = vector_hdr(*vector_ptr);
+ old_size = vh->alloc_size;
+ } else {
+ vh = NULL;
+ old_size = 0;
+ }
+
+ /* Round the allocated size to the next power of 2 of the requested position */
+ size_t new_size = next_pow2(pos);
+
+ /* Don't grow the vector back */
+ if (new_size < old_size)
+ return 0;
+
+ /* Don't exceed maximum size (for init, check is done beforehand) */
+ if (vh && vh->max_size && new_size > vh->max_size)
+ return -1;
+
+ vh = realloc(vh, VECTOR_HDRLEN + new_size * elt_size);
if (!vh)
- return false;
- vh->max_size = new_elts;
+ return -1;
+ vh->alloc_size = new_size;
+
+ /* Zero out the newly allocated memory (except headers) */
+ memset((uint8_t*)vh + VECTOR_HDRLEN + old_size * elt_size, 0, (new_size - old_size) * elt_size);
/* Reassign vector pointer */
*vector_ptr = (uint8_t*)vh + VECTOR_HDRLEN;
- return true;
+ return 0;
}
diff --git a/hicn-light/src/hicn/base/vector.h b/hicn-light/src/hicn/base/vector.h
index 06ffa4428..ff12e6ee6 100644
--- a/hicn-light/src/hicn/base/vector.h
+++ b/hicn-light/src/hicn/base/vector.h
@@ -45,7 +45,7 @@
#ifndef UTIL_VECTOR_H
#define UTIL_VECTOR_H
-#include <stdbool.h>
+#include <stdint.h>
#include <stddef.h>
#include <stdint.h>
#include <string.h>
@@ -58,7 +58,8 @@
typedef struct {
size_t cur_size; /** Vector current size (corresponding to the highest used element). */
- size_t max_size; /** The currently allocated size. */
+ size_t alloc_size; /** The currently allocated size. */
+ size_t max_size; /** The maximum allowed size (0 = no limit) */
} vector_hdr_t;
/* Make sure elements following the header are aligned */
@@ -80,7 +81,7 @@ typedef struct {
* @param[in] elt_size Size of a vector element.
* @param[in] max_size Maximum vector size (O = unlimited).
*/
-void _vector_init(void ** vector_ptr, size_t elt_size, size_t max_size);
+void _vector_init(void ** vector_ptr, size_t elt_size, size_t init_size, size_t max_size);
/**
* @brief Free a vector data structure.
@@ -97,7 +98,7 @@ void _vector_free(void ** vector_ptr);
* @param[in] pos The position at which the vector should be able to hold an
* element.
*
- * @return bool Flag indicating whether the vector has been correctly resized.
+ * @return int Flag indicating whether the vector has been correctly resized.
*
* NOTE:
* - The resize operation does not specify the final size of the vector but
@@ -105,7 +106,7 @@ void _vector_free(void ** vector_ptr);
* position. This allows the caller not to care about doing successive calls to
* this API while the vector is growing in size.
*/
-bool _vector_resize(void ** vector_ptr, size_t elt_size, off_t pos);
+int _vector_resize(void ** vector_ptr, size_t elt_size, off_t pos);
/**
* @brief Ensures a vector is sufficiently large to hold an element at the
@@ -115,7 +116,7 @@ bool _vector_resize(void ** vector_ptr, size_t elt_size, off_t pos);
* @param[in] elt_size The size of a vector element.
* @param[in] pos The position to validate.
*
- * @return bool Flag indicating whether the vector is available.
+ * @return int Flag indicating whether the vector is available.
*
* NOTE:
* - This function should always be called before writing to a vector element
@@ -124,13 +125,13 @@ bool _vector_resize(void ** vector_ptr, size_t elt_size, off_t pos);
* be resized.
*/
static inline
-bool
+int
_vector_ensure_pos(void ** vector_ptr, size_t elt_size, off_t pos)
{
vector_hdr_t * vh = vector_hdr(*vector_ptr);
- if (pos >= vh->max_size)
- return _vector_resize(vector_ptr, elt_size, pos);
- return true;
+ if (pos >= vh->alloc_size)
+ return _vector_resize(vector_ptr, elt_size, pos + 1);
+ return 0;
}
/**
@@ -146,15 +147,17 @@ _vector_ensure_pos(void ** vector_ptr, size_t elt_size, off_t pos)
* maximum size).
*/
static inline
-bool
+int
_vector_push(void ** vector_ptr, size_t elt_size, void * elt)
{
vector_hdr_t * vh = vector_hdr(*vector_ptr);
- if (!_vector_ensure_pos(vector_ptr, elt_size, vh->cur_size))
- return false;
- /*(*vector_ptr)[vh->cur_size++] = elt; */
- memcpy((uint8_t*)vector_ptr + vh->cur_size++ * elt_size, elt, elt_size);
- return true;
+ if (_vector_ensure_pos(vector_ptr, elt_size, vh->cur_size) < 0)
+ return -1;
+ /* Always get header after a potential resize */
+ memcpy((uint8_t*)*vector_ptr + vh->cur_size * elt_size, elt, elt_size);
+ vh = vector_hdr(*vector_ptr);
+ vh->cur_size++;
+ return 0;
}
/******************************************************************************/
@@ -165,9 +168,13 @@ _vector_push(void ** vector_ptr, size_t elt_size, void * elt)
*
* @param[in,out] vector Vector to allocate and initialize.
* @param[in] max_size Maximum vector size (nonzero).
+ *
+ * NOTE:
+ * - Allocated memory is set to 0 (used by bitmap)
*/
-#define vector_init(vector, max_size) \
- _vector_init((void**)&vector, sizeof(vector[0]), max_size)
+
+#define vector_init(vector, init_size, max_size) \
+ _vector_init((void**)&vector, sizeof(vector[0]), init_size, max_size)
/**
* @brief Free a vector data structure.
@@ -184,7 +191,7 @@ _vector_push(void ** vector_ptr, size_t elt_size, void * elt)
* @param[in] pos The position at which the vector should be able to hold an
* element.
*
- * @return bool Flag indicating whether the vector has been correctly resized.
+ * @return int Flag indicating whether the vector has been correctly resized.
*
* NOTE:
* - The resize operation does not specify the final size of the vector but
@@ -193,6 +200,7 @@ _vector_push(void ** vector_ptr, size_t elt_size, void * elt)
* this API while the vector is growing in size.
* - If the new size is smaller than the current size, the content of the
* vector will be truncated.
+ * - Newly allocated memory is set to 0 (used by bitmap)
*/
#define vector_resize(vector) _vector_resize((void**)&(vector), sizeof((vector)[0]), 0)
@@ -241,6 +249,10 @@ do { \
* - A user should always call vector_ensure_pos to ensure the vector is
* sufficiently large to hold an element at the specified position.
*/
-#define vector_len(vector) vector_hdr((vector))->cur_size
+#define vector_len(vector) vector_hdr(vector)->cur_size
+
+#ifdef WITH_TESTS
+#define vector_get_alloc_size(vector) vector_hdr(vector)->alloc_size
+#endif /* WITH_TESTS */
#endif /* UTIL_VECTOR_H */