diff options
author | Remco Burema <r.burema@ultimaker.com> | 2022-04-20 22:01:40 +0300 |
---|---|---|
committer | Remco Burema <r.burema@ultimaker.com> | 2022-04-20 22:01:40 +0300 |
commit | 615896c97c8a90fff444d0767937ae03bd5e8fd1 (patch) | |
tree | 38ae6f8a43a8782d8d50f9710ca0b044de9dc2ca | |
parent | f2a3b6fe97b1008640214c8688d17300a40c0618 (diff) |
Alternate fix for crashes/deadlocks Tree-Support.
Other fix could still crash and deadlock. Could have probably made it work, but the critical section using 'volumes_' within the scope of the parallel for can be very small, since the access to the tree envelope cash ('volumes_') occurs twice in quick succession. Much easier to make it its own little critical section and not worry about making that entire class thread-safe. That takes care of the crash. During investigation it was found that, since it had multiple critical sections in the loop, handled by the same mutex, _and_ a seprate atomic that was then accessed _inside_ one of the critical sections (what was I thinking...) it could deadlock or at the very least report the wrong progress (causing that part of the front-end to hang). Fixed that as well.
part of CURA-9159
-rw-r--r-- | src/TreeSupport.cpp | 22 |
1 files changed, 11 insertions, 11 deletions
diff --git a/src/TreeSupport.cpp b/src/TreeSupport.cpp index 6edfa7f29..b9ac0421b 100644 --- a/src/TreeSupport.cpp +++ b/src/TreeSupport.cpp @@ -99,8 +99,9 @@ void TreeSupport::drawCircles(SliceDataStorage& storage, const std::vector<std:: const size_t tip_layers = (branch_radius - minimum_tip_radius) / layer_height; //The number of layers to be shrinking the circle to create a tip. This produces a 45 degree angle. const coord_t resolution = mesh_group_settings.get<coord_t>("support_tree_collision_resolution"); - std::atomic<size_t> completed = 0; //To track progress in a multi-threaded environment. - std::mutex critical_sections; + size_t completed = 0; //To track progress, should be locked when altered. + std::mutex critical_section_volumes; + std::mutex critical_section_progress; cura::parallel_for<size_t>(0, contact_nodes.size(), 1, [&](const size_t layer_nr) { Polygons support_layer; @@ -142,8 +143,12 @@ void TreeSupport::drawCircles(SliceDataStorage& storage, const std::vector<std:: support_layer = support_layer.unionPolygons(); roof_layer = roof_layer.unionPolygons(); const size_t z_collision_layer = static_cast<size_t>(std::max(0, static_cast<int>(layer_nr) - static_cast<int>(z_distance_bottom_layers) + 1)); //Layer to test against to create a Z-distance. - support_layer = support_layer.difference(volumes_.getCollision(0, z_collision_layer)); //Subtract the model itself (sample 0 is with 0 diameter but proper X/Y offset). - roof_layer = roof_layer.difference(volumes_.getCollision(0, z_collision_layer)); + { + const std::lock_guard<std::mutex> lock(critical_section_volumes); + + support_layer = support_layer.difference(volumes_.getCollision(0, z_collision_layer)); //Subtract the model itself (sample 0 is with 0 diameter but proper X/Y offset). + roof_layer = roof_layer.difference(volumes_.getCollision(0, z_collision_layer)); + } support_layer = support_layer.difference(roof_layer); //We smooth this support as much as possible without altering single circles. So we remove any line less than the side length of those circles. const double diameter_angle_scale_factor_this_layer = static_cast<double>(storage.support.supportLayers.size() - layer_nr - tip_layers) * diameter_angle_scale_factor; //Maximum scale factor. @@ -181,19 +186,14 @@ void TreeSupport::drawCircles(SliceDataStorage& storage, const std::vector<std:: } { - std::lock_guard<std::mutex> critical_section_support_max_layer_nr(critical_sections); + const std::lock_guard<std::mutex> lock(critical_section_progress); if (!storage.support.supportLayers[layer_nr].support_infill_parts.empty() || !storage.support.supportLayers[layer_nr].support_roof.empty()) { storage.support.layer_nr_max_filled_layer = std::max(storage.support.layer_nr_max_filled_layer, static_cast<int>(layer_nr)); } - } - - ++completed; - - { - std::lock_guard<std::mutex> critical_section_progress(critical_sections); + ++completed; const double progress_contact_nodes = contact_nodes.size() * PROGRESS_WEIGHT_DROPDOWN; const double progress_current = completed * PROGRESS_WEIGHT_AREAS; const double progress_total = completed * PROGRESS_WEIGHT_AREAS; |