From 4ff8d0681069712cfb58938cdd8614b6d42fa7e0 Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Sun, 21 Mar 2021 20:53:20 -0400 Subject: [PATCH] Changed to a hybrid list and stack; the list keeps 65536 entries at a time, and when it runs out of space, it pushes the stack. This should speed up the connectivity routine somewhat, as it no longer has to copy memory when expanding the list size, and it no longer has limit at the integer boundary for memory allocation. --- database/DBconnect.c | 199 ++++++++----------------------------------- 1 file changed, 36 insertions(+), 163 deletions(-) diff --git a/database/DBconnect.c b/database/DBconnect.c index cdab8d1c..3ea3bee9 100644 --- a/database/DBconnect.c +++ b/database/DBconnect.c @@ -29,6 +29,7 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/ #include "utils/geometry.h" #include "tiles/tile.h" #include "utils/hash.h" +#include "utils/stack.h" #include "database/database.h" #include "database/databaseInt.h" #include "select/select.h" @@ -86,13 +87,13 @@ struct conSrArg2 int csa2_xMask; /* Cell window mask for search */ Rect *csa2_bounds; /* Area that limits the search */ + Stack *csa2_stack; /* Stack of full csa2_list entries */ conSrArea *csa2_list; /* List of areas to process */ int csa2_top; /* Index of next area to process */ int csa2_lasttop; /* Previous top index */ - int csa2_size; /* Max. number bins in area list */ }; -#define CSA2_LIST_START_SIZE 256 +#define CSA2_LIST_SIZE 65536 /* Number of entries per list */ /* *----------------------------------------------------------------- @@ -775,24 +776,17 @@ dbcConnectLabelFunc(scx, lab, tpath, csa2) /* Register the area and connection mask as needing to be processed */ - if (++csa2->csa2_top == csa2->csa2_size) + if (++csa2->csa2_top == CSA2_LIST_SIZE) { + /* Reached list size limit---need to push the list and */ + /* start a new one. */ + conSrArea *newlist; - int newSize, newTotal; - /* Reached list size limit---need to enlarge the list */ - /* Double the size of the list every time we hit the limit */ - - newSize = csa2->csa2_size * 2; - newTotal = newSize * sizeof(conSrArea); - if (newTotal <= 0) return 1; - - newlist = (conSrArea *)mallocMagic((size_t)newTotal); - memcpy((void *)newlist, (void *)csa2->csa2_list, - (size_t)csa2->csa2_size * sizeof(conSrArea)); - freeMagic((char *)csa2->csa2_list); + newlist = (conSrArea *)mallocMagic(CSA2_LIST_SIZE * + sizeof(conSrArea)); + StackPush((ClientData)csa2->csa2_list, csa2->csa2_stack); csa2->csa2_list = newlist; - csa2->csa2_size = newSize; } csa2->csa2_list[csa2->csa2_top].area = newarea; @@ -973,25 +967,17 @@ dbcConnectFunc(tile, cx) /* Register the area and connection mask as needing to be processed */ - if (++csa2->csa2_top == csa2->csa2_size) + if (++csa2->csa2_top == CSA2_LIST_SIZE) { - /* Reached list size limit---need to enlarge the list */ - /* Double the size of the list every time we hit the limit */ + /* Reached list size limit---need to push the list and */ + /* start a new one. */ conSrArea *newlist; - int newSize, newTotal; - newSize = csa2->csa2_size * 2; - newTotal = newSize * sizeof(conSrArea); - - if (newTotal <= 0) return 1; /* Exceeded integer bounds */ - - newlist = (conSrArea *)mallocMagic((size_t)newTotal); - memcpy((void *)newlist, (void *)csa2->csa2_list, - (size_t)csa2->csa2_size * sizeof(conSrArea)); - freeMagic((char *)csa2->csa2_list); + newlist = (conSrArea *)mallocMagic(CSA2_LIST_SIZE * sizeof(conSrArea)); + StackPush((ClientData)csa2->csa2_list, csa2->csa2_stack); csa2->csa2_list = newlist; - csa2->csa2_size = newSize; + csa2->csa2_top = 0; } csa2->csa2_list[csa2->csa2_top].area = newarea; @@ -1001,119 +987,6 @@ dbcConnectFunc(tile, cx) return 0; } -/* - * ---------------------------------------------------------------------------- - * ---------------------------------------------------------------------------- - */ - -int -dbcCheckConnectFunc(tile, cx) - Tile *tile; /* Tile found. */ - TreeContext *cx; /* Describes context of search. The client - * data is a pointer to a conSrArg2 record - * containing various required information. - */ -{ - struct conSrArg2 *csa2; - Rect tileArea, newarea; - TileTypeBitMask *connectMask, notConnectMask; - Rect *srArea; - SearchContext *scx = cx->tc_scx; - SearchContext scx2; - TileType loctype = TiGetTypeExact(tile); - TileType dinfo = 0; - int i, pNum = cx->tc_plane; - CellDef *def; - - TiToRect(tile, &tileArea); - srArea = &scx->scx_area; - - GeoTransRect(&scx->scx_trans, &tileArea, &newarea); - - /* Clip the current area down to something that overlaps the - * area of interest. - */ - - csa2 = (struct conSrArg2 *)cx->tc_filter->tf_arg; - GeoClip(&newarea, csa2->csa2_bounds); - if (GEO_RECTNULL(&newarea)) return 1; - - if (IsSplit(tile)) - { - dinfo = DBTransformDiagonal(loctype, &scx->scx_trans); - loctype = (SplitSide(tile)) ? SplitRightType(tile) : SplitLeftType(tile); - } - - connectMask = &csa2->csa2_connect[loctype]; - - if (DBIsContact(loctype)) - { - /* The mask of contact types must include all stacked contacts */ - - TTMaskZero(¬ConnectMask); - TTMaskSetMask(¬ConnectMask, &DBNotConnectTbl[loctype]); - } - else - TTMaskCom2(¬ConnectMask, connectMask); - - /* Only check those tiles in the destination (select) */ - /* which have not already been painted. */ - - def = csa2->csa2_use->cu_def; - if (DBSrPaintNMArea((Tile *) NULL, def->cd_planes[pNum], - dinfo, &newarea, ¬ConnectMask, dbcUnconnectFunc, - (ClientData) NULL) == 0) - return 1; - - return 0; -} - -/* - * ---------------------------------------------------------------------------- - * ---------------------------------------------------------------------------- - */ - -int -dbPruneEntries(scx, xMask, csa2) - SearchContext *scx; - int xMask; - struct conSrArg2 *csa2; -{ - int i, j, result; - TileTypeBitMask *newmask; - TileType newtype; - - for (i = 0, j = 0; i < csa2->csa2_top; i++) - { - newmask = csa2->csa2_list[i].connectMask; - scx->scx_area = csa2->csa2_list[i].area; - newtype = csa2->csa2_list[i].dinfo; - - if (newtype & TT_DIAGONAL) - result = DBTreeSrNMTiles(scx, newtype, newmask, xMask, dbcCheckConnectFunc, - (ClientData) csa2); - else - result = DBTreeSrTiles(scx, newmask, xMask, dbcCheckConnectFunc, - (ClientData) csa2); - - if (result == 0) - { - if (i > j) - { - csa2->csa2_list[j].connectMask = newmask; - csa2->csa2_list[j].area = scx->scx_area; - csa2->csa2_list[j].dinfo = newtype; - } - j++; - } - } - if (j == i) - return 1; - - csa2->csa2_top = j; - return 0; -} - /* * ---------------------------------------------------------------------------- * @@ -1189,16 +1062,15 @@ DBTreeCopyConnect(scx, mask, xMask, connect, area, doLabels, destUse) /* malloc calls by maintaining a small list and expanding it only */ /* when necessary. */ - csa2.csa2_size = CSA2_LIST_START_SIZE; - csa2.csa2_list = (conSrArea *)mallocMagic(CSA2_LIST_START_SIZE - * sizeof(conSrArea)); + csa2.csa2_list = (conSrArea *)mallocMagic(CSA2_LIST_SIZE * sizeof(conSrArea)); csa2.csa2_top = -1; csa2.csa2_lasttop = -1; + csa2.csa2_stack = StackNew(100); + DBTreeSrTiles(scx, mask, xMask, dbcConnectFunc, (ClientData) &csa2); while (csa2.csa2_top >= 0) { - int result; char pathstring[FLATTERMSIZE]; TerminalPath tpath; @@ -1209,29 +1081,29 @@ DBTreeCopyConnect(scx, mask, xMask, connect, area, doLabels, destUse) newmask = csa2.csa2_list[csa2.csa2_top].connectMask; scx->scx_area = csa2.csa2_list[csa2.csa2_top].area; newtype = csa2.csa2_list[csa2.csa2_top].dinfo; - csa2.csa2_top--; + if (csa2.csa2_top == 0) + { + if (StackLook(csa2.csa2_stack) != (ClientData)NULL) + { + freeMagic(csa2.csa2_list); + csa2.csa2_list = (conSrArea *)StackPop(csa2.csa2_stack); + csa2.csa2_top = CSA2_LIST_SIZE - 1; + } + else + csa2.csa2_top--; + } + else + csa2.csa2_top--; + csa2.csa2_lasttop = csa2.csa2_top; if (newtype & TT_DIAGONAL) - result = DBTreeSrNMTiles(scx, newtype, newmask, xMask, dbcConnectFunc, + DBTreeSrNMTiles(scx, newtype, newmask, xMask, dbcConnectFunc, (ClientData) &csa2); else - result = DBTreeSrTiles(scx, newmask, xMask, dbcConnectFunc, + DBTreeSrTiles(scx, newmask, xMask, dbcConnectFunc, (ClientData) &csa2); - if (result != 0) - { - result = dbPruneEntries(scx, xMask, &csa2); - if (result == 1) - { - TxError("Connectivity search exceeded memory limit and stopped;" - " incomplete result.\n"); - break; - } - else - continue; - } - /* Check the source def for any labels belonging to this */ /* tile area and plane, and add them to the destination. */ @@ -1271,6 +1143,7 @@ DBTreeCopyConnect(scx, mask, xMask, connect, area, doLabels, destUse) } } freeMagic((char *)csa2.csa2_list); + StackFree(csa2.csa2_stack); /* Recompute the bounding box of the destination and record its area * for redisplay.