diff options
Diffstat (limited to 'source/blender/blenlib')
-rw-r--r-- | source/blender/blenlib/BLI_asan.h | 4 | ||||
-rw-r--r-- | source/blender/blenlib/BLI_compiler_attrs.h | 11 | ||||
-rw-r--r-- | source/blender/blenlib/BLI_ghash.h | 43 | ||||
-rw-r--r-- | source/blender/blenlib/BLI_linklist_stack.h | 2 | ||||
-rw-r--r-- | source/blender/blenlib/BLI_mempool.h | 13 | ||||
-rw-r--r-- | source/blender/blenlib/BLI_strict_flags.h | 24 | ||||
-rw-r--r-- | source/blender/blenlib/intern/BLI_ghash_utils.c | 119 | ||||
-rw-r--r-- | source/blender/blenlib/intern/BLI_mempool.c | 219 | ||||
-rw-r--r-- | source/blender/blenlib/intern/task_pool.cc | 3 |
9 files changed, 408 insertions, 30 deletions
diff --git a/source/blender/blenlib/BLI_asan.h b/source/blender/blenlib/BLI_asan.h index c38ad6b39d0..fadf7fc3362 100644 --- a/source/blender/blenlib/BLI_asan.h +++ b/source/blender/blenlib/BLI_asan.h @@ -21,8 +21,8 @@ # define __has_feature(x) 0 #endif -#if (defined(__SANITIZE_ADDRESS__) || __has_feature(address_sanitizer)) && !defined(_MSC_VER) -# include "sanitizer/asan_interface.h" +#if (defined(__SANITIZE_ADDRESS__) || __has_feature(address_sanitizer)) +# include "sanitizer/asan_interface.h" #else /* Ensure return value is used. Just using UNUSED_VARS results in a warning. */ # define ASAN_POISON_MEMORY_REGION(addr, size) (void)(0 && ((size) != 0 && (addr) != NULL)) diff --git a/source/blender/blenlib/BLI_compiler_attrs.h b/source/blender/blenlib/BLI_compiler_attrs.h index 4b5a7d671f2..bf31e35cd50 100644 --- a/source/blender/blenlib/BLI_compiler_attrs.h +++ b/source/blender/blenlib/BLI_compiler_attrs.h @@ -99,6 +99,17 @@ # define ATTR_ALIGN(x) __attribute__((aligned(x))) #endif +/* Disable optimization for a function (for debugging use only!)*/ +#ifdef __clang__ +# define ATTR_NO_OPT __attribute__((optnone)) +#elif defined(__MSC_VER) +# define ATTR_NO_OPT __pragma(optimize("", off)) +#elif defined(__GNUC__) +# define ATTR_NO_OPT __attribute__((optimize("O0"))) +#else +# define ATTR_NO_OPT +#endif + /* Alignment directive */ #ifdef _WIN64 # define ALIGN_STRUCT __declspec(align(64)) diff --git a/source/blender/blenlib/BLI_ghash.h b/source/blender/blenlib/BLI_ghash.h index e708b327bd4..4386f52140d 100644 --- a/source/blender/blenlib/BLI_ghash.h +++ b/source/blender/blenlib/BLI_ghash.h @@ -188,6 +188,49 @@ BLI_INLINE bool BLI_ghashIterator_done(const GHashIterator *ghi) typedef struct GSet GSet; +typedef struct TableGSet { + struct GHash *ptr_to_idx; + void **elems; + int size, length; + int cur; +} TableGSet; + +TableGSet *BLI_table_gset_new(const char *info); +TableGSet *BLI_table_gset_new_ex(const char *info, int size); +void BLI_table_gset_free(TableGSet *ts, GHashKeyFreeFP freefp); +void BLI_table_gset_insert(TableGSet *ts, void *elem); +bool BLI_table_gset_add(TableGSet *ts, void *elem); +void BLI_table_gset_remove(TableGSet *ts, void *elem, GHashKeyFreeFP freefp); +bool BLI_table_gset_haskey(TableGSet *ts, void *elem); + +int BLI_table_gset_len(TableGSet *ts); + +#define TGSET_ITER(v, ts) \ + { \ + int _i1; \ + for (_i1 = 0; _i1 < (ts)->cur; _i1++) { \ + if (!(ts)->elems[_i1]) \ + continue; \ + v = (ts)->elems[_i1]; + +#define TGSET_ITER_END \ + } \ + } + +#define TGSET_ITER_INDEX(v, ts, index) \ + { \ + int _i1; \ + index = -1; \ + for (_i1 = 0; _i1 < (ts)->cur; _i1++) { \ + if (!(ts)->elems[_i1]) \ + continue; \ + v = (ts)->elems[_i1]; \ + index++; + +#define TGSET_ITER_INDEX_END \ + } \ + } \ + typedef GHashHashFP GSetHashFP; typedef GHashCmpFP GSetCmpFP; typedef GHashKeyFreeFP GSetKeyFreeFP; diff --git a/source/blender/blenlib/BLI_linklist_stack.h b/source/blender/blenlib/BLI_linklist_stack.h index 8a5e94a7b56..c07a0376f5b 100644 --- a/source/blender/blenlib/BLI_linklist_stack.h +++ b/source/blender/blenlib/BLI_linklist_stack.h @@ -52,7 +52,7 @@ #define BLI_LINKSTACK_SIZE(var) BLI_mempool_len(var##_pool_) /* check for typeof() */ -#ifdef __GNUC__ +#if defined(__GNUC__) || defined(__clang__) # define BLI_LINKSTACK_PUSH(var, ptr) \ (CHECK_TYPE_INLINE(ptr, typeof(var##_type_)), \ BLI_linklist_prepend_pool(&(var), ptr, var##_pool_)) diff --git a/source/blender/blenlib/BLI_mempool.h b/source/blender/blenlib/BLI_mempool.h index 61b572a4943..b8e1a22b875 100644 --- a/source/blender/blenlib/BLI_mempool.h +++ b/source/blender/blenlib/BLI_mempool.h @@ -92,6 +92,19 @@ enum { void BLI_mempool_iternew(BLI_mempool *pool, BLI_mempool_iter *iter) ATTR_NONNULL(); void *BLI_mempool_iterstep(BLI_mempool_iter *iter) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); +/* +This preallocates a mempool suitable for threading. totelem elements are preallocated +in chunks of size pchunk, and returned in r_chunks. +*/ + +BLI_mempool *BLI_mempool_create_for_tasks(const unsigned int esize, + int totelem, + const int pchunk, + void ***r_chunks, + int *r_totchunk, + int *r_esize, + int flag); + #ifdef __cplusplus } #endif diff --git a/source/blender/blenlib/BLI_strict_flags.h b/source/blender/blenlib/BLI_strict_flags.h index b967d7e494d..ab7aacc4d2d 100644 --- a/source/blender/blenlib/BLI_strict_flags.h +++ b/source/blender/blenlib/BLI_strict_flags.h @@ -45,10 +45,22 @@ #endif #ifdef _MSC_VER -# pragma warning(error : 4018) /* signed/unsigned mismatch */ -# pragma warning(error : 4244) /* conversion from 'type1' to 'type2', possible loss of data */ -# pragma warning(error : 4245) /* conversion from 'int' to 'unsigned int' */ -# pragma warning(error : 4267) /* conversion from 'size_t' to 'type', possible loss of data */ -# pragma warning(error : 4305) /* truncation from 'type1' to 'type2' */ -# pragma warning(error : 4389) /* signed/unsigned mismatch */ +/* While regular clang defines __GNUC__ and is handled by the code above, clang-cl does not and + * needs to be handled separately. */ +# ifdef __clang__ +# pragma clang diagnostic error "-Wsign-conversion" +# pragma clang diagnostic error "-Wsign-compare" +# pragma clang diagnostic error "-Wimplicit-float-conversion" +# pragma clang diagnostic error "-Wimplicit-int-conversion" +# pragma clang diagnostic error "-Wimplicit-int" +# pragma clang diagnostic error "-Wshadow" +/* Normal MSVC */ +# else +# pragma warning(error : 4018) /* signed/unsigned mismatch */ +# pragma warning(error : 4244) /* conversion from 'type1' to 'type2', possible loss of data */ +# pragma warning(error : 4245) /* conversion from 'int' to 'unsigned int' */ +# pragma warning(error : 4267) /* conversion from 'size_t' to 'type', possible loss of data */ +# pragma warning(error : 4305) /* truncation from 'type1' to 'type2' */ +# pragma warning(error : 4389) /* signed/unsigned mismatch */ +# endif #endif diff --git a/source/blender/blenlib/intern/BLI_ghash_utils.c b/source/blender/blenlib/intern/BLI_ghash_utils.c index 182c27aed6d..034f71e4deb 100644 --- a/source/blender/blenlib/intern/BLI_ghash_utils.c +++ b/source/blender/blenlib/intern/BLI_ghash_utils.c @@ -288,4 +288,123 @@ GSet *BLI_gset_int_new(const char *info) return BLI_gset_int_new_ex(info, 0); } +TableGSet *BLI_table_gset_new(const char *info) +{ + TableGSet *ts = MEM_callocN(sizeof(TableGSet), info); + + ts->ptr_to_idx = BLI_ghash_ptr_new(info); + + return ts; +} + +TableGSet *BLI_table_gset_new_ex(const char *info, int size) +{ + TableGSet *ts = MEM_callocN(sizeof(TableGSet), info); + + ts->ptr_to_idx = BLI_ghash_ptr_new_ex(info, (uint)size); + if (size) { + ts->elems = MEM_callocN(sizeof(void *) * (uint)size, info); + ts->size = size; + ts->length = 0; + ts->cur = 0; + } + + return ts; +} + +void BLI_table_gset_free(TableGSet *ts, GHashKeyFreeFP freefp) +{ + if (!ts->ptr_to_idx) { + return; + } + + if (ts->elems) { + MEM_freeN(ts->elems); + } + + BLI_ghash_free(ts->ptr_to_idx, freefp, NULL); + ts->ptr_to_idx = NULL; + + MEM_freeN(ts); +} + +bool BLI_table_gset_add(TableGSet *ts, void *elem) +{ + if (BLI_table_gset_haskey(ts, elem)) { + return true; + } + + BLI_table_gset_insert(ts, elem); + return false; +} + +void BLI_table_gset_insert(TableGSet *ts, void *elem) +{ + if (ts->cur >= ts->size) { + uint newsize = (uint)(ts->cur + 1); + newsize = (newsize << 1U) - (newsize >> 1U); + newsize = MAX2(newsize, 8U); + + if (!ts->elems) { + ts->elems = (void *)MEM_mallocN(sizeof(void *) * newsize, "ts->elems"); + } + else { + ts->elems = (void *)MEM_reallocN(ts->elems, newsize * sizeof(void *)); + } + + BLI_ghash_clear(ts->ptr_to_idx, NULL, NULL); + + // compact + int i = 0, j = 0; + for (i = 0; i < ts->cur; i++) { + void *elem2 = ts->elems[i]; + + if (elem2) { + BLI_ghash_insert(ts->ptr_to_idx, elem2, (void *)j); + ts->elems[j++] = elem2; + } + } + + ts->size = (int)newsize; + ts->cur = j; + } + + BLI_ghash_insert(ts->ptr_to_idx, elem, (void *)ts->cur); + ts->elems[ts->cur++] = elem; + ts->length++; +} + +void BLI_table_gset_remove(TableGSet *ts, void *elem, GHashKeyFreeFP freefp) +{ + if (!elem || !ts) { + return; + } + + int *idx = (int *)BLI_ghash_lookup_p(ts->ptr_to_idx, elem); + if (!idx) { + return; + } + + int idx2 = *idx; + + BLI_ghash_remove(ts->ptr_to_idx, elem, freefp, NULL); + + if (!ts->elems || ts->elems[idx2] != elem) { + return; + } + + ts->length--; + ts->elems[idx2] = NULL; +} + +bool BLI_table_gset_haskey(TableGSet *ts, void *elem) +{ + return BLI_ghash_haskey(ts->ptr_to_idx, elem); +} + +int BLI_table_gset_len(TableGSet *ts) +{ + return ts->length; +} + /** \} */ diff --git a/source/blender/blenlib/intern/BLI_mempool.c b/source/blender/blenlib/intern/BLI_mempool.c index 5263af2ae56..523bb300247 100644 --- a/source/blender/blenlib/intern/BLI_mempool.c +++ b/source/blender/blenlib/intern/BLI_mempool.c @@ -36,6 +36,7 @@ #include "BLI_utildefines.h" +#include "BLI_asan.h" #include "BLI_mempool.h" /* own include */ #include "BLI_mempool_private.h" /* own include */ @@ -47,6 +48,12 @@ # include "valgrind/memcheck.h" #endif +#if (defined(__SANITIZE_ADDRESS__) || __has_feature(address_sanitizer)) +# define POISON_REDZONE_SIZE 32 +#else +# define POISON_REDZONE_SIZE 0 +#endif + /* NOTE: copied from BLO_blend_defs.h, don't use here because we're in BLI. */ #ifdef __BIG_ENDIAN__ /* Big Endian */ @@ -222,22 +229,42 @@ static BLI_freenode *mempool_chunk_add(BLI_mempool *pool, j = pool->pchunk; if (pool->flag & BLI_MEMPOOL_ALLOW_ITER) { while (j--) { - curnode->next = NODE_STEP_NEXT(curnode); + BLI_freenode *next; + + BLI_asan_unpoison(curnode, pool->esize); + + curnode->next = next = NODE_STEP_NEXT(curnode); curnode->freeword = FREEWORD; - curnode = curnode->next; + + BLI_asan_poison(curnode, pool->esize); + + curnode = next; } } else { while (j--) { - curnode->next = NODE_STEP_NEXT(curnode); - curnode = curnode->next; + BLI_freenode *next; + + BLI_asan_unpoison(curnode, pool->esize); + curnode->next = next = NODE_STEP_NEXT(curnode); + BLI_asan_poison(curnode, pool->esize); + + curnode = next; } } /* terminate the list (rewind one) * will be overwritten if 'curnode' gets passed in again as 'last_tail' */ + + BLI_asan_unpoison(curnode, pool->esize); + BLI_freenode *prev = NODE_STEP_PREV(curnode); + BLI_asan_poison(curnode, pool->esize); + curnode = NODE_STEP_PREV(curnode); + + BLI_asan_unpoison(curnode, pool->esize); curnode->next = NULL; + BLI_asan_poison(curnode, pool->esize); #ifdef USE_TOTALLOC pool->totalloc += pool->pchunk; @@ -245,24 +272,128 @@ static BLI_freenode *mempool_chunk_add(BLI_mempool *pool, /* final pointer in the previously allocated chunk is wrong */ if (last_tail) { + BLI_asan_unpoison(last_tail, pool->esize); last_tail->next = CHUNK_DATA(mpchunk); + BLI_asan_poison(last_tail, pool->esize); } return curnode; } -static void mempool_chunk_free(BLI_mempool_chunk *mpchunk) +/* +This preallocates a mempool suitable for threading. totelem elements are preallocated +in chunks of size pchunk, and returned in r_chunks. The idea is to pass these +to tasks. +*/ + +BLI_mempool *BLI_mempool_create_for_tasks(const unsigned int esize, + int totelem, + const int pchunk, + void ***r_chunks, + int *r_totchunk, + int *r_esize, + int flag) +{ + BLI_mempool *pool = BLI_mempool_create(esize, 0, (uint)pchunk, (uint)flag); + + // override pchunk, may not be a power of 2 + pool->pchunk = (uint)pchunk; + pool->csize = (uint)pchunk * pool->esize; + + if (totelem % pchunk == 0) { + pool->maxchunks = (uint)totelem / (uint)pchunk; + } + else { + pool->maxchunks = (uint)totelem / (uint)pchunk + 1; + } + + if (totelem) { + BLI_freenode *last_tail = NULL; + + /* Allocate the actual chunks. */ + for (uint i = 0; i < pool->maxchunks; i++) { + BLI_mempool_chunk *mpchunk = mempool_chunk_alloc(pool); + last_tail = mempool_chunk_add(pool, mpchunk, last_tail); + } + } + + void **chunks = MEM_callocN(sizeof(void *) * pool->maxchunks, + "BLI_mempool_create_for_tasks r_chunks"); + + unsigned int totalloc = 0; + *r_totchunk = 0; + + BLI_mempool_chunk *chunk = pool->chunks, *lastchunk = NULL; + + while (chunk) { + lastchunk = chunk; + totalloc += pool->pchunk; + chunk = chunk->next; + } + + pool->totused = totalloc; + pool->free = NULL; + + int i = (int)pool->pchunk - 1; + + while (lastchunk && totalloc > (uint)totelem) { + if (i < 0) { + BLI_mempool_chunk *lastchunk2 = NULL; + + for (chunk = pool->chunks; chunk; chunk = chunk->next) { + if (chunk == lastchunk) { + lastchunk = lastchunk2; + } + } + + if (!lastchunk) { + break; + } + + i = (int)pool->pchunk - 1; + } + + char *elem = CHUNK_DATA(lastchunk); + elem += pool->esize * (unsigned int)i; + + BLI_mempool_free(pool, elem); + + totalloc--; + i--; + } + + int ci = 0; + + chunk = pool->chunks; + while (chunk && chunk != lastchunk) { + chunks[ci++] = CHUNK_DATA(chunk); + chunk = chunk->next; + } + + if (lastchunk && i >= 0) { + chunks[ci++] = CHUNK_DATA(lastchunk); + } + + *r_totchunk = ci; + *r_chunks = (void **)chunks; + *r_esize = (int)pool->esize; + + return pool; +} + +static void mempool_chunk_free(BLI_mempool_chunk *mpchunk, BLI_mempool *pool) { + BLI_asan_unpoison(mpchunk, sizeof(BLI_mempool_chunk) + pool->esize * pool->csize); MEM_freeN(mpchunk); } -static void mempool_chunk_free_all(BLI_mempool_chunk *mpchunk) +static void mempool_chunk_free_all(BLI_mempool_chunk *mpchunk, BLI_mempool *pool) { BLI_mempool_chunk *mpchunk_next; for (; mpchunk; mpchunk = mpchunk_next) { mpchunk_next = mpchunk->next; - mempool_chunk_free(mpchunk); + mempool_chunk_free(mpchunk, pool); } } @@ -284,6 +415,8 @@ BLI_mempool *BLI_mempool_create(uint esize, uint totelem, uint pchunk, uint flag esize = MAX2(esize, (uint)sizeof(BLI_freenode)); } + esize += POISON_REDZONE_SIZE; + maxchunks = mempool_maxchunks(totelem, pchunk); pool->chunks = NULL; @@ -344,6 +477,8 @@ void *BLI_mempool_alloc(BLI_mempool *pool) free_pop = pool->free; + BLI_asan_unpoison(free_pop, pool->esize - POISON_REDZONE_SIZE); + BLI_assert(pool->chunk_tail->next == NULL); if (pool->flag & BLI_MEMPOOL_ALLOW_ITER) { @@ -363,7 +498,7 @@ void *BLI_mempool_alloc(BLI_mempool *pool) void *BLI_mempool_calloc(BLI_mempool *pool) { void *retval = BLI_mempool_alloc(pool); - memset(retval, 0, (size_t)pool->esize); + memset(retval, 0, (size_t)pool->esize - POISON_REDZONE_SIZE); return retval; } @@ -393,7 +528,7 @@ void BLI_mempool_free(BLI_mempool *pool, void *addr) /* Enable for debugging. */ if (UNLIKELY(mempool_debug_memset)) { - memset(addr, 255, pool->esize); + memset(addr, 255, pool->esize - POISON_REDZONE_SIZE); } #endif @@ -408,6 +543,8 @@ void BLI_mempool_free(BLI_mempool *pool, void *addr) newhead->next = pool->free; pool->free = newhead; + BLI_asan_poison(newhead, pool->esize); + pool->totused--; #ifdef WITH_MEM_VALGRIND @@ -422,7 +559,7 @@ void BLI_mempool_free(BLI_mempool *pool, void *addr) BLI_mempool_chunk *first; first = pool->chunks; - mempool_chunk_free_all(first->next); + mempool_chunk_free_all(first->next, pool); first->next = NULL; pool->chunk_tail = first; @@ -440,11 +577,21 @@ void BLI_mempool_free(BLI_mempool *pool, void *addr) j = pool->pchunk; while (j--) { - curnode->next = NODE_STEP_NEXT(curnode); - curnode = curnode->next; + BLI_asan_unpoison(curnode, pool->esize); + BLI_freenode *next = curnode->next = NODE_STEP_NEXT(curnode); + BLI_asan_poison(curnode, pool->esize); + curnode = next; } - curnode = NODE_STEP_PREV(curnode); + + BLI_asan_unpoison(curnode, pool->esize); + BLI_freenode *prev = NODE_STEP_PREV(curnode); + BLI_asan_poison(curnode, pool->esize); + + curnode = prev; + + BLI_asan_unpoison(curnode, pool->esize); curnode->next = NULL; /* terminate the list */ + BLI_asan_poison(curnode, pool->esize); #ifdef WITH_MEM_VALGRIND VALGRIND_MEMPOOL_FREE(pool, CHUNK_DATA(first)); @@ -510,7 +657,7 @@ void **BLI_mempool_as_tableN(BLI_mempool *pool, const char *allocstr) */ void BLI_mempool_as_array(BLI_mempool *pool, void *data) { - const uint esize = pool->esize; + const uint esize = pool->esize - (uint)POISON_REDZONE_SIZE; BLI_mempool_iter iter; char *elem, *p = data; BLI_assert(pool->flag & BLI_MEMPOOL_ALLOW_ITER); @@ -638,12 +785,16 @@ void *BLI_mempool_iterstep(BLI_mempool_iter *iter) return NULL; } + intptr_t freeword = 0; + const uint esize = iter->pool->esize; BLI_freenode *curnode = POINTER_OFFSET(CHUNK_DATA(iter->curchunk), (esize * iter->curindex)); BLI_freenode *ret; do { ret = curnode; + BLI_asan_unpoison(ret, iter->pool->esize - POISON_REDZONE_SIZE); + if (++iter->curindex != iter->pool->pchunk) { curnode = POINTER_OFFSET(curnode, esize); } @@ -651,7 +802,13 @@ void *BLI_mempool_iterstep(BLI_mempool_iter *iter) iter->curindex = 0; iter->curchunk = iter->curchunk->next; if (UNLIKELY(iter->curchunk == NULL)) { - return (ret->freeword == FREEWORD) ? NULL : ret; + BLI_asan_unpoison(ret, iter->pool->esize - POISON_REDZONE_SIZE); + void *ret2 = (ret->freeword == FREEWORD) ? NULL : ret; + + if (ret->freeword == FREEWORD) { + BLI_asan_poison(ret, iter->pool->esize); + } + return ret2; } curnode = CHUNK_DATA(iter->curchunk); } @@ -678,6 +835,8 @@ void *mempool_iter_threadsafe_step(BLI_mempool_threadsafe_iter *ts_iter) do { ret = curnode; + BLI_asan_unpoison(ret, esize - POISON_REDZONE_SIZE); + if (++iter->curindex != iter->pool->pchunk) { curnode = POINTER_OFFSET(curnode, esize); } @@ -693,17 +852,37 @@ void *mempool_iter_threadsafe_step(BLI_mempool_threadsafe_iter *ts_iter) /* pass. */ } if (UNLIKELY(iter->curchunk == NULL)) { - return (ret->freeword == FREEWORD) ? NULL : ret; + if (ret->freeword == FREEWORD) { + BLI_asan_poison(ret, esize); + return NULL; + } + else { + return ret; + } } /* End `threadsafe` exception. */ iter->curchunk = iter->curchunk->next; if (UNLIKELY(iter->curchunk == NULL)) { - return (ret->freeword == FREEWORD) ? NULL : ret; + if (ret->freeword == FREEWORD) { + BLI_asan_poison(ret, iter->pool->esize); + return NULL; + } + else { + return ret; + } } + curnode = CHUNK_DATA(iter->curchunk); } - } while (ret->freeword == FREEWORD); + + if (ret->freeword == FREEWORD) { + BLI_asan_poison(ret, iter->pool->esize); + } + else { + break; + } + } while (true); return ret; } @@ -747,7 +926,7 @@ void BLI_mempool_clear_ex(BLI_mempool *pool, const int totelem_reserve) do { mpchunk_next = mpchunk->next; - mempool_chunk_free(mpchunk); + mempool_chunk_free(mpchunk, pool); } while ((mpchunk = mpchunk_next)); } @@ -781,7 +960,7 @@ void BLI_mempool_clear(BLI_mempool *pool) */ void BLI_mempool_destroy(BLI_mempool *pool) { - mempool_chunk_free_all(pool->chunks); + mempool_chunk_free_all(pool->chunks, pool); #ifdef WITH_MEM_VALGRIND VALGRIND_DESTROY_MEMPOOL(pool); diff --git a/source/blender/blenlib/intern/task_pool.cc b/source/blender/blenlib/intern/task_pool.cc index 6250c1b9986..367a3d7599f 100644 --- a/source/blender/blenlib/intern/task_pool.cc +++ b/source/blender/blenlib/intern/task_pool.cc @@ -90,7 +90,8 @@ class Task { other.freedata = nullptr; } -#if defined(WITH_TBB) && TBB_INTERFACE_VERSION_MAJOR < 10 +#if (defined(WITH_TBB) && TBB_INTERFACE_VERSION_MAJOR < 10) || \ + (defined(__clang__) && defined(WIN32)) Task(const Task &other) : pool(other.pool), run(other.run), |