[consider merging] Enabling Shapes-based RecursiveShapeIterators for MT-use

This fixes a crash when using DRC fill in tiled mode with multiple
threads.
This commit is contained in:
Matthias Koefferlein 2025-07-12 13:58:47 +02:00
parent 54a4564a52
commit 76f7c620f6
3 changed files with 18 additions and 1 deletions

View File

@ -280,7 +280,8 @@ fill_polygon_impl (db::Cell *cell, const db::Polygon &fp0, db::cell_index_type f
{ {
// In case we run this from a tiling processor we need to lock against multithread races // In case we run this from a tiling processor we need to lock against multithread races
tl::MutexLocker locker (&db::TilingProcessor::output_lock ()); tl_assert (cell->layout () != 0);
tl::MutexLocker locker (&cell->layout ()->lock ());
cell->insert (array); cell->insert (array);
} }

View File

@ -500,15 +500,21 @@ RecursiveShapeIterator::validate (RecursiveShapeReceiver *receiver) const
} }
if (mp_shapes) { if (mp_shapes) {
// Ensures the trees are built properly - this is important in MT contexts (i.e. TilingProcessor) // Ensures the trees are built properly - this is important in MT contexts (i.e. TilingProcessor)
// TODO: get rid of that const cast // TODO: get rid of that const cast
(const_cast <db::Shapes *> (mp_shapes))->update (); (const_cast <db::Shapes *> (mp_shapes))->update ();
start_shapes (); start_shapes ();
} else if (mp_layout && (! m_has_layers || m_current_layer < m_layers.size ())) { } else if (mp_layout && (! m_has_layers || m_current_layer < m_layers.size ())) {
// Ensures the trees are built properly - this is important in MT contexts (i.e. TilingProcessor) // Ensures the trees are built properly - this is important in MT contexts (i.e. TilingProcessor)
mp_layout->update (); mp_layout->update ();
new_cell (receiver); new_cell (receiver);
next_shape (receiver); next_shape (receiver);
} }
if (mp_layout && ! at_end ()) { if (mp_layout && ! at_end ()) {

View File

@ -1127,10 +1127,20 @@ void Shapes::reset_bbox_dirty ()
void Shapes::update () void Shapes::update ()
{ {
std::unique_ptr<tl::MutexLocker> locker;
// If not in a layout context, we should lock here against multiple calls from different threads.
// In a layout context, the Layout object will do that for us.
if (layout () == 0) {
static tl::Mutex lock;
locker.reset (new tl::MutexLocker (&lock));
}
for (tl::vector<LayerBase *>::const_iterator l = m_layers.begin (); l != m_layers.end (); ++l) { for (tl::vector<LayerBase *>::const_iterator l = m_layers.begin (); l != m_layers.end (); ++l) {
(*l)->sort (); (*l)->sort ();
(*l)->update_bbox (); (*l)->update_bbox ();
} }
set_dirty (false); set_dirty (false);
} }