diff options
Diffstat (limited to 'source/blender/blenlib')
-rw-r--r-- | source/blender/blenlib/BLI_assert.h | 12 | ||||
-rw-r--r-- | source/blender/blenlib/BLI_memarena.h | 2 | ||||
-rw-r--r-- | source/blender/blenlib/BLI_task.h | 7 | ||||
-rw-r--r-- | source/blender/blenlib/intern/BLI_assert.c | 5 | ||||
-rw-r--r-- | source/blender/blenlib/intern/BLI_memarena.c | 53 | ||||
-rw-r--r-- | source/blender/blenlib/intern/BLI_mempool.c | 2 | ||||
-rw-r--r-- | source/blender/blenlib/intern/expr_pylike_eval.c | 2 | ||||
-rw-r--r-- | source/blender/blenlib/intern/math_color.c | 2 | ||||
-rw-r--r-- | source/blender/blenlib/intern/path_util.c | 2 | ||||
-rw-r--r-- | source/blender/blenlib/intern/system.c | 2 | ||||
-rw-r--r-- | source/blender/blenlib/intern/task_iterator.c | 29 | ||||
-rw-r--r-- | source/blender/blenlib/intern/task_range.cc | 2 | ||||
-rw-r--r-- | source/blender/blenlib/tests/BLI_delaunay_2d_test.cc | 8 |
13 files changed, 107 insertions, 21 deletions
diff --git a/source/blender/blenlib/BLI_assert.h b/source/blender/blenlib/BLI_assert.h index 685f526b4ad..6019f0f3566 100644 --- a/source/blender/blenlib/BLI_assert.h +++ b/source/blender/blenlib/BLI_assert.h @@ -31,6 +31,7 @@ extern "C" { /* Utility functions. */ void _BLI_assert_print_pos(const char *file, const int line, const char *function, const char *id); +void _BLI_assert_print_extra(const char *str); void _BLI_assert_print_backtrace(void); void _BLI_assert_abort(void); void _BLI_assert_unreachable_print(const char *file, const int line, const char *function); @@ -61,8 +62,17 @@ void _BLI_assert_unreachable_print(const char *file, const int line, const char _BLI_ASSERT_ABORT(), \ NULL)) : \ NULL) +/** A version of #BLI_assert() to pass an additional message to be printed on failure. */ +# define BLI_assert_msg(a, msg) \ + (void)((!(a)) ? ((_BLI_assert_print_backtrace(), \ + _BLI_ASSERT_PRINT_POS(a), \ + _BLI_assert_print_extra(msg), \ + _BLI_ASSERT_ABORT(), \ + NULL)) : \ + NULL) #else # define BLI_assert(a) ((void)0) +# define BLI_assert_msg(a, msg) ((void)0) #endif #if defined(__cplusplus) @@ -96,7 +106,7 @@ void _BLI_assert_unreachable_print(const char *file, const int line, const char #define BLI_assert_unreachable() \ { \ _BLI_assert_unreachable_print(__FILE__, __LINE__, __func__); \ - BLI_assert(!"This line of code is marked to be unreachable."); \ + BLI_assert_msg(0, "This line of code is marked to be unreachable."); \ } \ ((void)0) diff --git a/source/blender/blenlib/BLI_memarena.h b/source/blender/blenlib/BLI_memarena.h index d7798f12fcc..b2e05b00735 100644 --- a/source/blender/blenlib/BLI_memarena.h +++ b/source/blender/blenlib/BLI_memarena.h @@ -50,6 +50,8 @@ void *BLI_memarena_alloc(struct MemArena *ma, size_t size) ATTR_WARN_UNUSED_RESU void *BLI_memarena_calloc(struct MemArena *ma, size_t size) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) ATTR_MALLOC ATTR_ALLOC_SIZE(2); +void BLI_memarena_merge(MemArena *ma_dst, MemArena *ma_src) ATTR_NONNULL(1, 2); + void BLI_memarena_clear(MemArena *ma) ATTR_NONNULL(1); #ifdef __cplusplus diff --git a/source/blender/blenlib/BLI_task.h b/source/blender/blenlib/BLI_task.h index dbe8ec3dcc0..418db14e2f3 100644 --- a/source/blender/blenlib/BLI_task.h +++ b/source/blender/blenlib/BLI_task.h @@ -129,6 +129,9 @@ typedef struct TaskParallelTLS { typedef void (*TaskParallelRangeFunc)(void *__restrict userdata, const int iter, const TaskParallelTLS *__restrict tls); + +typedef void (*TaskParallelInitFunc)(const void *__restrict userdata, void *__restrict chunk); + typedef void (*TaskParallelReduceFunc)(const void *__restrict userdata, void *__restrict chunk_join, void *__restrict chunk); @@ -151,6 +154,10 @@ typedef struct TaskParallelSettings { /* Function called from calling thread once whole range have been * processed. */ + /* Function called to initialize user data chunk, + * typically to allocate data, freed by `func_free`. + */ + TaskParallelInitFunc func_init; /* Function called to join user data chunk into another, to reduce * the result to the original userdata_chunk memory. * The reduce functions should have no side effects, so that they diff --git a/source/blender/blenlib/intern/BLI_assert.c b/source/blender/blenlib/intern/BLI_assert.c index 887f583242f..cebc6f8957f 100644 --- a/source/blender/blenlib/intern/BLI_assert.c +++ b/source/blender/blenlib/intern/BLI_assert.c @@ -31,6 +31,11 @@ void _BLI_assert_print_pos(const char *file, const int line, const char *functio fprintf(stderr, "BLI_assert failed: %s:%d, %s(), at \'%s\'\n", file, line, function, id); } +void _BLI_assert_print_extra(const char *str) +{ + fprintf(stderr, " %s\n", str); +} + void _BLI_assert_unreachable_print(const char *file, const int line, const char *function) { fprintf(stderr, "Code marked as unreachable has been executed. Please report this as a bug.\n"); diff --git a/source/blender/blenlib/intern/BLI_memarena.c b/source/blender/blenlib/intern/BLI_memarena.c index fc381c22315..0ab27a5adad 100644 --- a/source/blender/blenlib/intern/BLI_memarena.c +++ b/source/blender/blenlib/intern/BLI_memarena.c @@ -45,6 +45,7 @@ # define VALGRIND_CREATE_MEMPOOL(pool, rzB, is_zeroed) UNUSED_VARS(pool, rzB, is_zeroed) # define VALGRIND_DESTROY_MEMPOOL(pool) UNUSED_VARS(pool) # define VALGRIND_MEMPOOL_ALLOC(pool, addr, size) UNUSED_VARS(pool, addr, size) +# define VALGRIND_MOVE_MEMPOOL(pool_a, pool_b) UNUSED_VARS(pool_a, pool_b) #endif struct MemBuf { @@ -179,6 +180,58 @@ void *BLI_memarena_calloc(MemArena *ma, size_t size) } /** + * Transfer ownership of allocated blocks from `ma_src` into `ma_dst`, + * cleaning the contents of `ma_src`. + * + * \note Useful for multi-threaded tasks that need a thread-local #MemArena + * that is kept after the multi-threaded operation is completed. + * + * \note Avoid accumulating memory pools where possible + * as any unused memory in `ma_src` is wasted every merge. + */ +void BLI_memarena_merge(MemArena *ma_dst, MemArena *ma_src) +{ + /* Memory arenas must be compatible. */ + BLI_assert(ma_dst != ma_src); + BLI_assert(ma_dst->align == ma_src->align); + BLI_assert(ma_dst->use_calloc == ma_src->use_calloc); + BLI_assert(ma_dst->bufsize == ma_src->bufsize); + + if (ma_src->bufs == NULL) { + return; + } + + if (UNLIKELY(ma_dst->bufs == NULL)) { + BLI_assert(ma_dst->curbuf == NULL); + ma_dst->bufs = ma_src->bufs; + ma_dst->curbuf = ma_src->curbuf; + ma_dst->cursize = ma_src->cursize; + } + else { + /* Keep the 'ma_dst->curbuf' for simplicity. + * Insert buffers after the first. */ + if (ma_dst->bufs->next != NULL) { + /* Loop over `ma_src` instead of `ma_dst` since it's likely the destination is larger + * when used for accumulating from multiple sources. */ + struct MemBuf *mb_src = ma_src->bufs; + mb_src = ma_src->bufs; + while (mb_src && mb_src->next) { + mb_src = mb_src->next; + } + mb_src->next = ma_dst->bufs->next; + } + ma_dst->bufs->next = ma_src->bufs; + } + + ma_src->bufs = NULL; + ma_src->curbuf = NULL; + ma_src->cursize = 0; + + VALGRIND_MOVE_MEMPOOL(ma_src, ma_dst); + VALGRIND_CREATE_MEMPOOL(ma_src, 0, false); +} + +/** * Clear for reuse, avoids re-allocation when an arena may * otherwise be free'd and recreated. */ diff --git a/source/blender/blenlib/intern/BLI_mempool.c b/source/blender/blenlib/intern/BLI_mempool.c index 934c1e44dc3..523bb300247 100644 --- a/source/blender/blenlib/intern/BLI_mempool.c +++ b/source/blender/blenlib/intern/BLI_mempool.c @@ -522,7 +522,7 @@ void BLI_mempool_free(BLI_mempool *pool, void *addr) } } if (!found) { - BLI_assert(!"Attempt to free data which is not in pool.\n"); + BLI_assert_msg(0, "Attempt to free data which is not in pool.\n"); } } diff --git a/source/blender/blenlib/intern/expr_pylike_eval.c b/source/blender/blenlib/intern/expr_pylike_eval.c index a5d4130cb20..4d1ba190c14 100644 --- a/source/blender/blenlib/intern/expr_pylike_eval.c +++ b/source/blender/blenlib/intern/expr_pylike_eval.c @@ -569,7 +569,7 @@ static int opcode_arg_count(eOpCode code) case OPCODE_FUNC3: return 3; default: - BLI_assert(!"unexpected opcode"); + BLI_assert_msg(0, "unexpected opcode"); return -1; } } diff --git a/source/blender/blenlib/intern/math_color.c b/source/blender/blenlib/intern/math_color.c index 263c508c07c..da97e697f2f 100644 --- a/source/blender/blenlib/intern/math_color.c +++ b/source/blender/blenlib/intern/math_color.c @@ -153,7 +153,7 @@ void rgb_to_ycc(float r, float g, float b, float *r_y, float *r_cb, float *r_cr, cr = (0.5f * sr) - (0.41869f * sg) - (0.08131f * sb) + 128.0f; break; default: - BLI_assert(!"invalid colorspace"); + BLI_assert_msg(0, "invalid colorspace"); break; } diff --git a/source/blender/blenlib/intern/path_util.c b/source/blender/blenlib/intern/path_util.c index 8969dd4f6b5..4d0dc43ed1e 100644 --- a/source/blender/blenlib/intern/path_util.c +++ b/source/blender/blenlib/intern/path_util.c @@ -1275,7 +1275,7 @@ void BLI_setenv(const char *env, const char *val) { /* free windows */ -#if (defined(WIN32) || defined(WIN64)) +#if (defined(_WIN32) || defined(_WIN64)) uputenv(env, val); #else diff --git a/source/blender/blenlib/intern/system.c b/source/blender/blenlib/intern/system.c index 87330cf4899..66d0b44cfb3 100644 --- a/source/blender/blenlib/intern/system.c +++ b/source/blender/blenlib/intern/system.c @@ -184,7 +184,7 @@ size_t BLI_system_memory_max_in_megabytes(void) /* Maximum addressable bytes on this platform. * * NOTE: Due to the shift arithmetic this is a half of the memory. */ - const size_t limit_bytes_half = (((size_t)1) << ((sizeof(size_t[8])) - 1)); + const size_t limit_bytes_half = (((size_t)1) << (sizeof(size_t[8]) - 1)); /* Convert it to megabytes and return. */ return (limit_bytes_half >> 20) * 2; } diff --git a/source/blender/blenlib/intern/task_iterator.c b/source/blender/blenlib/intern/task_iterator.c index 0ff408ddb0a..06087869685 100644 --- a/source/blender/blenlib/intern/task_iterator.c +++ b/source/blender/blenlib/intern/task_iterator.c @@ -186,6 +186,9 @@ static void task_parallel_iterator_no_threads(const TaskParallelSettings *settin if (use_userdata_chunk) { userdata_chunk_local = MALLOCA(userdata_chunk_size); memcpy(userdata_chunk_local, userdata_chunk, userdata_chunk_size); + if (settings->func_init != NULL) { + settings->func_init(state->userdata, userdata_chunk_local); + } } /* Also marking it as non-threaded for the iterator callback. */ @@ -247,6 +250,9 @@ static void task_parallel_iterator_do(const TaskParallelSettings *settings, if (use_userdata_chunk) { userdata_chunk_local = (char *)userdata_chunk_array + (userdata_chunk_size * i); memcpy(userdata_chunk_local, userdata_chunk, userdata_chunk_size); + if (settings->func_init != NULL) { + settings->func_init(state->userdata, userdata_chunk_local); + } } /* Use this pool's pre-allocated tasks. */ BLI_task_pool_push(task_pool, parallel_iterator_func, userdata_chunk_local, false, NULL); @@ -403,11 +409,7 @@ void BLI_task_parallel_mempool(BLI_mempool *mempool, TaskParallelMempoolFunc func, const TaskParallelSettings *settings) { - TaskPool *task_pool; - ParallelMempoolState state; - int i, num_threads, num_tasks; - - if (BLI_mempool_len(mempool) == 0) { + if (UNLIKELY(BLI_mempool_len(mempool) == 0)) { return; } @@ -422,6 +424,9 @@ void BLI_task_parallel_mempool(BLI_mempool *mempool, if (use_userdata_chunk) { userdata_chunk_local = MALLOCA(userdata_chunk_size); memcpy(userdata_chunk_local, userdata_chunk, userdata_chunk_size); + if (settings->func_init != NULL) { + settings->func_init(userdata, userdata_chunk_local); + } tls.userdata_chunk = userdata_chunk_local; } @@ -442,14 +447,15 @@ void BLI_task_parallel_mempool(BLI_mempool *mempool, return; } - task_pool = BLI_task_pool_create(&state, TASK_PRIORITY_HIGH); - num_threads = BLI_task_scheduler_num_threads(); + ParallelMempoolState state; + TaskPool *task_pool = BLI_task_pool_create(&state, TASK_PRIORITY_HIGH); + const int num_threads = BLI_task_scheduler_num_threads(); /* The idea here is to prevent creating task for each of the loop iterations * and instead have tasks which are evenly distributed across CPU cores and * pull next item to be crunched using the threaded-aware BLI_mempool_iter. */ - num_tasks = num_threads + 2; + const int num_tasks = num_threads + 2; state.userdata = userdata; state.func = func; @@ -461,10 +467,13 @@ void BLI_task_parallel_mempool(BLI_mempool *mempool, ParallelMempoolTaskData *mempool_iterator_data = mempool_iter_threadsafe_create( mempool, (size_t)num_tasks); - for (i = 0; i < num_tasks; i++) { + for (int i = 0; i < num_tasks; i++) { if (use_userdata_chunk) { userdata_chunk_local = (char *)userdata_chunk_array + (userdata_chunk_size * i); memcpy(userdata_chunk_local, userdata_chunk, userdata_chunk_size); + if (settings->func_init != NULL) { + settings->func_init(userdata, userdata_chunk_local); + } } mempool_iterator_data[i].tls.userdata_chunk = userdata_chunk_local; @@ -477,7 +486,7 @@ void BLI_task_parallel_mempool(BLI_mempool *mempool, if (use_userdata_chunk) { if ((settings->func_free != NULL) || (settings->func_reduce != NULL)) { - for (i = 0; i < num_tasks; i++) { + for (int i = 0; i < num_tasks; i++) { if (settings->func_reduce) { settings->func_reduce( userdata, userdata_chunk, mempool_iterator_data[i].tls.userdata_chunk); diff --git a/source/blender/blenlib/intern/task_range.cc b/source/blender/blenlib/intern/task_range.cc index 871d04c1f35..8407be2cb2b 100644 --- a/source/blender/blenlib/intern/task_range.cc +++ b/source/blender/blenlib/intern/task_range.cc @@ -156,7 +156,7 @@ int BLI_task_parallel_thread_id(const TaskParallelTLS *UNUSED(tls)) if (thread_id == -1) { thread_id = atomic_fetch_and_add_int32(&tbb_thread_id_counter, 1); if (thread_id >= BLENDER_MAX_THREADS) { - BLI_assert(!"Maximum number of threads exceeded for sculpting"); + BLI_assert_msg(0, "Maximum number of threads exceeded for sculpting"); thread_id = thread_id % BLENDER_MAX_THREADS; } } diff --git a/source/blender/blenlib/tests/BLI_delaunay_2d_test.cc b/source/blender/blenlib/tests/BLI_delaunay_2d_test.cc index 59c4be6d952..08a3818e18f 100644 --- a/source/blender/blenlib/tests/BLI_delaunay_2d_test.cc +++ b/source/blender/blenlib/tests/BLI_delaunay_2d_test.cc @@ -353,27 +353,27 @@ void graph_draw(const std::string &label, const vec2<T> &uco = verts[e.first]; const vec2<T> &vco = verts[e.second]; int strokew = thin_line; - f << "<line fill=\"none\" stroke=\"black\" stroke-width=\"" << strokew << "\" x1=\"" + f << R"(<line fill="none" stroke="black" stroke-width=")" << strokew << "\" x1=\"" << SX(uco[0]) << "\" y1=\"" << SY(uco[1]) << "\" x2=\"" << SX(vco[0]) << "\" y2=\"" << SY(vco[1]) << "\">\n"; f << " <title>[" << e.first << "][" << e.second << "]</title>\n"; f << "</line>\n"; if (draw_edge_labels) { f << "<text x=\"" << SX(0.5 * (uco[0] + vco[0])) << "\" y=\"" << SY(0.5 * (uco[1] + vco[1])) - << "\" font-size=\"small\">"; + << R"(" font-size="small">)"; f << "[" << e.first << "][" << e.second << "]</text>\n"; } } int i = 0; for (const vec2<T> &vco : verts) { - f << "<circle fill=\"black\" cx=\"" << SX(vco[0]) << "\" cy=\"" << SY(vco[1]) << "\" r=\"" + f << R"(<circle fill="black" cx=")" << SX(vco[0]) << "\" cy=\"" << SY(vco[1]) << "\" r=\"" << vert_radius << "\">\n"; f << " <title>[" << i << "]" << vco << "</title>\n"; f << "</circle>\n"; if (draw_vert_labels) { f << "<text x=\"" << SX(vco[0]) + vert_radius << "\" y=\"" << SY(vco[1]) - vert_radius - << "\" font-size=\"small\">[" << i << "]</text>\n"; + << R"(" font-size="small">[)" << i << "]</text>\n"; } ++i; } |