Changeset View
Changeset View
Standalone View
Standalone View
source/blender/blenkernel/intern/node_ui_storage.cc
| Show All 10 Lines | |||||
| * | * | ||||
| * You should have received a copy of the GNU General Public License | * You should have received a copy of the GNU General Public License | ||||
| * along with this program; if not, write to the Free Software Foundation, | * along with this program; if not, write to the Free Software Foundation, | ||||
| * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||||
| */ | */ | ||||
| #include "CLG_log.h" | #include "CLG_log.h" | ||||
| #include <mutex> | |||||
| #include "BLI_map.hh" | #include "BLI_map.hh" | ||||
| #include "BLI_string_ref.hh" | #include "BLI_string_ref.hh" | ||||
| #include "BLI_vector.hh" | #include "BLI_vector.hh" | ||||
| #include "DNA_node_types.h" | #include "DNA_node_types.h" | ||||
| #include "DNA_object_types.h" | #include "DNA_object_types.h" | ||||
| #include "BKE_context.h" | #include "BKE_context.h" | ||||
| #include "BKE_node_ui_storage.hh" | #include "BKE_node_ui_storage.hh" | ||||
| #include "BKE_object.h" | #include "BKE_object.h" | ||||
| static CLG_LogRef LOG = {"bke.node_ui_storage"}; | static CLG_LogRef LOG = {"bke.node_ui_storage"}; | ||||
| using blender::Map; | using blender::Map; | ||||
| using blender::StringRef; | using blender::StringRef; | ||||
| using blender::Vector; | using blender::Vector; | ||||
| /* Use a global mutex because otherwise it would have to be stored directly in the | |||||
| * bNodeTree struct in DNA. This could change if the node tree had a runtime struct. */ | |||||
| static std::mutex global_ui_storage_mutex; | |||||
| static void ui_storage_ensure(bNodeTree &ntree) | static void ui_storage_ensure(bNodeTree &ntree) | ||||
| { | { | ||||
| /* As an optimization, only acquire a lock if the UI storage doesn't exist, | |||||
JacquesLucke: This works, but a double checked locking should work here and reduces threading overhead. | |||||
| * because it only needs to be allocated once for every node tree. */ | |||||
| if (ntree.ui_storage == nullptr) { | |||||
| std::lock_guard<std::mutex> lock(global_ui_storage_mutex); | |||||
| /* Check again-- another thread may have allocated the storage while this one waited. */ | |||||
| if (ntree.ui_storage == nullptr) { | if (ntree.ui_storage == nullptr) { | ||||
| ntree.ui_storage = new NodeTreeUIStorage(); | ntree.ui_storage = new NodeTreeUIStorage(); | ||||
| } | } | ||||
| } | } | ||||
| } | |||||
| const NodeUIStorage *BKE_node_tree_ui_storage_get_from_context(const bContext *C, | const NodeUIStorage *BKE_node_tree_ui_storage_get_from_context(const bContext *C, | ||||
| const bNodeTree &ntree, | const bNodeTree &ntree, | ||||
| const bNode &node) | const bNode &node) | ||||
| { | { | ||||
| const NodeTreeUIStorage *ui_storage = ntree.ui_storage; | const NodeTreeUIStorage *ui_storage = ntree.ui_storage; | ||||
| if (ui_storage == nullptr) { | if (ui_storage == nullptr) { | ||||
| return nullptr; | return nullptr; | ||||
| Show All 17 Lines | |||||
| /** | /** | ||||
| * Removes only the UI data associated with a particular evaluation context. The same node tree | * Removes only the UI data associated with a particular evaluation context. The same node tree | ||||
| * can be used for execution in multiple places, but the entire UI storage can't be removed when | * can be used for execution in multiple places, but the entire UI storage can't be removed when | ||||
| * one execution starts, or all of the data associated with the node tree would be lost. | * one execution starts, or all of the data associated with the node tree would be lost. | ||||
| */ | */ | ||||
| void BKE_nodetree_ui_storage_free_for_context(bNodeTree &ntree, | void BKE_nodetree_ui_storage_free_for_context(bNodeTree &ntree, | ||||
| const NodeTreeEvaluationContext &context) | const NodeTreeEvaluationContext &context) | ||||
| { | { | ||||
| NodeTreeUIStorage *ui_storage = ntree.ui_storage; | NodeTreeUIStorage *ui_storage = ntree.ui_storage; | ||||
Not Done Inline ActionsThis lock does not seem necessary. JacquesLucke: This lock does not seem necessary. | |||||
| if (ui_storage != nullptr) { | if (ui_storage != nullptr) { | ||||
| std::lock_guard<std::mutex> lock(ui_storage->context_map_mutex); | |||||
| ui_storage->context_map.remove(context); | ui_storage->context_map.remove(context); | ||||
| } | } | ||||
| } | } | ||||
| static void node_error_message_log(bNodeTree &ntree, | static void node_error_message_log(bNodeTree &ntree, | ||||
| const bNode &node, | const bNode &node, | ||||
| const StringRef message, | const StringRef message, | ||||
| const NodeWarningType type) | const NodeWarningType type) | ||||
| Show All 26 Lines | |||||
| static NodeUIStorage &node_ui_storage_ensure(bNodeTree &ntree, | static NodeUIStorage &node_ui_storage_ensure(bNodeTree &ntree, | ||||
| const NodeTreeEvaluationContext &context, | const NodeTreeEvaluationContext &context, | ||||
| const bNode &node) | const bNode &node) | ||||
| { | { | ||||
| ui_storage_ensure(ntree); | ui_storage_ensure(ntree); | ||||
| NodeTreeUIStorage &ui_storage = *ntree.ui_storage; | NodeTreeUIStorage &ui_storage = *ntree.ui_storage; | ||||
| std::lock_guard<std::mutex> lock(ui_storage.context_map_mutex); | |||||
| Map<std::string, NodeUIStorage> &node_tree_ui_storage = | Map<std::string, NodeUIStorage> &node_tree_ui_storage = | ||||
| ui_storage.context_map.lookup_or_add_default(context); | ui_storage.context_map.lookup_or_add_default(context); | ||||
| NodeUIStorage &node_ui_storage = node_tree_ui_storage.lookup_or_add_default_as( | NodeUIStorage &node_ui_storage = node_tree_ui_storage.lookup_or_add_default_as( | ||||
| StringRef(node.name)); | StringRef(node.name)); | ||||
| return node_ui_storage; | return node_ui_storage; | ||||
| } | } | ||||
| Show All 21 Lines | |||||
This works, but a double checked locking should work here and reduces threading overhead.