static int wipeList(const char *fileName, int lineNbr, PsmPartition partition, PsmAddress list, SmListDeleteFn deleteFn, void *arg, int destroy) { SmList *listBuffer; PsmAddress elt; PsmAddress next; SmListElt *eltBuffer; listBuffer = (SmList *) psp(partition, list); if (lockSmlist(listBuffer) < 0) { putErrmsg(_cannotLockMsg(), NULL); return -1; } for (elt = listBuffer->first; elt != 0; elt = next) { eltBuffer = (SmListElt *) psp(partition, elt); CHKERR(eltBuffer); next = eltBuffer->next; if (deleteFn) { deleteFn(partition, elt, arg); } /* clear in case user mistakenly accesses later... */ eraseListElt(eltBuffer); Psm_free(fileName, lineNbr, partition, elt); } eraseList(listBuffer); if (destroy) { sm_SemDelete(listBuffer->lock); listBuffer->lock = SM_SEM_NONE; Psm_free(fileName, lineNbr, partition, list); } else { unlockSmlist(listBuffer); } return 0; }
void releaseToIonMemory(char *fileName, int lineNbr, void *block) { PsmPartition ionwm = _ionwm(NULL); Psm_free(fileName, lineNbr, ionwm, psa(ionwm, (char *) block)); #ifdef HAVE_VALGRIND_VALGRIND_H VALGRIND_FREELIKE_BLOCK(block, 0); #endif }
void Sm_rbt_destroy(char *file, int line, PsmPartition partition, PsmAddress rbt, SmRbtDeleteFn deleteFn, void *arg) { SmRbt *rbtPtr; CHKVOID(partition); CHKVOID(rbt); rbtPtr = (SmRbt *) psp(partition, rbt); oK(lockSmrbt(rbtPtr)); destroyRbtNodes(file, line, partition, rbtPtr, deleteFn, arg); /* Now destroy the tree itself. */ sm_SemDelete(rbtPtr->lock); /* just in case user mistakenly accesses later... */ eraseTree(rbtPtr); Psm_free(file, line, partition, rbt); }
void releaseToIonMemory(char *fileName, int lineNbr, void *block) { PsmPartition ionwm = _ionwm(NULL); Psm_free(fileName, lineNbr, ionwm, psa(ionwm, (char *) block)); }
static void releaseToDgrMemory(const char *fileName, int lineNbr, void *block) { Psm_free(fileName, lineNbr, dgrwm, psa(dgrwm, (char *) block)); }
void Sm_rbt_delete(char *file, int line, PsmPartition partition, PsmAddress rbt, SmRbtCompareFn compare, void *dataBuffer, SmRbtDeleteFn deleteFn, void *arg) { SmRbtNode dummyRootBuffer = { 0, 0, {0, 0}, 0, 0 }; /* Dummy root is a trick; it * lets us avoid special cases. */ SmRbt *rbtPtr; PsmAddress node; // q SmRbtNode *nodePtr; // q PsmAddress sibling; // s SmRbtNode *siblingPtr; // s PsmAddress parent; // p SmRbtNode *parentPtr; // p PsmAddress stepparent; // p SmRbtNode *stepparentPtr; // p SmRbtNode *grandparentPtr; // g PsmAddress target; // f SmRbtNode *targetPtr; // f int direction; // dir int otherDirection; // !dir int prevDirection; // last int prevOtherDirection; // !last int subtree; // dir2 SmRbtNode *childPtr[2]; int result; int i; int j; CHKVOID(partition); CHKVOID(rbt); CHKVOID(compare); rbtPtr = (SmRbt *) psp(partition, rbt); CHKVOID(rbtPtr); if (rbtPtr->length == 0 || rbtPtr->root == 0 || lockSmrbt(rbtPtr) == ERROR) { return; } /* We descend the tree, searching for the node that is * to be deleted (rather than requiring its address), * because we want to ensure that the node has been * recolored red -- if necessary -- by the time we * reach it. This is because deleting a red node never * violates any red-black tree rules, so there is no * subsequent tree fix-up needed. Our general strategy * is to push "red-ness" all the way down to the target * node, rotating as necessary to ensure that the target * node is transformed into a red leaf. * * Note: a special case is when the node that is to be * deleted is the only node in the tree, hence the root. * In this case (only), we can delete a black node * without violating any red-black tree rules. * * Note 2: this searching strategy is the reason we need * the compare function provided on node deletion just * as on node insertion. */ grandparentPtr = NULL; parent = 0; /* None. */ parentPtr = NULL; node = 0; nodePtr = &dummyRootBuffer; nodePtr->child[RIGHT] = rbtPtr->root; target = 0; // f direction = RIGHT; while (nodePtr->child[direction]) { prevDirection = direction; grandparentPtr = parentPtr; /* The first time through the loop, parentPtr * is NULL so grandparentPtr is still NULL. The * second time through the loop, nodePtr is a * pointer to the dummy root, so the dummy root * becomes the grandparent. The third time, a * pointer to the tree's root (a real node) is * placed in grandparentPtr. */ parent = node; parentPtr = nodePtr; /* The first time through the loop, nodePtr is * a pointer to the dummy root, so the dummy root * becomes the parent. The second time, a pointer * to the tree's root (a real node) is placed in * parentPtr. */ node = nodePtr->child[direction]; nodePtr = (SmRbtNode *) psp(partition, node); /* The first time through the loop, a pointer * to the tree's root (a real node) is placed in * nodePtr before any other processing happens. * * Note that the loop continues PAST the node * that is to be deleted, locating that node's * inorder predecessor. Then we come back to * move the predecessor's data into the target * node (erasing the target node's data) and * destroy to predecessor node. */ result = compare(partition, nodePtr->data, dataBuffer); if (result < 0) { direction = RIGHT; } else { direction = LEFT; if (result == 0) { target = node; } } if (nodeIsRed(partition, node) || nodeIsRed(partition, nodePtr->child[direction])) { continue; /* No recolor needed. */ } /* Neither the node nor its child (if any) in * the current direction of search are red, so * we must introduce some redness. */ otherDirection = 1 - direction; if (nodeIsRed(partition, nodePtr->child[otherDirection])) { /* This is the "red sibling" case. Rotate * current node down/red. */ childPtr[otherDirection] = (SmRbtNode *) psp(partition, nodePtr->child[otherDirection]); parentPtr->child[prevDirection] = rotateOnce(partition, node, direction); /* The new root of the subtree whose root * before rotation was "node" [the red * sibling] must be noted as "parent" in * place of the original parent of "node", * because it is now the actual parent * of "node". */ parent = parentPtr->child[prevDirection]; parentPtr = (SmRbtNode *) psp(partition, parent); /* We've introduced the necessary redness; * time to descend again. */ continue; } /* Node and all of its children (if any) are now * known to be black. * * Remaining cases concern the children (if any) * of the sibling (if any) of the current node. */ prevOtherDirection = 1 - prevDirection; sibling = parentPtr->child[prevOtherDirection]; if (sibling == 0) /* (True of tree root.) */ { continue; /* No sibling, no problem. */ } /* Node has got a sibling. Therefore it can't be * the root of the tree, so the root of the tree * must be above this node. Therefore this node's * parent cannot be the dummy node, so both the * node's parent and the dummy node are above this * node in the tree. So the node must have a * grandparent (the dummy node or some real node * lower in the tree). So grandparentPtr cannot * be NULL. */ siblingPtr = (SmRbtNode *) psp(partition, sibling); /* Check for need to flip colors. NOT TREE ROOT. */ if (nodeIsRed(partition, siblingPtr->child[LEFT]) == 0 && nodeIsRed(partition, siblingPtr->child[RIGHT]) == 0) { /* Sibling has no red children, so it's * safe to make both the current node and * its sibling RED and their parent BLACK. */ parentPtr->isRed = 0; siblingPtr->isRed = 1; nodePtr->isRed = 1; continue; } if (parent == grandparentPtr->child[RIGHT]) { subtree = RIGHT; } else { subtree = LEFT; } /* Note: grandparent is known to have a child * on the "subtree" side ("parent"), even if * grandparent is dummy. And that child is * known to have two children -- "node" and * "sibling". */ if (nodeIsRed(partition, siblingPtr->child[prevDirection])) { grandparentPtr->child[subtree] = rotateTwice(partition, parent, prevDirection); } else { if (nodeIsRed(partition, siblingPtr->child[prevOtherDirection])) { grandparentPtr->child[subtree] = rotateOnce(partition, parent, prevDirection); } } /* The subtree may now have a new parent, due * to rotation. Ensure nodes have correct colors. */ stepparent = grandparentPtr->child[subtree]; stepparentPtr = (SmRbtNode *) psp(partition, stepparent); stepparentPtr->isRed = 1; nodePtr->isRed = 1; childPtr[LEFT] = (SmRbtNode *) psp(partition, stepparentPtr->child[LEFT]); childPtr[LEFT]->isRed = 0; childPtr[RIGHT] = (SmRbtNode *) psp(partition, stepparentPtr->child[RIGHT]); childPtr[RIGHT]->isRed = 0; } /* At this point the current node is NOT the one we're * trying to delete. It is the inorder predecessor of * the node we're trying to delete -- a node whose * content we want to retain. The data that's in this * predecessor is retained by copying it into the * target node -- which effectively deletes the target * node without actually removing it from the tree. * Then the current node (the inorder predecessor of * the target node, which is now redundant) is removed * from the tree. */ if (target) { targetPtr = (SmRbtNode *) psp(partition, target); if (deleteFn) { deleteFn(partition, targetPtr->data, arg); } targetPtr->data = nodePtr->data; /* To destroy inorder predecessor node, must * make its parent forget about it. */ if (parentPtr->child[RIGHT] == node) { i = RIGHT; } else { i = LEFT; } if (nodePtr->child[LEFT] == 0) { j = RIGHT; } else { j = LEFT; } parentPtr->child[i] = nodePtr->child[j]; /* just in case user mistakenly accesses later... */ eraseTreeNode(nodePtr); Psm_free(file, line, partition, node); rbtPtr->length -= 1; } /* Update root in rbt object. */ rbtPtr->root = dummyRootBuffer.child[RIGHT]; /* Make sure root is BLACK. */ if (rbtPtr->root) { nodePtr = (SmRbtNode *) psp(partition, rbtPtr->root); nodePtr->isRed = 0; } unlockSmrbt(rbtPtr); }
static void destroyRbtNodes(char *file, int line, PsmPartition partition, SmRbt *rbtPtr, SmRbtDeleteFn deleteFn, void *arg) { PsmAddress node; SmRbtNode *nodePtr; PsmAddress parentNode; node = rbtPtr->root; nodePtr = (SmRbtNode *) psp(partition, node); /* Destroy all nodes of the tree. */ while (node) { /* If node has a left subtree, descend into it. */ if (nodePtr->child[LEFT]) { node = nodePtr->child[LEFT]; nodePtr = (SmRbtNode *) psp(partition, node); continue; } /* If node has a right subtree, descend into it. */ if (nodePtr->child[RIGHT]) { node = nodePtr->child[RIGHT]; nodePtr = (SmRbtNode *) psp(partition, node); continue; } /* Node is a leaf, so can delete it. */ parentNode = nodePtr->parent; if (deleteFn) { deleteFn(partition, nodePtr->data, arg); } /* just in case user mistakenly accesses later... */ eraseTreeNode(nodePtr); Psm_free(file, line, partition, node); /* Now pop back up to this node's parent. */ if (parentNode == 0) { rbtPtr->root = 0; break; /* Have deleted the root node. */ } nodePtr = (SmRbtNode *) psp(partition, parentNode); /* Erase the child pointer for the child that * has now been deleted. */ if (node == nodePtr->child[LEFT]) { nodePtr->child[LEFT] = 0; } if (node == nodePtr->child[RIGHT]) { nodePtr->child[RIGHT] = 0; } node = parentNode; } }
int Sm_list_delete(const char *fileName, int lineNbr, PsmPartition partition, PsmAddress elt, SmListDeleteFn deleteFn, void *arg) { SmListElt *eltBuffer; PsmAddress list; SmList *listBuffer; PsmAddress next; PsmAddress prev; CHKERR(partition); CHKERR(elt); eltBuffer = (SmListElt *) psp(partition, elt); CHKERR(eltBuffer); if ((list = eltBuffer->list) == 0) { putErrmsg(_noListMsg(), NULL); return -1; } listBuffer = (SmList *) psp(partition, list); if (lockSmlist(listBuffer) == ERROR) { putErrmsg(_cannotLockMsg(), NULL); return -1; } if (listBuffer->length < 1) { unlockSmlist(listBuffer); putErrmsg("list element can't be deleted, list is empty", NULL); return -1; } next = eltBuffer->next; prev = eltBuffer->prev; if (deleteFn) { deleteFn(partition, elt, arg); } /* clear in case user accesses later... */ eraseListElt(eltBuffer); Psm_free(fileName, lineNbr, partition, elt); if (prev) { eltBuffer = (SmListElt *) psp(partition, prev); CHKERR(eltBuffer); eltBuffer->next = next; } else { listBuffer->first = next; } if (next) { eltBuffer = (SmListElt *) psp(partition, next); CHKERR(eltBuffer); eltBuffer->prev = prev; } else { listBuffer->last = prev; } listBuffer->length -= 1; unlockSmlist(listBuffer); return 0; }
void Sdr_free(const char *file, int line, Sdr sdr, Object object) { //TODO check sdr type return Psm_free(file, line, sdr, object); }