/** * Deletes the requested node. * * @param node node to be deleted */ static void node_delete_aux(struct bst_node** node) { /* TODO: For Step 2 you will have to make this function thread-safe */ struct bst_node* old_node = *node; if ((*node)->left == NULL) { *node = (*node)->right; // Node is replaced by its RIGHT node free_node(old_node); } else if ((*node)->right == NULL) { *node = (*node)->left; // Node is replaced by its LEFT node free_node(old_node); } else { // Here we need to lock the node we are looking at AND its parent struct bst_node** pred = &(*node)->left; // pred is set to the LEFT node while ((*pred)->right != NULL) { // Find the most RIGHT node of pred pred = &(*pred)->right; } /* Swap values */ void* temp = (*pred)->data; // Set the value of NODE = NODE->LEFT->(most RIGHT node value) (*pred)->data = (*node)->data; (*node)->data = temp; node_delete_aux(pred); // Remove NODE->LEFT->(most RIGHT node) instead of NODE } }
/** * Deletes the requested node. * * @param node node to be deleted */ static void node_delete_aux(struct bst_node** node) { /* TODO: For Step 2 you will have to make this function thread-safe */ struct bst_node* old_node = *node; if ((*node)->left == NULL) { *node = (*node)->right; free_node(old_node); } else if ((*node)->right == NULL) { *node = (*node)->left; free_node(old_node); } else { struct bst_node** pred = &(*node)->left; while ((*pred)->right != NULL) { pred = &(*pred)->right; } /* Swap values */ void* temp = (*pred)->data; (*pred)->data = (*node)->data; (*node)->data = temp; node_delete_aux(pred); } }
/** * Deletes the node which points to the requested data. * * @param root root of the tree * @param comparator function used to compare nodes * @param data pointer to the data to be deleted * @return 1 if data is not found, 0 otherwise */ int node_delete(struct bst_node** root, comparator compare, void* data) { struct bst_node** node = search(root, compare, data); if (*node == NULL) return -1; node_delete_aux(node); return 0; }
/** * Deletes the node which points to the requested data. * * Should be safe when called in parallel with other threads that * might call the same functions. Uses fine grained locking. * * @param root root of the tree * @param comparator function used to compare nodes * @param data pointer to the data to be deleted * @return 1 if data is not found, 0 otherwise */ int node_delete_ts_fg(struct bst_node** root, comparator compare, void* data) { /* TODO: Fill-in the body of this function */ struct bst_node** node = search(root, compare, data); //find node to delete if (*node == NULL) return -1; node_delete_aux(node); //delete node return 0; }
/** * Deletes the node which points to the requested data. * * Should be safe when called in parallel with other threads that * might call the same functions. Uses fine grained locking. * * @param root root of the tree * @param comparator function used to compare nodes * @param data pointer to the data to be deleted * @return 1 if data is not found, 0 otherwise */ int node_delete_ts_cg(struct bst_node** root, comparator compare, void* data) { /* TODO: Fill-in the body of this function */ assert(pthread_mutex_lock(&mutexCG) == 0); //lock mutexCG struct bst_node** node = search(root, compare, data); //find the node (if any) to delete node_delete_aux(node); assert(pthread_mutex_unlock(&mutexCG) == 0); //unlock mutexCG return 0; }
/** * Deletes the node which points to the requested data. * * Should be safe when called in parallel with other threads that * might call the same functions. Uses fine grained locking. * * @param root root of the tree * @param comparator function used to compare nodes * @param data pointer to the data to be deleted * @return 1 if data is not found, 0 otherwise */ int node_delete_ts_fg(struct bst_node** root, comparator compare, void* data) { /* TODO: Fill-in the body of this function */ struct bst_node** node = search(root, compare, data); if (node == NULL) return -1; else { node_delete_aux(node); return 0; } }
static void fg_node_delete_aux(struct bst_node** node) { /* TODO: For Step 2 you will have to make this function thread-safe */ struct bst_node* old_node = *node; if ((*node)->left == NULL) { if((*node)->right != NULL) { pthread_mutex_lock(&(*node)->right->fg_mutex); } *node = (*node)->right; pthread_mutex_unlock(&old_node->fg_mutex); free_node(old_node); if((*node) != NULL) { pthread_mutex_unlock(&(*node)->fg_mutex); } } else if ((*node)->right == NULL) { if((*node)->left != NULL) { pthread_mutex_lock(&(*node)->left->fg_mutex); } *node = (*node)->left; pthread_mutex_unlock(&old_node->fg_mutex); free_node(old_node); if((*node) != NULL) { pthread_mutex_unlock(&(*node)->fg_mutex); } } else { pthread_mutex_lock(&(*node)->left->fg_mutex); struct bst_node** pred = &(*node)->left; struct bst_node** pred_temp = pred; while ((*pred)->right != NULL) { pthread_mutex_lock(&(*pred)->right->fg_mutex); pred = &(*pred)->right; pthread_mutex_unlock(&(*pred_temp)->fg_mutex); pred_temp = pred; } /* Swap values */ void* temp = (*pred)->data; (*pred)->data = (*node)->data; (*node)->data = temp; pthread_mutex_unlock(&old_node->fg_mutex); node_delete_aux(pred); } }
/** * Deletes the node which points to the requested data. * * Should be safe when called in parallel with other threads that * might call the same functions. Uses fine grained locking. * * @param root root of the tree * @param comparator function used to compare nodes * @param data pointer to the data to be deleted * @return 1 if data is not found, 0 otherwise */ int node_delete_ts_cg(struct bst_node** root, comparator compare, void* data) { /* TODO: Fill-in the body of this function */ pthread_mutex_lock(&mutexCG); struct bst_node** node = search(root, compare, data); if (*node == NULL){ pthread_mutex_unlock(&mutexCG); return -1; } else { node_delete_aux(node); pthread_mutex_unlock(&mutexCG); return 0; } }
/** * Deletes the requested node. * * @param node node to be deleted */ static void node_delete_aux(struct bst_node** node) { /* TODO: For Step 2 you will have to make this function thread-safe */ // vi vet att vi är i rätt nod struct bst_node* old_node = *node; // kolla om vänster barn existerar if ((*node)->left == NULL) { // eftersom vänster barn inte finns kan vi använda höger barn *node = (*node)->right; free_node(old_node); // Vänster Barn Finns och höger finns inte } else if ((*node)->right == NULL) { // swap till vänster barn *node = (*node)->left; free_node(old_node); /*********************************************/ if(*parent != NULL) assert(pthread_mutex_unlock(&(*parent)->mutexNODE) == 0); /*********************************************/ } else { // vi vet att båda barn finns, vi måste alltså gå ett steg till // vänster och gå längst ner i dess högerbarn struct bst_node** pred = &(*node)->left; while ((*pred)->right != NULL) { pred = &(*pred)->right; } /* Swap values */ void* temp = (*pred)->data; (*pred)->data = (*node)->data; (*node)->data = temp; assert(pthread_mutex_unlock(&(*parent)->mutexNODE) == 0); // vi har bytt info, och skall ta bort temp barnet men gör det // rekursivt eftersom den kan ha vänsterbarn node_delete_aux(pred); assert(pthread_mutex_unlock(&(*node)->mutexNODE) == 0); } }
//pthread_spinlock_t cg_spin; int node_delete_ts_cg(struct bst_node** root, comparator compare, void* data) { /* TODO: Fill-in the body of this function */ if(pthread_mutex_lock(&cg_mutex) != 0) { perror("ERROR: "); exit(EXIT_FAILURE); } //if(pthread_spin_lock(&cg_spin) != 0) { perror("ERROR: "); exit(EXIT_FAILURE); } struct bst_node** node = search(root, compare, data); if (node == NULL) { //if(pthread_spin_unlock(&cg_spin) != 0) { perror("ERROR: "); exit(EXIT_FAILURE); } if(pthread_mutex_unlock(&cg_mutex) != 0) { perror("ERROR: "); exit(EXIT_FAILURE); } return -1; } node_delete_aux(node); //if(pthread_spin_unlock(&cg_spin) != 0) { perror("ERROR: "); exit(EXIT_FAILURE); } if(pthread_mutex_unlock(&cg_mutex) != 0) { perror("ERROR: "); exit(EXIT_FAILURE); } return 0; }