@@ -223,213 +223,305 @@ static db::Shape insert_shape_with_dcplx_trans (db::Shapes *s, const db::Shape &
223223 return s->insert (shape, dbu_trans.inverted () * trans * dbu_trans, pm);
224224}
225225
226+ namespace {
227+
228+ /* *
229+ * @brief Provides protection against inserting shapes into a target that is also source
230+ *
231+ * The strategy is to use an temporary Shapes container if needed.
232+ */
233+ class ProtectedShapes
234+ {
235+ public:
236+ ProtectedShapes (db::Shapes *target, const db::RecursiveShapeIterator &src)
237+ : mp_target (target), mp_tmp_shapes ()
238+ {
239+ if (target == src.shapes () || target->layout () == src.layout ()) {
240+ mp_tmp_shapes.reset (new db::Shapes ());
241+ }
242+ }
243+
244+ ProtectedShapes (db::Shapes *target, const db::Shapes &src)
245+ : mp_target (target), mp_tmp_shapes ()
246+ {
247+ if (target == &src || target->layout () == src.layout ()) {
248+ mp_tmp_shapes.reset (new db::Shapes ());
249+ }
250+ }
251+
252+ ProtectedShapes (db::Shapes *target, const db::Region &src)
253+ : mp_target (target), mp_tmp_shapes ()
254+ {
255+ auto iter = src.begin_iter ();
256+ if (target == iter.first .shapes () || target->layout () == iter.first .layout ()) {
257+ mp_tmp_shapes.reset (new db::Shapes ());
258+ }
259+ }
260+
261+ ProtectedShapes (db::Shapes *target, const db::Texts &src)
262+ : mp_target (target), mp_tmp_shapes ()
263+ {
264+ auto iter = src.begin_iter ();
265+ if (target == iter.first .shapes () || target->layout () == iter.first .layout ()) {
266+ mp_tmp_shapes.reset (new db::Shapes ());
267+ }
268+ }
269+
270+ ProtectedShapes (db::Shapes *target, const db::Edges &src)
271+ : mp_target (target), mp_tmp_shapes ()
272+ {
273+ auto iter = src.begin_iter ();
274+ if (target == iter.first .shapes () || target->layout () == iter.first .layout ()) {
275+ mp_tmp_shapes.reset (new db::Shapes ());
276+ }
277+ }
278+
279+ ProtectedShapes (db::Shapes *target, const db::EdgePairs &src)
280+ : mp_target (target), mp_tmp_shapes ()
281+ {
282+ auto iter = src.begin_iter ();
283+ if (target == iter.first .shapes () || target->layout () == iter.first .layout ()) {
284+ mp_tmp_shapes.reset (new db::Shapes ());
285+ }
286+ }
287+
288+ ~ProtectedShapes ()
289+ {
290+ if (mp_tmp_shapes.get ()) {
291+ mp_target->insert (*mp_tmp_shapes.get ());
292+ }
293+ }
294+
295+ db::Shapes *operator -> () const
296+ {
297+ if (mp_tmp_shapes.get ()) {
298+ return mp_tmp_shapes.get ();
299+ } else {
300+ return mp_target;
301+ }
302+ }
303+
304+ private:
305+ db::Shapes *mp_target;
306+ std::unique_ptr<db::Shapes> mp_tmp_shapes;
307+ };
308+
309+ }
310+
226311static void insert_iter (db::Shapes *sh, const db::RecursiveShapeIterator &r)
227312{
228- // NOTE: if the source (r) is from the same layout than the shapes live in, we better
229- // lock the layout against updates while inserting
230- db::LayoutLocker locker (sh->layout ());
313+ ProtectedShapes ps (sh, r);
231314 for (db::RecursiveShapeIterator i = r; !i.at_end (); ++i) {
232315 tl::ident_map<db::properties_id_type> pm;
233- sh ->insert (*i, i.trans (), pm);
316+ ps ->insert (*i, i.trans (), pm);
234317 }
235318}
236319
237320static void insert_iter_with_trans (db::Shapes *sh, const db::RecursiveShapeIterator &r, const db::ICplxTrans &trans)
238321{
239- // NOTE: if the source (r) is from the same layout than the shapes live in, we better
240- // lock the layout against updates while inserting
241- db::LayoutLocker locker (sh->layout ());
322+ ProtectedShapes ps (sh, r);
242323 for (db::RecursiveShapeIterator i = r; !i.at_end (); ++i) {
243324 tl::ident_map<db::properties_id_type> pm;
244- sh ->insert (*i, trans * i.trans (), pm);
325+ ps ->insert (*i, trans * i.trans (), pm);
245326 }
246327}
247328
248329static void insert_shapes (db::Shapes *sh, const db::Shapes &s)
249330{
250- sh->insert (s);
331+ ProtectedShapes ps (sh, s);
332+ ps->insert (s);
251333}
252334
253335static void insert_shapes_with_flags (db::Shapes *sh, const db::Shapes &s, unsigned int flags)
254336{
255- sh->insert (s, flags);
337+ ProtectedShapes ps (sh, s);
338+ ps->insert (s, flags);
256339}
257340
258341static void insert_shapes_with_trans (db::Shapes *sh, const db::Shapes &s, const db::ICplxTrans &trans)
259342{
260- // NOTE: if the source (r) is from the same layout than the shapes live in, we better
261- // lock the layout against updates while inserting
262- db::LayoutLocker locker (sh->layout ());
343+ ProtectedShapes ps (sh, s);
263344 for (db::Shapes::shape_iterator i = s.begin (db::ShapeIterator::All); !i.at_end (); ++i) {
264345 tl::ident_map<db::properties_id_type> pm;
265- sh ->insert (*i, trans, pm);
346+ ps ->insert (*i, trans, pm);
266347 }
267348}
268349
269350static void insert_shapes_with_flag_and_trans (db::Shapes *sh, const db::Shapes &s, unsigned int flags, const db::ICplxTrans &trans)
270351{
271- // NOTE: if the source (r) is from the same layout than the shapes live in, we better
272- // lock the layout against updates while inserting
273- db::LayoutLocker locker (sh->layout ());
352+ ProtectedShapes ps (sh, s);
274353 for (db::Shapes::shape_iterator i = s.begin (flags); !i.at_end (); ++i) {
275354 tl::ident_map<db::properties_id_type> pm;
276- sh ->insert (*i, trans, pm);
355+ ps ->insert (*i, trans, pm);
277356 }
278357}
279358
280359static void insert_region (db::Shapes *sh, const db::Region &r)
281360{
282- // NOTE: if the source (r) is from the same layout than the shapes live in, we better
283- // lock the layout against updates while inserting
284- db::LayoutLocker locker (sh->layout ());
361+ ProtectedShapes ps (sh, r);
285362 for (db::Region::const_iterator s = r.begin (); ! s.at_end (); ++s) {
286- sh ->insert (*s);
363+ ps ->insert (*s);
287364 }
288365}
289366
290367static void insert_region_with_trans (db::Shapes *sh, const db::Region &r, const db::ICplxTrans &trans)
291368{
292- // NOTE: if the source (r) is from the same layout than the shapes live in, we better
293- // lock the layout against updates while inserting
294- db::LayoutLocker locker (sh->layout ());
369+ ProtectedShapes ps (sh, r);
295370 for (db::Region::const_iterator s = r.begin (); ! s.at_end (); ++s) {
296- sh ->insert (s->transformed (trans));
371+ ps ->insert (s->transformed (trans));
297372 }
298373}
299374
300375static void insert_region_with_dtrans (db::Shapes *sh, const db::Region &r, const db::DCplxTrans &trans)
301376{
377+ ProtectedShapes ps (sh, r);
302378 db::CplxTrans dbu_trans (shapes_dbu (sh));
303379 db::ICplxTrans itrans = dbu_trans.inverted () * trans * dbu_trans;
304380 for (db::Region::const_iterator s = r.begin (); ! s.at_end (); ++s) {
305- sh ->insert (s->transformed (itrans));
381+ ps ->insert (s->transformed (itrans));
306382 }
307383}
308384
309385static void insert_edges (db::Shapes *sh, const db::Edges &r)
310386{
387+ ProtectedShapes ps (sh, r);
311388 for (db::Edges::const_iterator s = r.begin (); ! s.at_end (); ++s) {
312- sh ->insert (*s);
389+ ps ->insert (*s);
313390 }
314391}
315392
316393static void insert_edges_with_trans (db::Shapes *sh, const db::Edges &r, const db::ICplxTrans &trans)
317394{
395+ ProtectedShapes ps (sh, r);
318396 for (db::Edges::const_iterator s = r.begin (); ! s.at_end (); ++s) {
319- sh ->insert (s->transformed (trans));
397+ ps ->insert (s->transformed (trans));
320398 }
321399}
322400
323401static void insert_edges_with_dtrans (db::Shapes *sh, const db::Edges &r, const db::DCplxTrans &trans)
324402{
403+ ProtectedShapes ps (sh, r);
325404 db::CplxTrans dbu_trans (shapes_dbu (sh));
326405 db::ICplxTrans itrans = dbu_trans.inverted () * trans * dbu_trans;
327406 for (db::Edges::const_iterator s = r.begin (); ! s.at_end (); ++s) {
328- sh ->insert (s->transformed (itrans));
407+ ps ->insert (s->transformed (itrans));
329408 }
330409}
331410
332411static void insert_edge_pairs_as_polygons (db::Shapes *sh, const db::EdgePairs &r, db::Coord e)
333412{
413+ ProtectedShapes ps (sh, r);
334414 for (db::EdgePairs::const_iterator s = r.begin (); ! s.at_end (); ++s) {
335- sh ->insert (s->normalized ().to_simple_polygon (e));
415+ ps ->insert (s->normalized ().to_simple_polygon (e));
336416 }
337417}
338418
339419static void insert_edge_pairs_as_polygons_d (db::Shapes *sh, const db::EdgePairs &r, db::DCoord de)
340420{
421+ ProtectedShapes ps (sh, r);
341422 db::Coord e = db::coord_traits<db::Coord>::rounded (de / shapes_dbu (sh));
342423 for (db::EdgePairs::const_iterator s = r.begin (); ! s.at_end (); ++s) {
343- sh ->insert (s->normalized ().to_simple_polygon (e));
424+ ps ->insert (s->normalized ().to_simple_polygon (e));
344425 }
345426}
346427
347428static void insert_edge_pairs_as_polygons_with_trans (db::Shapes *sh, const db::EdgePairs &r, const db::ICplxTrans &trans, db::Coord e)
348429{
430+ ProtectedShapes ps (sh, r);
349431 for (db::EdgePairs::const_iterator s = r.begin (); ! s.at_end (); ++s) {
350- sh ->insert (s->normalized ().to_simple_polygon (e).transformed (trans));
432+ ps ->insert (s->normalized ().to_simple_polygon (e).transformed (trans));
351433 }
352434}
353435
354436static void insert_edge_pairs_as_polygons_with_dtrans (db::Shapes *sh, const db::EdgePairs &r, const db::DCplxTrans &trans, db::DCoord de)
355437{
438+ ProtectedShapes ps (sh, r);
356439 db::Coord e = db::coord_traits<db::Coord>::rounded (de / shapes_dbu (sh));
357440 db::CplxTrans dbu_trans (shapes_dbu (sh));
358441 db::ICplxTrans itrans = dbu_trans.inverted () * trans * dbu_trans;
359442 for (db::EdgePairs::const_iterator s = r.begin (); ! s.at_end (); ++s) {
360- sh ->insert (s->normalized ().to_simple_polygon (e).transformed (itrans));
443+ ps ->insert (s->normalized ().to_simple_polygon (e).transformed (itrans));
361444 }
362445}
363446
364447static void insert_edge_pairs_as_edges (db::Shapes *sh, const db::EdgePairs &r)
365448{
449+ ProtectedShapes ps (sh, r);
366450 for (db::EdgePairs::const_iterator s = r.begin (); ! s.at_end (); ++s) {
367- sh ->insert (s->first ());
368- sh ->insert (s->second ());
451+ ps ->insert (s->first ());
452+ ps ->insert (s->second ());
369453 }
370454}
371455
372456static void insert_edge_pairs_as_edges_with_trans (db::Shapes *sh, const db::EdgePairs &r, const db::ICplxTrans &trans)
373457{
458+ ProtectedShapes ps (sh, r);
374459 for (db::EdgePairs::const_iterator s = r.begin (); ! s.at_end (); ++s) {
375- sh ->insert (s->first ().transformed (trans));
376- sh ->insert (s->second ().transformed (trans));
460+ ps ->insert (s->first ().transformed (trans));
461+ ps ->insert (s->second ().transformed (trans));
377462 }
378463}
379464
380465static void insert_edge_pairs_as_edges_with_dtrans (db::Shapes *sh, const db::EdgePairs &r, const db::DCplxTrans &trans)
381466{
467+ ProtectedShapes ps (sh, r);
382468 db::CplxTrans dbu_trans (shapes_dbu (sh));
383469 db::ICplxTrans itrans = dbu_trans.inverted () * trans * dbu_trans;
384470 for (db::EdgePairs::const_iterator s = r.begin (); ! s.at_end (); ++s) {
385- sh ->insert (s->first ().transformed (itrans));
386- sh ->insert (s->second ().transformed (itrans));
471+ ps ->insert (s->first ().transformed (itrans));
472+ ps ->insert (s->second ().transformed (itrans));
387473 }
388474}
389475
390476static void insert_edge_pairs (db::Shapes *sh, const db::EdgePairs &r)
391477{
478+ ProtectedShapes ps (sh, r);
392479 for (db::EdgePairs::const_iterator s = r.begin (); ! s.at_end (); ++s) {
393- sh ->insert (*s);
480+ ps ->insert (*s);
394481 }
395482}
396483
397484static void insert_edge_pairs_with_trans (db::Shapes *sh, const db::EdgePairs &r, const db::ICplxTrans &trans)
398485{
486+ ProtectedShapes ps (sh, r);
399487 for (db::EdgePairs::const_iterator s = r.begin (); ! s.at_end (); ++s) {
400- sh ->insert (s->transformed (trans));
488+ ps ->insert (s->transformed (trans));
401489 }
402490}
403491
404492static void insert_edge_pairs_with_dtrans (db::Shapes *sh, const db::EdgePairs &r, const db::DCplxTrans &trans)
405493{
494+ ProtectedShapes ps (sh, r);
406495 db::CplxTrans dbu_trans (shapes_dbu (sh));
407496 db::ICplxTrans itrans = dbu_trans.inverted () * trans * dbu_trans;
408497 for (db::EdgePairs::const_iterator s = r.begin (); ! s.at_end (); ++s) {
409- sh ->insert (s->transformed (itrans));
498+ ps ->insert (s->transformed (itrans));
410499 }
411500}
412501
413502static void insert_texts (db::Shapes *sh, const db::Texts &r)
414503{
504+ ProtectedShapes ps (sh, r);
415505 for (db::Texts::const_iterator s = r.begin (); ! s.at_end (); ++s) {
416- sh ->insert (*s);
506+ ps ->insert (*s);
417507 }
418508}
419509
420510static void insert_texts_with_trans (db::Shapes *sh, const db::Texts &r, const db::ICplxTrans &trans)
421511{
512+ ProtectedShapes ps (sh, r);
422513 for (db::Texts::const_iterator s = r.begin (); ! s.at_end (); ++s) {
423- sh ->insert (s->transformed (trans));
514+ ps ->insert (s->transformed (trans));
424515 }
425516}
426517
427518static void insert_texts_with_dtrans (db::Shapes *sh, const db::Texts &r, const db::DCplxTrans &trans)
428519{
520+ ProtectedShapes ps (sh, r);
429521 db::CplxTrans dbu_trans (shapes_dbu (sh));
430522 db::ICplxTrans itrans = dbu_trans.inverted () * trans * dbu_trans;
431523 for (db::Texts::const_iterator s = r.begin (); ! s.at_end (); ++s) {
432- sh ->insert (s->transformed (itrans));
524+ ps ->insert (s->transformed (itrans));
433525 }
434526}
435527
0 commit comments