diff options
author | Campbell Barton <ideasman42@gmail.com> | 2017-07-29 16:38:20 +0300 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2017-07-29 17:08:17 +0300 |
commit | 913d8ec6082c4b42cd7957912078645af10ad024 (patch) | |
tree | 7015f7c7d33a381b0562895155a1c80ce1f068d8 | |
parent | 277dc47eeaf4d96cfaf927e29288dbe69322d272 (diff) |
BLI_memiter: Small API for many small allocations
- Each allocation can be a different size
(but should be smaller than the chunk size).
- Result can be looped over in order of allocation.
- Allocations are aligned to pointer size to avoid unaligned reads.
-rw-r--r-- | source/blender/blenlib/BLI_memiter.h | 72 | ||||
-rw-r--r-- | source/blender/blenlib/CMakeLists.txt | 2 | ||||
-rw-r--r-- | source/blender/blenlib/intern/BLI_memiter.c | 354 | ||||
-rw-r--r-- | tests/gtests/blenlib/BLI_memiter_test.cc | 206 | ||||
-rw-r--r-- | tests/gtests/blenlib/CMakeLists.txt | 1 |
5 files changed, 635 insertions, 0 deletions
diff --git a/source/blender/blenlib/BLI_memiter.h b/source/blender/blenlib/BLI_memiter.h new file mode 100644 index 00000000000..96a47d53984 --- /dev/null +++ b/source/blender/blenlib/BLI_memiter.h @@ -0,0 +1,72 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef __BLI_MEMITER_H__ +#define __BLI_MEMITER_H__ + +/** \file BLI_memiter.h + * \ingroup bli + */ + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include "BLI_compiler_attrs.h" +#include "BLI_compiler_compat.h" + +/* 512kb, good default for small elems. */ +#define BLI_MEMITER_DEFAULT_SIZE (2 << 18) + +struct BLI_memiter; +struct BLI_memiter_chunk; + +typedef struct BLI_memiter BLI_memiter; + +/* warning, ATTR_MALLOC flag on BLI_memiter_alloc causes crash, see: D2756 */ +BLI_memiter *BLI_memiter_create(unsigned int chunk_size) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT; +void *BLI_memiter_alloc(BLI_memiter *mi, unsigned int size) ATTR_RETURNS_NONNULL ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1); +void BLI_memiter_alloc_from(BLI_memiter *mi, uint elem_size, const void *data_from) ATTR_NONNULL(1, 3); +void *BLI_memiter_calloc(BLI_memiter *mi, unsigned int size) ATTR_RETURNS_NONNULL ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1); +void BLI_memiter_destroy(BLI_memiter *mi) ATTR_NONNULL(1); +void BLI_memiter_clear(BLI_memiter *mi) ATTR_NONNULL(1); +unsigned int BLI_memiter_count(const BLI_memiter *mi) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1); + +/* utils */ +void *BLI_memiter_elem_first(BLI_memiter *mi); +void *BLI_memiter_elem_first_size(BLI_memiter *mi, unsigned int *r_size); + +/* private structure */ +typedef struct BLI_memiter_handle { + struct BLI_memiter_elem *elem; + uint elem_left; +} BLI_memiter_handle; + +void BLI_memiter_iter_init(BLI_memiter *mi, BLI_memiter_handle *iter) ATTR_NONNULL(); +bool BLI_memiter_iter_done(BLI_memiter_handle *iter) ATTR_NONNULL(); +void *BLI_memiter_iter_step(BLI_memiter_handle *iter) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); +void *BLI_memiter_iter_step_size(BLI_memiter_handle *iter, uint *r_size) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); + +#ifdef __cplusplus +} +#endif + +#endif /* __BLI_MEMITER_H__ */ diff --git a/source/blender/blenlib/CMakeLists.txt b/source/blender/blenlib/CMakeLists.txt index dc81ce000ea..1d865f99239 100644 --- a/source/blender/blenlib/CMakeLists.txt +++ b/source/blender/blenlib/CMakeLists.txt @@ -50,6 +50,7 @@ set(SRC intern/BLI_kdtree.c intern/BLI_linklist.c intern/BLI_memarena.c + intern/BLI_memiter.c intern/BLI_mempool.c intern/DLRB_tree.c intern/array_store.c @@ -179,6 +180,7 @@ set(SRC BLI_math_statistics.h BLI_math_vector.h BLI_memarena.h + BLI_memiter.h BLI_memory_utils.h BLI_mempool.h BLI_noise.h diff --git a/source/blender/blenlib/intern/BLI_memiter.c b/source/blender/blenlib/intern/BLI_memiter.c new file mode 100644 index 00000000000..4d365680e8a --- /dev/null +++ b/source/blender/blenlib/intern/BLI_memiter.c @@ -0,0 +1,354 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/blenlib/intern/BLI_memiter.c + * \ingroup bli + * + * Simple, fast memory allocator for allocating many small elements of different sizes + * in fixed size memory chunks, + * although allocations bigger than the chunk size are supported. + * They will reduce the efficiency of this data-structure. + * Elements are pointer aligned. + * + * Supports: + * + * - Allocation of mixed sizes. + * - Iterating over allocations in-order. + * - Clearing for re-use. + * + * Unsupported: + * + * - Freeing individual elements. + * + * \note We could inline iteration stepping, + * but tests show this doesn't give noticeable speedup. + */ + +#include <string.h> +#include <stdlib.h> + +#include "BLI_utildefines.h" + +#include "BLI_memiter.h" /* own include */ + +#include "MEM_guardedalloc.h" + +#include "BLI_strict_flags.h" /* keep last */ + +typedef uintptr_t data_t; +typedef intptr_t offset_t; + +/* Write the chunk terminator on adding each element. + * typically we rely on the 'count' to avoid iterating past the end. */ +// #define USE_TERMINATE_PARANOID + +/* Currently totalloc isnt used. */ + // #define USE_TOTALLOC + +/* pad must be power of two */ +#define PADUP(num, pad) (((num) + ((pad) - 1)) & ~((pad) - 1)) + +typedef struct BLI_memiter_elem { + offset_t size; + data_t data[0]; +} BLI_memiter_elem; + +typedef struct BLI_memiter_chunk { + struct BLI_memiter_chunk *next; + /** + * internal format is: + * ``[next_pointer, size:data, size:data, ..., negative_offset]`` + * + * Where negative offset rewinds to the start. + */ + data_t data[0]; +} BLI_memiter_chunk; + +typedef struct BLI_memiter { + /* A pointer to 'head' is needed*/ + struct BLI_memiter_chunk *head, *tail; + data_t *data_curr; + data_t *data_last; + /* Used unless a large element is requested. + * (which should be very rare!). */ + uint chunk_size_in_bytes_min; + uint count; +#ifdef USE_TOTALLOC + uint totalloc; +#endif +} BLI_memiter; + + +BLI_INLINE uint data_offset_from_size(uint size) +{ + return (PADUP(size, (uint)sizeof(data_t))) / (uint)sizeof(data_t); +} + +static void memiter_set_rewind_offset(BLI_memiter *mi) +{ + BLI_memiter_elem *elem = (BLI_memiter_elem *)mi->data_curr; + elem->size = (offset_t)(((data_t *)mi->tail) - mi->data_curr); + BLI_assert(elem->size < 0); +} + +static void memiter_init(BLI_memiter *mi) +{ + mi->head = NULL; + mi->tail = NULL; + mi->data_curr = NULL; + mi->data_last = NULL; + mi->count = 0; +#ifdef USE_TOTALLOC + mi->totalloc = 0; +#endif +} + +/* -------------------------------------------------------------------- */ + +/** \name Public API's + * \{ */ + +/** + * \param chunk_size_min: Should be a power of two and + * significantly larger than the average element size used. + * + * While allocations of any size are supported, they won't be efficient + * (effectively becoming a single-linked list). + * + * Its intended that many elements can be stored per chunk. + */ +BLI_memiter *BLI_memiter_create(uint chunk_size_min) +{ + BLI_memiter *mi = MEM_mallocN(sizeof(BLI_memiter), STRINGIFY(BLI_memiter)); + memiter_init(mi); + + /* Small values are used for tests to check for correctness, + * but otherwise not that useful. */ + const uint slop_space = (sizeof(BLI_memiter_chunk) + MEM_SIZE_OVERHEAD); + if (chunk_size_min >= 1024) { + /* As long as the input is a power of 2, this will give efficient sizes. */ + chunk_size_min -= slop_space; + } + + mi->chunk_size_in_bytes_min = (offset_t)chunk_size_min; + return mi; +} + +void *BLI_memiter_alloc(BLI_memiter *mi, uint elem_size) +{ + const uint data_offset = data_offset_from_size(elem_size); + data_t *data_curr_next = mi->data_curr + (1 + data_offset); + + if (UNLIKELY(mi->data_curr == NULL) || (data_curr_next > mi->data_last)) { + +#ifndef USE_TERMINATE_PARANOID + if (mi->data_curr != NULL) { + memiter_set_rewind_offset(mi); + } +#endif + + uint chunk_size_in_bytes = mi->chunk_size_in_bytes_min; + if (UNLIKELY(chunk_size_in_bytes < elem_size + (uint)sizeof(data_t[2]))) { + chunk_size_in_bytes = elem_size + (uint)sizeof(data_t[2]); + } + uint chunk_size = data_offset_from_size(chunk_size_in_bytes); + BLI_memiter_chunk *chunk = MEM_mallocN( + sizeof(BLI_memiter_chunk) + + (chunk_size * sizeof(data_t)), + STRINGIFY(BLI_memiter_chunk)); + + if (mi->head == NULL) { + BLI_assert(mi->tail == NULL); + mi->head = chunk; + } + else { + mi->tail->next = chunk; + } + mi->tail = chunk; + chunk->next = NULL; + + mi->data_curr = chunk->data; + mi->data_last = chunk->data + (chunk_size - 1); + data_curr_next = mi->data_curr + (1 + data_offset); + } + + BLI_assert(data_curr_next <= mi->data_last); + + BLI_memiter_elem *elem = (BLI_memiter_elem *)mi->data_curr; + elem->size = elem_size; + mi->data_curr = data_curr_next; + +#ifdef USE_TERMINATE_PARANOID + memiter_set_rewind_offset(mi); +#endif + + mi->count += 1; + +#ifdef USE_TOTALLOC + mi->totalloc += elem_size; +#endif + + return elem->data; +} + +void *BLI_memiter_calloc(BLI_memiter *mi, uint elem_size) +{ + void *data = BLI_memiter_alloc(mi, elem_size); + memset(data, 0, elem_size); + return data; +} + +void BLI_memiter_alloc_from(BLI_memiter *mi, uint elem_size, const void *data_from) +{ + void *data = BLI_memiter_alloc(mi, elem_size); + memcpy(data, data_from, elem_size); +} + +static void memiter_free_data(BLI_memiter *mi) +{ + BLI_memiter_chunk *chunk = mi->head; + while (chunk) { + BLI_memiter_chunk *chunk_next = chunk->next; + MEM_freeN(chunk); + chunk = chunk_next; + } +} + +void BLI_memiter_destroy(BLI_memiter *mi) +{ + memiter_free_data(mi); + MEM_freeN(mi); +} + +void BLI_memiter_clear(BLI_memiter *mi) +{ + memiter_free_data(mi); + memiter_init(mi); +} + +uint BLI_memiter_count(const BLI_memiter *mi) +{ + return mi->count; +} + +/** \} */ + + +/* -------------------------------------------------------------------- */ + +/** \name Helper API's + * \{ */ + +/* Support direct lookup for first. */ +void *BLI_memiter_elem_first(BLI_memiter *mi) +{ + if (mi->head != NULL) { + BLI_memiter_chunk *chunk = mi->head; + BLI_memiter_elem *elem = (BLI_memiter_elem *)chunk->data; + return elem->data; + } + else { + return NULL; + } +} + +void *BLI_memiter_elem_first_size(BLI_memiter *mi, unsigned int *r_size) +{ + if (mi->head != NULL) { + BLI_memiter_chunk *chunk = mi->head; + BLI_memiter_elem *elem = (BLI_memiter_elem *)chunk->data; + *r_size = (uint)elem->size; + return elem->data; + } + else { + return NULL; + } +} + +/** \} */ + + +/* -------------------------------------------------------------------- */ + +/** \name Iterator API's + * + * \note We could loop over elements until a NULL chunk is found, + * however this means every allocation needs to preemptively run + * #memiter_set_rewind_offset (see #USE_TERMINATE_PARANOID). + * Unless we have a call to finalize allocation (which complicates usage). + * So use a counter instead. + * + * \{ */ + +void BLI_memiter_iter_init(BLI_memiter *mi, BLI_memiter_handle *iter) +{ + iter->elem = mi->head ? (BLI_memiter_elem *)mi->head->data : NULL; + iter->elem_left = mi->count; +} + +bool BLI_memiter_iter_done(BLI_memiter_handle *iter) +{ + return iter->elem_left != 0; +} + +BLI_INLINE void memiter_iter_step(BLI_memiter_handle *iter) +{ + if (UNLIKELY(iter->elem->size < 0)) { + BLI_memiter_chunk *chunk = (BLI_memiter_chunk *)(((data_t *)iter->elem) + iter->elem->size); + chunk = chunk->next; + iter->elem = chunk ? (BLI_memiter_elem *)chunk->data : NULL; + BLI_assert(iter->elem == NULL || iter->elem->size >= 0); + } +} + +void *BLI_memiter_iter_step_size(BLI_memiter_handle *iter, uint *r_size) +{ + if (iter->elem_left != 0) { + iter->elem_left -= 1; + memiter_iter_step(iter); + BLI_assert(iter->elem->size >= 0); + uint size = (uint)iter->elem->size; + *r_size = size; /* <-- only difference */ + data_t *data = iter->elem->data; + iter->elem = (BLI_memiter_elem *)&data[data_offset_from_size(size)]; + return (void *)data; + } + else { + return NULL; + } +} + +void *BLI_memiter_iter_step(BLI_memiter_handle *iter) +{ + if (iter->elem_left != 0) { + iter->elem_left -= 1; + memiter_iter_step(iter); + BLI_assert(iter->elem->size >= 0); + uint size = (uint)iter->elem->size; + data_t *data = iter->elem->data; + iter->elem = (BLI_memiter_elem *)&data[data_offset_from_size(size)]; + return (void *)data; + } + else { + return NULL; + } +} + +/** \} */ diff --git a/tests/gtests/blenlib/BLI_memiter_test.cc b/tests/gtests/blenlib/BLI_memiter_test.cc new file mode 100644 index 00000000000..601eadea267 --- /dev/null +++ b/tests/gtests/blenlib/BLI_memiter_test.cc @@ -0,0 +1,206 @@ +/* Apache License, Version 2.0 */ + +#include "testing/testing.h" + +extern "C" { +#include "BLI_array_utils.h" +#include "BLI_memiter.h" +#include "MEM_guardedalloc.h" + +#include "BLI_string.h" +#include "BLI_ressource_strings.h" +} + +TEST(memiter, Nop) +{ + BLI_memiter *mi = BLI_memiter_create(64); + BLI_memiter_destroy(mi); +} + +void memiter_empty_test(int num_elems, const int chunk_size) +{ + BLI_memiter *mi = BLI_memiter_create(chunk_size); + void *data; + for (int index = 0; index < num_elems; index++) { + data = BLI_memiter_alloc(mi, 0); + } + int index = 0, total_size = 0; + BLI_memiter_handle it; + BLI_memiter_iter_init(mi, &it); + uint elem_size; + while ((data = BLI_memiter_iter_step_size(&it, &elem_size))) { + index += 1; + total_size += elem_size; + } + EXPECT_EQ(0, total_size); + EXPECT_EQ(num_elems, index); + + BLI_memiter_destroy(mi); +} + +#define MEMITER_NUMBER_TEST_FN(fn, number_type) \ +void fn(int num_elems, const int chunk_size) \ +{ \ + BLI_memiter *mi = BLI_memiter_create(chunk_size); \ + number_type *data; \ + for (int index = 0; index < num_elems; index++) { \ + data = (number_type *)BLI_memiter_alloc(mi, sizeof(number_type)); \ + *data = index; \ + } \ + BLI_memiter_handle it; \ + BLI_memiter_iter_init(mi, &it); \ + uint elem_size; \ + int index = 0; \ + while ((data = (number_type *)BLI_memiter_iter_step_size(&it, &elem_size))) { \ + EXPECT_EQ(sizeof(number_type), elem_size); \ + EXPECT_EQ(index, *data); \ + index += 1; \ + } \ + BLI_memiter_destroy(mi); \ +} + +/* generate number functions */ +MEMITER_NUMBER_TEST_FN(memiter_char_test, char) +MEMITER_NUMBER_TEST_FN(memiter_short_test, short) +MEMITER_NUMBER_TEST_FN(memiter_int_test, int) +MEMITER_NUMBER_TEST_FN(memiter_long_test, int64_t) + +void memiter_string_test(const char *strings[], const int chunk_size) +{ + BLI_memiter *mi = BLI_memiter_create(chunk_size); + char *data; + int index = 0; + int total_size_expect = 0; + while (strings[index]) { + const int size = strlen(strings[index]) + 1; + BLI_memiter_alloc_from(mi, size, strings[index]); + total_size_expect += size; + index += 1; + } + const int strings_len = index; + int total_size = 0; + BLI_memiter_handle it; + BLI_memiter_iter_init(mi, &it); + uint elem_size; + index = 0; + while ((data = (char *)BLI_memiter_iter_step_size(&it, &elem_size))) { + EXPECT_EQ(strlen(strings[index]) + 1, elem_size); + EXPECT_STREQ(strings[index], data); + total_size += elem_size; + index += 1; + } + EXPECT_EQ(total_size_expect, total_size); + EXPECT_EQ(strings_len, index); + + BLI_memiter_destroy(mi); +} + +void memiter_words10k_test(const char split_char, const int chunk_size) +{ + const int words_len = sizeof(words10k) - 1; + char *words = BLI_strdupn(words10k, words_len); + BLI_str_replace_char(words, split_char, '\0'); + + BLI_memiter *mi = BLI_memiter_create(chunk_size); + + char *data; + int index; + char *c_end, *c; + c_end = words + words_len; + c = words; + index = 0; + while (c < c_end) { + int elem_size = strlen(c) + 1; + data = (char *)BLI_memiter_alloc(mi, elem_size); + memcpy(data, c, elem_size); + c += elem_size; + index += 1; + } + const int len_expect = index; + c = words; + uint size; + BLI_memiter_handle it; + BLI_memiter_iter_init(mi, &it); + index = 0; + while ((data = (char *)BLI_memiter_iter_step_size(&it, &size))) { + int size_expect = strlen(c) + 1; + EXPECT_EQ(size_expect, size); + EXPECT_STREQ(c, data); + c += size; + index += 1; + } + EXPECT_EQ(len_expect, index); + BLI_memiter_destroy(mi); + MEM_freeN(words); +} + + +#define TEST_EMPTY_AT_CHUNK_SIZE(chunk_size) \ +TEST(memiter, Empty0_##chunk_size) { memiter_empty_test(0, chunk_size); } \ +TEST(memiter, Empty1_##chunk_size) { memiter_empty_test(1, chunk_size); } \ +TEST(memiter, Empty2_##chunk_size) { memiter_empty_test(2, chunk_size); } \ +TEST(memiter, Empty3_##chunk_size) { memiter_empty_test(3, chunk_size); } \ +TEST(memiter, Empty13_##chunk_size) { memiter_empty_test(13, chunk_size); } \ +TEST(memiter, Empty256_##chunk_size) { memiter_empty_test(256, chunk_size); } \ + +TEST_EMPTY_AT_CHUNK_SIZE(1) +TEST_EMPTY_AT_CHUNK_SIZE(2) +TEST_EMPTY_AT_CHUNK_SIZE(3) +TEST_EMPTY_AT_CHUNK_SIZE(13) +TEST_EMPTY_AT_CHUNK_SIZE(256) + +#define TEST_NUMBER_AT_CHUNK_SIZE(chunk_size) \ +TEST(memiter, Char1_##chunk_size) { memiter_char_test(1, chunk_size); } \ +TEST(memiter, Short1_##chunk_size) { memiter_short_test(1, chunk_size); } \ +TEST(memiter, Int1_##chunk_size) { memiter_int_test(1, chunk_size); } \ +TEST(memiter, Long1_##chunk_size) { memiter_long_test(1, chunk_size); } \ +\ +TEST(memiter, Char2_##chunk_size) { memiter_char_test(2, chunk_size); } \ +TEST(memiter, Short2_##chunk_size) { memiter_short_test(2, chunk_size); } \ +TEST(memiter, Int2_##chunk_size) { memiter_int_test(2, chunk_size); } \ +TEST(memiter, Long2_##chunk_size) { memiter_long_test(2, chunk_size); } \ +\ +TEST(memiter, Char3_##chunk_size) { memiter_char_test(3, chunk_size); } \ +TEST(memiter, Short3_##chunk_size) { memiter_short_test(3, chunk_size); } \ +TEST(memiter, Int3_##chunk_size) { memiter_int_test(3, chunk_size); } \ +TEST(memiter, Long3_##chunk_size) { memiter_long_test(3, chunk_size); } \ +\ +TEST(memiter, Char256_##chunk_size) { memiter_char_test(256, chunk_size); } \ +TEST(memiter, Short256_##chunk_size) { memiter_short_test(256, chunk_size); } \ +TEST(memiter, Int256_##chunk_size) { memiter_int_test(256, chunk_size); } \ +TEST(memiter, Long256_##chunk_size) { memiter_long_test(256, chunk_size); } \ + +TEST_NUMBER_AT_CHUNK_SIZE(1) +TEST_NUMBER_AT_CHUNK_SIZE(2) +TEST_NUMBER_AT_CHUNK_SIZE(3) +TEST_NUMBER_AT_CHUNK_SIZE(13) +TEST_NUMBER_AT_CHUNK_SIZE(256) + +#define STRINGS_TEST(chunk_size, ...) { \ + const char *data[] = {__VA_ARGS__, NULL}; \ + memiter_string_test(data, chunk_size); \ +} + +#define TEST_STRINGS_AT_CHUNK_SIZE(chunk_size) \ +TEST(memiter, Strings_##chunk_size) { \ + STRINGS_TEST(chunk_size, ""); \ + STRINGS_TEST(chunk_size, "test", "me"); \ + STRINGS_TEST(chunk_size, "more", "test", "data", "to", "follow"); \ +} + +TEST_STRINGS_AT_CHUNK_SIZE(1) +TEST_STRINGS_AT_CHUNK_SIZE(2) +TEST_STRINGS_AT_CHUNK_SIZE(3) +TEST_STRINGS_AT_CHUNK_SIZE(13) +TEST_STRINGS_AT_CHUNK_SIZE(256) + + +#define TEST_WORDS10K_AT_CHUNK_SIZE(chunk_size) \ +TEST(memiter, Words10kSentence_##chunk_size) { memiter_words10k_test('.', chunk_size); } \ +TEST(memiter, Words10kWords_##chunk_size) { memiter_words10k_test(' ', chunk_size); } \ + +TEST_WORDS10K_AT_CHUNK_SIZE(1) +TEST_WORDS10K_AT_CHUNK_SIZE(2) +TEST_WORDS10K_AT_CHUNK_SIZE(3) +TEST_WORDS10K_AT_CHUNK_SIZE(13) +TEST_WORDS10K_AT_CHUNK_SIZE(256) diff --git a/tests/gtests/blenlib/CMakeLists.txt b/tests/gtests/blenlib/CMakeLists.txt index 8b013e7a7a6..21b1d173e76 100644 --- a/tests/gtests/blenlib/CMakeLists.txt +++ b/tests/gtests/blenlib/CMakeLists.txt @@ -42,6 +42,7 @@ BLENDER_TEST(BLI_stack "bf_blenlib") BLENDER_TEST(BLI_math_color "bf_blenlib") BLENDER_TEST(BLI_math_geom "bf_blenlib;bf_intern_eigen") BLENDER_TEST(BLI_math_base "bf_blenlib") +BLENDER_TEST(BLI_memiter "bf_blenlib") BLENDER_TEST(BLI_string "bf_blenlib") BLENDER_TEST(BLI_string_utf8 "bf_blenlib") if(WIN32) |