BLI: use blender::Mutex by default which wraps tbb::mutex

This patch adds a new `BLI_mutex.hh` header which adds `blender::Mutex` as alias
for either `tbb::mutex` or `std::mutex` depending on whether TBB is enabled.

Description copied from the patch:
```
/**
 * blender::Mutex should be used as the default mutex in Blender. It implements a subset of the API
 * of std::mutex but has overall better guaranteed properties. It can be used with RAII helpers
 * like std::lock_guard. However, it is not compatible with e.g. std::condition_variable. So one
 * still has to use std::mutex for that case.
 *
 * The mutex provided by TBB has these properties:
 * - It's as fast as a spin-lock in the non-contended case, i.e. when no other thread is trying to
 *   lock the mutex at the same time.
 * - In the contended case, it spins a couple of times but then blocks to avoid draining system
 *   resources by spinning for a long time.
 * - It's only 1 byte large, compared to e.g. 40 bytes when using the std::mutex of GCC. This makes
 *   it more feasible to have many smaller mutexes which can improve scalability of algorithms
 *   compared to using fewer larger mutexes. Also it just reduces "memory slop" across Blender.
 * - It is *not* a fair mutex, i.e. it's not guaranteed that a thread will ever be able to lock the
 *   mutex when there are always more than one threads that try to lock it. In the majority of
 *   cases, using a fair mutex just causes extra overhead without any benefit. std::mutex is not
 *   guaranteed to be fair either.
 */
 ```

The performance benchmark suggests that the impact is negilible in almost
all cases. The only benchmarks that show interesting behavior are the once
testing foreach zones in Geometry Nodes. These tests are explicitly testing
overhead, which I still have to reduce over time. So it's not unexpected that
changing the mutex has an impact there. What's interesting is that on macos the
performance improves a lot while on linux it gets worse. Since that overhead
should eventually be removed almost entirely, I don't really consider that
blocking.

Links:
* Documentation of different mutex flavors in TBB:
  https://www.intel.com/content/www/us/en/docs/onetbb/developer-guide-api-reference/2021-12/mutex-flavors.html
* Older implementation of a similar mutex by me:
  https://archive.blender.org/developer/differential/0016/0016711/index.html
* Interesting read regarding how a mutex can be this small:
  https://webkit.org/blog/6161/locking-in-webkit/

Pull Request: https://projects.blender.org/blender/blender/pulls/138370
This commit is contained in:
Jacques Lucke
2025-05-07 04:53:16 +02:00
parent ed29ab303c
commit b7a1325c3c
50 changed files with 149 additions and 97 deletions

View File

@@ -9,13 +9,13 @@
#pragma once
#include <memory>
#include <mutex>
#include <optional>
#include "AS_asset_catalog.hh"
#include "DNA_asset_types.h"
#include "BLI_mutex.hh"
#include "BLI_set.hh"
#include "BLI_string_ref.hh"
#include "BLI_vector.hh"
@@ -82,7 +82,7 @@ class AssetLibrary {
* within the catalog service may still happen without the mutex being locked. They should be
* protected separately. */
std::unique_ptr<AssetCatalogService> catalog_service_;
std::mutex catalog_service_mutex_;
Mutex catalog_service_mutex_;
std::optional<eAssetImportMethod> import_method_;
/** Assets owned by this library may be imported with a different method than set in

View File

@@ -14,7 +14,6 @@
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <mutex>
#include <ft2build.h>
@@ -49,7 +48,7 @@ FontBLF *global_font[BLF_MAX_FONT] = {nullptr};
int blf_mono_font = -1;
int blf_mono_font_render = -1;
static std::mutex g_blf_load_mutex;
static blender::Mutex g_blf_load_mutex;
static FontBLF *blf_get(int fontid)
{

View File

@@ -10,13 +10,13 @@
#include <atomic>
#include <cmath>
#include <mutex>
#include "DNA_vec_types.h"
#include "BLF_api.hh"
#include "BLI_map.hh"
#include "BLI_mutex.hh"
#include "BLI_vector.hh"
#include "GPU_texture.hh"
@@ -397,5 +397,5 @@ struct FontBLF {
FontBufInfoBLF buf_info;
/** Mutex lock for glyph cache. */
std::mutex glyph_cache_mutex;
blender::Mutex glyph_cache_mutex;
};

View File

@@ -8,6 +8,7 @@
#pragma once
#include "BLI_mutex.hh"
#include "BLI_sub_frame.hh"
#include "BKE_bake_items.hh"
@@ -98,7 +99,7 @@ struct BakeNodeCache {
};
struct ModifierCache {
mutable std::mutex mutex;
mutable Mutex mutex;
/**
* Set of nested node IDs (see #bNestedNodeRef) that is expected to be baked in the next
* evaluation. This is filled and cleared by the bake operator.

View File

@@ -10,6 +10,7 @@
#include "BLI_fileops.hh"
#include "BLI_function_ref.hh"
#include "BLI_mutex.hh"
#include "BLI_serialize.hh"
#include "BKE_bake_items.hh"
@@ -141,7 +142,7 @@ class BlobReadSharing : NonCopyable, NonMovable {
/**
* Use a mutex so that #read_shared can be implemented in a thread-safe way.
*/
mutable std::mutex mutex_;
mutable Mutex mutex_;
/**
* Map used to detect when some data has been previously loaded. This keeps strong
* references to #ImplicitSharingInfo.
@@ -166,7 +167,7 @@ class BlobReadSharing : NonCopyable, NonMovable {
class DiskBlobReader : public BlobReader {
private:
const std::string blobs_dir_;
mutable std::mutex mutex_;
mutable Mutex mutex_;
mutable Map<std::string, std::unique_ptr<fstream>> open_input_streams_;
public:

View File

@@ -9,7 +9,6 @@
*/
#include <iosfwd>
#include <mutex>
#include "BLI_bounds_types.hh"
#include "BLI_function_ref.hh"
@@ -17,6 +16,7 @@
#include "BLI_map.hh"
#include "BLI_math_vector_types.hh"
#include "BLI_memory_counter_fwd.hh"
#include "BLI_mutex.hh"
/* For #Map. */
#include "BKE_attribute.hh"
@@ -605,7 +605,7 @@ class CurveComponent : public GeometryComponent {
* even when the new curve data structure is used.
*/
mutable Curve *curve_for_render_ = nullptr;
mutable std::mutex curve_for_render_mutex_;
mutable Mutex curve_for_render_mutex_;
public:
CurveComponent();

View File

@@ -9,7 +9,6 @@
*/
#include <memory>
#include <mutex>
#include <variant>
#include "BLI_array.hh"
@@ -18,6 +17,7 @@
#include "BLI_implicit_sharing.hh"
#include "BLI_kdopbvh.hh"
#include "BLI_math_vector_types.hh"
#include "BLI_mutex.hh"
#include "BLI_shared_cache.hh"
#include "BLI_vector.hh"
#include "BLI_virtual_array_fwd.hh"
@@ -136,10 +136,10 @@ struct MeshRuntime {
* threads, access and use must be protected by the #eval_mutex lock.
*/
Mesh *mesh_eval = nullptr;
std::mutex eval_mutex;
Mutex eval_mutex;
/** Needed to ensure some thread-safety during render data pre-processing. */
std::mutex render_mutex;
Mutex render_mutex;
/** Implicit sharing user count for #Mesh::face_offset_indices. */
const ImplicitSharingInfo *face_offsets_sharing_info = nullptr;

View File

@@ -9,11 +9,11 @@
#pragma once
#include <memory>
#include <mutex>
#include "BLI_cache_mutex.hh"
#include "BLI_math_vector_types.hh"
#include "BLI_multi_value_map.hh"
#include "BLI_mutex.hh"
#include "BLI_set.hh"
#include "BLI_utility_mixins.hh"
#include "BLI_vector.hh"
@@ -70,7 +70,7 @@ struct NodeLinkError {
};
struct LoggedZoneGraphs {
std::mutex mutex;
Mutex mutex;
/**
* Technically there can be more than one graph per zone because the zone can be invoked in
* different contexts. However, for the purpose of logging here, we only need one at a time
@@ -158,7 +158,7 @@ class bNodeTreeRuntime : NonCopyable, NonMovable {
* evaluate the node group. Caching it here allows us to reuse the preprocessed node tree in case
* its used multiple times.
*/
std::mutex geometry_nodes_lazy_function_graph_info_mutex;
Mutex geometry_nodes_lazy_function_graph_info_mutex;
std::unique_ptr<nodes::GeometryNodesLazyFunctionGraphInfo>
geometry_nodes_lazy_function_graph_info;

View File

@@ -13,13 +13,13 @@
#ifdef WITH_OPENVDB
# include <functional>
# include <mutex>
# include <optional>
# include "BKE_volume_enums.hh"
# include "BKE_volume_grid_type_traits.hh"
# include "BLI_implicit_sharing_ptr.hh"
# include "BLI_mutex.hh"
# include "BLI_string_ref.hh"
# include "openvdb_fwd.hh"
@@ -80,7 +80,7 @@ class VolumeGridData : public ImplicitSharingMixin {
/**
* A mutex that needs to be locked whenever working with the data members below.
*/
mutable std::mutex mutex_;
mutable Mutex mutex_;
/**
* The actual grid. Depending on the current state, is in one of multiple possible states:
* - Empty: When the grid is lazy-loaded and no meta-data is provided.

View File

@@ -16,6 +16,7 @@
#include "BLI_fileops.h"
#include "BLI_ghash.h"
#include "BLI_listbase.h"
#include "BLI_mutex.hh"
#include "BLI_path_utils.hh"
#include "BLI_string.h"
#include "BLI_utildefines.h"
@@ -46,8 +47,6 @@
# include "usd.hh"
#endif
#include <mutex>
static void cachefile_handle_free(CacheFile *cache_file);
static void cache_file_init_data(ID *id)
@@ -153,7 +152,7 @@ IDTypeInfo IDType_ID_CF = {
};
/* TODO: make this per cache file to avoid global locks. */
static std::mutex cache_mutex;
static blender::Mutex cache_mutex;
void BKE_cachefile_reader_open(CacheFile *cache_file,
CacheReader **reader,

View File

@@ -9,7 +9,6 @@
#include <cstdlib>
#include <cstring>
#include <memory>
#include <mutex>
#include "CLG_log.h"
@@ -21,6 +20,7 @@
#include "BLI_fileops.h"
#include "BLI_ghash.h"
#include "BLI_linklist_lockfree.h"
#include "BLI_mutex.hh"
#include "BLI_threads.h"
#include "BLI_utildefines.h"
@@ -55,7 +55,7 @@ static int gNextIconId = 1;
/* Protected by gIconMutex. */
static int gFirstIconId = 1;
static std::mutex gIconMutex;
static blender::Mutex gIconMutex;
/* Queue of icons for deferred deletion. */
struct DeferredIconDeleteNode {

View File

@@ -332,7 +332,7 @@ void Instances::remove_unused_references()
const Span<int> reference_handles = this->reference_handles();
Array<bool> usage_by_handle(tot_references_before, false);
std::mutex mutex;
Mutex mutex;
/* Loop over all instances to see which references are used. */
threading::parallel_for(IndexRange(tot_instances), 1000, [&](IndexRange range) {

View File

@@ -12,7 +12,6 @@
#include <cmath>
#include <cstdio>
#include <cstring>
#include <mutex>
#include "CLG_log.h"
@@ -22,6 +21,7 @@
#include "BLI_math_matrix.h"
#include "BLI_math_rotation.h"
#include "BLI_math_vector.h"
#include "BLI_mutex.hh"
#ifdef WITH_BULLET
# include "RBI_api.h"
@@ -83,7 +83,7 @@ static void RB_constraint_delete(void * /*con*/) {}
struct RigidBodyWorld_Runtime {
rbDynamicsWorld *physics_world = nullptr;
std::mutex mutex;
blender::Mutex mutex;
~RigidBodyWorld_Runtime()
{

View File

@@ -72,7 +72,6 @@ using blender::bke::GVolumeGrid;
#ifdef WITH_OPENVDB
# include <list>
# include <mutex>
# include <openvdb/openvdb.h>
# include <openvdb/points/PointDataGrid.h>
@@ -110,7 +109,7 @@ struct VolumeGridVector : public std::list<GVolumeGrid> {
/* Mutex for file loading of grids list. `const` write access to the fields after this must be
* protected by locking with this mutex. */
mutable std::mutex mutex;
mutable blender::Mutex mutex;
/* Absolute file path that grids have been loaded from. */
char filepath[FILE_MAX];
/* File loading error message. */
@@ -480,7 +479,7 @@ bool BKE_volume_load(const Volume *volume, const Main *bmain)
}
/* Double-checked lock. */
std::lock_guard<std::mutex> lock(const_grids.mutex);
std::lock_guard lock(const_grids.mutex);
if (BKE_volume_is_loaded(volume)) {
return const_grids.error_msg.empty();
}

View File

@@ -62,7 +62,7 @@ struct FileCache {
* Singleton cache that's shared throughout the application.
*/
struct GlobalCache {
std::mutex mutex;
Mutex mutex;
Map<std::string, FileCache> file_map;
};

View File

@@ -21,7 +21,7 @@
* protected data should generally be placed next to each other.
*
* Each #CacheMutex protects exactly one cache, so multiple cache mutexes have to be used when a
* class has multiple caches. That is contrary to a "custom" solution using `std::mutex` where one
* class has multiple caches. That is contrary to a "custom" solution using `Mutex` where one
* mutex could protect multiple caches at the cost of higher lock contention.
*
* To make sure the cache is up to date, call `CacheMutex::ensure` and pass in the function that
@@ -63,15 +63,15 @@
*/
#include <atomic>
#include <mutex>
#include "BLI_function_ref.hh"
#include "BLI_mutex.hh"
namespace blender {
class CacheMutex {
private:
std::mutex mutex_;
Mutex mutex_;
std::atomic<bool> cache_valid_ = false;
public:

View File

@@ -24,6 +24,7 @@
# endif
# endif
#else
# include "BLI_mutex.hh"
# include "BLI_set.hh"
#endif
@@ -163,7 +164,7 @@ class ConcurrentMap {
using UsedSet = Set<SetKey>;
struct Accessor {
std::unique_lock<std::mutex> mutex;
std::unique_lock<Mutex> mutex;
std::pair<Key, Value> *data = nullptr;
std::pair<Key, Value> *operator->()
@@ -172,7 +173,7 @@ class ConcurrentMap {
}
};
std::mutex mutex_;
Mutex mutex_;
UsedSet set_;
public:

View File

@@ -28,9 +28,9 @@
#else
# include <atomic>
# include <functional>
# include <mutex>
# include "BLI_map.hh"
# include "BLI_mutex.hh"
#endif
#include "BLI_utility_mixins.hh"
@@ -81,7 +81,7 @@ template<typename T> class EnumerableThreadSpecific : NonCopyable, NonMovable {
#else /* WITH_TBB */
private:
std::mutex mutex_;
Mutex mutex_;
/* Maps thread ids to their corresponding values. The values are not embedded in the map, so that
* their addresses do not change when the map grows. */
Map<int, std::reference_wrapper<T>> values_;

View File

@@ -0,0 +1,51 @@
/* SPDX-FileCopyrightText: 2025 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
#pragma once
/* Always include that so that `BLI_mutex.hh` can be used as replacement to including <mutex>.
* Otherwise it might be confusing if both are included explicitly in a file. That also makes the
* difference between compiling with and without TBB smaller. */
#include <mutex> // IWYU pragma: export
#ifdef WITH_TBB
# include <tbb/mutex.h>
#endif
namespace blender {
#ifdef WITH_TBB
/**
* blender::Mutex should be used as the default mutex in Blender. It implements a subset of the API
* of std::mutex but has overall better guaranteed properties. It can be used with RAII helpers
* like std::lock_guard. However, it is not compatible with e.g. std::condition_variable. So one
* still has to use std::mutex for that case.
*
* The mutex provided by TBB has these properties:
* - It's as fast as a spin-lock in the non-contended case, i.e. when no other thread is trying to
* lock the mutex at the same time.
* - In the contended case, it spins a couple of times but then blocks to avoid draining system
* resources by spinning for a long time.
* - It's only 1 byte large, compared to e.g. 40 bytes when using the std::mutex of GCC. This makes
* it more feasible to have many smaller mutexes which can improve scalability of algorithms
* compared to using fewer larger mutexes. Also it just reduces "memory slop" across Blender.
* - It is *not* a fair mutex, i.e. it's not guaranteed that a thread will ever be able to lock the
* mutex when there are always more than one threads that try to lock it. In the majority of
* cases, using a fair mutex just causes extra overhead without any benefit. std::mutex is not
* guaranteed to be fair either.
*/
using Mutex = tbb::mutex;
/* If this is not true anymore at some point, the comment above needs to be updated. */
static_assert(sizeof(Mutex) == 1);
#else
/** Use std::mutex as a fallback when compiling without TBB. */
using Mutex = std::mutex;
#endif
} // namespace blender

View File

@@ -337,6 +337,7 @@ set(SRC
BLI_mesh_intersect.hh
BLI_mmap.h
BLI_multi_value_map.hh
BLI_mutex.hh
BLI_noise.h
BLI_noise.hh
BLI_offset_indices.hh

View File

@@ -7,12 +7,12 @@
*/
#include <atomic>
#include <mutex>
#include <optional>
#include "BLI_concurrent_map.hh"
#include "BLI_memory_cache.hh"
#include "BLI_memory_counter.hh"
#include "BLI_mutex.hh"
namespace blender::memory_cache {
@@ -43,7 +43,7 @@ struct Cache {
*/
std::atomic<int64_t> size_in_bytes = 0;
std::mutex global_mutex;
Mutex global_mutex;
/** Amount of memory currently used in the cache. */
MemoryCount memory;
/**

View File

@@ -14,7 +14,6 @@
# include <functional>
# include <iostream>
# include <memory>
# include <mutex>
# include <numeric>
# include "BLI_array.hh"
@@ -28,6 +27,7 @@
# include "BLI_math_vector.h"
# include "BLI_math_vector_mpq_types.hh"
# include "BLI_math_vector_types.hh"
# include "BLI_mutex.hh"
# include "BLI_polyfill_2d.h"
# include "BLI_set.hh"
# include "BLI_sort.hh"
@@ -329,7 +329,7 @@ class IMeshArena::IMeshArenaImpl : NonCopyable, NonMovable {
int next_face_id_ = 0;
/* Need a lock when multi-threading to protect allocation of new elements. */
std::mutex mutex_;
Mutex mutex_;
public:
void reserve(int vert_num_hint, int face_num_hint)

View File

@@ -16,13 +16,13 @@
#include <cstdlib>
#include <functional>
#include <mutex>
#include "MEM_guardedalloc.h"
#include "DNA_ID.h" /* for ID_Type and INDEX_ID_MAX */
#include "BLI_linear_allocator.hh"
#include "BLI_mutex.hh"
#include "BLI_set.hh"
#include "BLI_threads.h" /* for SpinLock */
@@ -193,7 +193,7 @@ struct Depsgraph {
*/
Vector<std::function<void()>> sync_writeback_callbacks;
/** Needs to be locked when adding a writeback callback during evaluation. */
std::mutex sync_writeback_callbacks_mutex;
Mutex sync_writeback_callbacks_mutex;
MEM_CXX_CLASS_ALLOC_FUNCS("Depsgraph");
};

View File

@@ -6,9 +6,8 @@
* \ingroup depsgraph
*/
#include <mutex>
#include "BLI_map.hh"
#include "BLI_mutex.hh"
#include "BLI_vector_set.hh"
#include "intern/depsgraph_registry.hh"
@@ -27,7 +26,7 @@ namespace blender::deg {
using GraphSetPtr = std::unique_ptr<VectorSet<Depsgraph *>>;
struct GraphRegistry {
Map<Main *, GraphSetPtr> map;
std::mutex mutex;
Mutex mutex;
};
static GraphRegistry &get_graph_registry()
@@ -41,7 +40,7 @@ void register_graph(Depsgraph *depsgraph)
GraphRegistry &graph_registry = get_graph_registry();
Main *bmain = depsgraph->bmain;
std::lock_guard<std::mutex> lock{graph_registry.mutex};
std::lock_guard lock{graph_registry.mutex};
graph_registry.map
.lookup_or_add_cb(bmain, []() { return std::make_unique<VectorSet<Depsgraph *>>(); })
->add_new(depsgraph);
@@ -52,7 +51,7 @@ void unregister_graph(Depsgraph *depsgraph)
Main *bmain = depsgraph->bmain;
GraphRegistry &graph_registry = get_graph_registry();
std::lock_guard<std::mutex> lock{graph_registry.mutex};
std::lock_guard lock{graph_registry.mutex};
GraphSetPtr &graphs = graph_registry.map.lookup(bmain);
graphs->remove(depsgraph);
@@ -65,7 +64,7 @@ void unregister_graph(Depsgraph *depsgraph)
Span<Depsgraph *> get_all_registered_graphs(Main *bmain)
{
GraphRegistry &graph_registry = get_graph_registry();
std::lock_guard<std::mutex> lock{graph_registry.mutex};
std::lock_guard lock{graph_registry.mutex};
GraphSetPtr *graphs = graph_registry.map.lookup_ptr(bmain);
if (graphs) {
return **graphs;

View File

@@ -8,8 +8,6 @@
* Contains everything about light baking.
*/
#include <mutex>
#include "DRW_engine.hh"
#include "DRW_render.hh"
@@ -18,6 +16,7 @@
#include "DNA_lightprobe_types.h"
#include "BLI_mutex.hh"
#include "BLI_threads.h"
#include "BLI_time.h"
@@ -74,7 +73,7 @@ class LightBake {
Vector<Object *> original_probes_;
/** Frame to copy to original objects during update. This is needed to avoid race conditions. */
Vector<LightProbeGridCacheFrame *> bake_result_;
std::mutex result_mutex_;
Mutex result_mutex_;
public:
LightBake(Main *bmain,

View File

@@ -14,7 +14,9 @@
#include <array>
#include <string>
#include "BLI_mutex.hh"
#include "BLI_string_ref.hh"
#include "DRW_render.hh"
#include "GPU_material.hh"
#include "GPU_shader.hh"
@@ -170,7 +172,7 @@ class ShaderModule {
private:
std::array<StaticShader, MAX_SHADER_TYPE> shaders_;
BatchHandle compilation_handle_ = 0;
std::mutex mutex_;
Mutex mutex_;
class SpecializationsKey {
private:

View File

@@ -48,7 +48,7 @@ void drw_attributes_clear(DRW_Attributes *attributes)
*attributes = {};
}
void drw_attributes_merge(DRW_Attributes *dst, const DRW_Attributes *src, std::mutex &render_mutex)
void drw_attributes_merge(DRW_Attributes *dst, const DRW_Attributes *src, Mutex &render_mutex)
{
if (src->num_requests == 0) {
return;

View File

@@ -10,10 +10,9 @@
#pragma once
#include <mutex>
#include "DNA_customdata_types.h"
#include "BLI_mutex.hh"
#include "BLI_sys_types.h"
#include "GPU_shader.hh"
@@ -55,9 +54,7 @@ static_assert(sizeof(DRW_MeshCDMask) <= sizeof(uint32_t), "DRW_MeshCDMask exceed
void drw_attributes_clear(DRW_Attributes *attributes);
void drw_attributes_merge(DRW_Attributes *dst,
const DRW_Attributes *src,
std::mutex &render_mutex);
void drw_attributes_merge(DRW_Attributes *dst, const DRW_Attributes *src, Mutex &render_mutex);
/* Return true if all requests in b are in a. */
bool drw_attributes_overlap(const DRW_Attributes *a, const DRW_Attributes *b);

View File

@@ -100,7 +100,7 @@ struct CurvesBatchCache {
* some locking would be necessary because multiple objects can use the same curves data with
* different materials, etc. This is a placeholder to make multi-threading easier in the future.
*/
std::mutex render_mutex;
Mutex render_mutex;
};
static bool batch_cache_is_dirty(const Curves &curves)

View File

@@ -90,7 +90,7 @@ struct PointCloudBatchCache {
* some locking would be necessary because multiple objects can use the same object data with
* different materials, etc. This is a placeholder to make multi-threading easier in the future.
*/
std::mutex render_mutex;
Mutex render_mutex;
};
static PointCloudBatchCache *pointcloud_batch_cache_get(PointCloud &pointcloud)

View File

@@ -1580,7 +1580,7 @@ static void draw_subdiv_cache_ensure_mat_offsets(DRWSubdivCache &cache,
static OpenSubdiv_EvaluatorCache *g_subdiv_evaluator_cache = nullptr;
static uint64_t g_subdiv_evaluator_users = 0;
/* The evaluator cache is global, so we cannot allow concurrent usage and need synchronization. */
static std::mutex g_subdiv_eval_mutex;
static Mutex g_subdiv_eval_mutex;
static bool draw_subdiv_create_requested_buffers(Object &ob,
Mesh &mesh,

View File

@@ -16,6 +16,7 @@
#pragma once
#include "BLI_math_vector_types.hh"
#include "BLI_mutex.hh"
#include "DNA_object_types.h"
@@ -93,7 +94,7 @@ class DebugDraw {
/* Reference counter used by GPUContext to allow freeing of DebugDrawBuf before the last
* context is destroyed. */
int ref_count_ = 0;
std::mutex ref_count_mutex_;
Mutex ref_count_mutex_;
public:
void reset();

View File

@@ -2407,7 +2407,7 @@ static struct Clipboard {
} *grease_pencil_clipboard = nullptr;
/** The clone brush accesses the clipboard from multiple threads. Protect from parallel access. */
std::mutex grease_pencil_clipboard_lock;
blender::Mutex grease_pencil_clipboard_lock;
static Clipboard &ensure_grease_pencil_clipboard()
{

View File

@@ -9,7 +9,6 @@
#include <condition_variable>
#include <cstddef>
#include <cstring>
#include <mutex>
#include "MEM_guardedalloc.h"
@@ -17,6 +16,7 @@
#include "BLI_fileops.h"
#include "BLI_listbase.h"
#include "BLI_math_color_blend.h"
#include "BLI_mutex.hh"
#include "BLI_string.h"
#include "BLI_task.h"
#include "BLI_task.hh"
@@ -113,7 +113,7 @@ struct OGLRender : public RenderJobBase {
GPUViewport *viewport = nullptr;
std::mutex reports_mutex;
blender::Mutex reports_mutex;
ReportList *reports = nullptr;
int cfrao = 0;

View File

@@ -238,7 +238,7 @@ struct StepData {
bool applied;
std::mutex nodes_mutex;
Mutex nodes_mutex;
/**
* #undo::Node is stored per #pbvh::Node to reduce data storage needed for changes only impacting

View File

@@ -9,7 +9,6 @@
#include <cerrno>
#include <cstddef>
#include <fcntl.h>
#include <mutex>
#include <sys/types.h>
#ifndef WIN32
@@ -25,6 +24,7 @@
#include "BLI_fileops.h"
#include "BLI_listbase.h"
#include "BLI_mutex.hh"
#include "BLI_rect.h"
#include "BLI_task.h"
#include "BLI_utildefines.h"
@@ -682,7 +682,7 @@ struct PrefetchQueue {
*/
bool forward;
std::mutex mutex;
blender::Mutex mutex;
bool *stop;
bool *do_update;

View File

@@ -55,7 +55,7 @@ class GeometryDataSource : public DataSource {
/* Some data is computed on the fly only when it is requested. Computing it does not change the
* logical state of this data source. Therefore, the corresponding methods are const and need to
* be protected with a mutex. */
mutable std::mutex mutex_;
mutable Mutex mutex_;
mutable ResourceScope scope_;
public:

View File

@@ -42,10 +42,10 @@
*/
#include <atomic>
#include <mutex>
#include "BLI_enumerable_thread_specific.hh"
#include "BLI_function_ref.hh"
#include "BLI_mutex.hh"
#include "BLI_stack.hh"
#include "BLI_task.h"
#include "BLI_task.hh"
@@ -130,11 +130,6 @@ struct OutputState {
};
struct NodeState {
/**
* Needs to be locked when any data in this state is accessed that is not explicitly marked as
* not needing the lock.
*/
mutable std::mutex mutex;
/**
* States of the individual input and output sockets. One can index into these arrays without
* locking. However, to access data inside, a lock is needed unless noted otherwise.
@@ -149,6 +144,11 @@ struct NodeState {
* cases.
*/
int missing_required_inputs = 0;
/**
* Needs to be locked when any data in this state is accessed that is not explicitly marked as
* not needing the lock.
*/
mutable Mutex mutex;
/**
* Is set to true once the node is done with its work, i.e. when all outputs that may be used
* have been computed.
@@ -274,7 +274,7 @@ struct CurrentTask {
/**
* Mutex used to protect #scheduled_nodes when the executor uses multi-threading.
*/
std::mutex mutex;
Mutex mutex;
/**
* Nodes that have been scheduled to execute next.
*/

View File

@@ -53,7 +53,7 @@ using namespace blender::gpu;
static thread_local Context *active_ctx = nullptr;
static std::mutex backend_users_mutex;
static blender::Mutex backend_users_mutex;
static int num_backend_users = 0;
static void gpu_backend_create();
@@ -271,7 +271,7 @@ void GPU_context_end_frame(GPUContext *ctx)
* Used to avoid crash on some old drivers.
* \{ */
static std::mutex main_context_mutex;
static blender::Mutex main_context_mutex;
void GPU_context_main_lock()
{

View File

@@ -3,7 +3,9 @@
* SPDX-License-Identifier: GPL-2.0-or-later */
#include "BLI_map.hh"
#include "BLI_mutex.hh"
#include "BLI_string_ref.hh"
#include <fmt/format.h>
#include <fstream>
#include <iostream>
@@ -16,7 +18,7 @@ namespace blender::gpu {
class ProfileReport {
private:
std::fstream _report;
std::mutex _mutex;
Mutex _mutex;
Map<size_t, int> _thread_ids;
ProfileReport()

View File

@@ -12,6 +12,7 @@
# include <cstdint>
# include <mutex>
# include "BLI_mutex.hh"
# include "BLI_threads.h"
# include "BLI_vector.hh"
@@ -39,7 +40,7 @@ struct SwscaleContext {
bool is_used = false;
};
static std::mutex swscale_cache_lock;
static blender::Mutex swscale_cache_lock;
static int64_t swscale_cache_timestamp = 0;
static blender::Vector<SwscaleContext> *swscale_cache = nullptr;

View File

@@ -950,7 +950,7 @@ static void check_property_socket_sync(const Object *ob,
class NodesModifierBakeDataBlockMap : public bake::BakeDataBlockMap {
/** Protects access to `new_mappings` which may be added to from multiple threads. */
std::mutex mutex_;
Mutex mutex_;
public:
Map<bake::BakeDataBlockID, ID *> old_mappings;

View File

@@ -5,9 +5,9 @@
#pragma once
#include <cstdint>
#include <mutex>
#include "BLI_compute_context.hh"
#include "BLI_mutex.hh"
#include "BLI_vector.hh"
struct bNodeTree;
@@ -32,7 +32,7 @@ struct ClosureSourceLocation {
};
struct ClosureEvalLog {
std::mutex mutex;
Mutex mutex;
Vector<ClosureEvalLocation> evaluations;
};

View File

@@ -186,7 +186,7 @@ static bake::BakeSocketConfig make_bake_socket_config(const Span<NodeGeometryBak
*/
struct DummyDataBlockMap : public bake::BakeDataBlockMap {
private:
std::mutex mutex_;
Mutex mutex_;
Map<bake::BakeDataBlockID, ID *> map_;
public:

View File

@@ -64,7 +64,7 @@ static void node_geo_exec(GeoNodeExecParams params)
wildcard_suffix = StringRef(pattern).substr(wildcard_index + 1);
}
std::mutex attribute_log_mutex;
Mutex attribute_log_mutex;
Set<std::string> removed_attributes;
Set<std::string> failed_attributes;

View File

@@ -1738,7 +1738,7 @@ class GeometryNodesLazyFunctionLogger : public lf::GraphExecutor::Logger {
}
}
static inline std::mutex dump_error_context_mutex;
static inline Mutex dump_error_context_mutex;
void dump_when_outputs_are_missing(const lf::FunctionNode &node,
Span<const lf::OutputSocket *> missing_sockets,

View File

@@ -12,10 +12,9 @@
/* exposed internal in render module only! */
/* ------------------------------------------------------------------------- */
#include <mutex>
#include "DNA_scene_types.h"
#include "BLI_mutex.hh"
#include "BLI_threads.h"
#include "RE_compositor.hh"
@@ -216,7 +215,7 @@ struct Render : public BaseRender {
/* Compositor.
* NOTE: Use bare pointer instead of smart pointer because the it is a fully opaque type. */
blender::render::Compositor *compositor = nullptr;
std::mutex compositor_mutex;
blender::Mutex compositor_mutex;
/* Callbacks for the corresponding base class method implementation. */
void (*display_init_cb)(void *handle, RenderResult *rr) = nullptr;

View File

@@ -10,11 +10,10 @@
#include "DNA_vec_types.h"
#include "BLI_mutex.hh"
#include "BLI_set.hh"
#include "BLI_vector.hh"
#include <mutex>
struct RenderResult;
namespace blender::render {
@@ -57,7 +56,7 @@ class TilesHighlight {
void highlight_tile(const Tile &tile);
void unhighlight_tile(const Tile &tile);
mutable std::mutex mutex_;
mutable Mutex mutex_;
Set<Tile> highlighted_tiles_set_;
/* Cached flat list of currently highlighted tiles for a fast access via API. */

View File

@@ -15,16 +15,16 @@
#include "BLI_listbase.h"
#include "BLI_map.hh"
#include "BLI_mutex.hh"
#include "BLI_vector_set.hh"
#include <cstring>
#include <mutex>
#include "MEM_guardedalloc.h"
namespace blender::seq {
static std::mutex lookup_lock;
static Mutex lookup_lock;
struct StripLookup {
blender::Map<std::string, Strip *> strip_by_name;

View File

@@ -8,6 +8,7 @@
#include "BLI_map.hh"
#include "BLI_math_base.h"
#include "BLI_mutex.hh"
#include "BLI_path_utils.hh"
#include "BLI_set.hh"
#include "BLI_task.hh"
@@ -38,7 +39,7 @@ static constexpr int MAX_THUMBNAILS = 5000;
// #define DEBUG_PRINT_THUMB_JOB_TIMES
static std::mutex thumb_cache_mutex;
static Mutex thumb_cache_mutex;
/* Thumbnail cache is a map keyed by media file path, with values being
* the various thumbnails that are loaded for it (mostly images would contain just