Skip to content

Commit 71202ea

Browse files
Merge pull request #2098 from KLayout/bugfix/issue-2094
Fixing issue #2094 (slow insert into Shapes)
2 parents ff7d7f2 + 4ab64ca commit 71202ea

File tree

2 files changed

+313
-46
lines changed

2 files changed

+313
-46
lines changed

src/db/db/gsiDeclDbShapes.cc

Lines changed: 138 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
226311
static 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

237320
static 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

248329
static 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

253335
static 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

258341
static 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

269350
static 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

280359
static 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

290367
static 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

300375
static 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

309385
static 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

316393
static 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

323401
static 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

332411
static 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

339419
static 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

347428
static 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

354436
static 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

364447
static 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

372456
static 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

380465
static 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

390476
static 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

397484
static 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

404492
static 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

413502
static 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

420510
static 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

427518
static 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

Comments
 (0)