int HashDelete(HashTable ht, void *data) /* Removes the record containing 'data' from ht. If no such record exists, hashDelete returns 0. On success it returns 1. DOES NOT DESTROY DATA */ { int retval=0; HashInfoPtr tmp; unsigned int hashval = ht->calcIndx(data)%ht->size; ErrPushFunc("HashDelete"); if(ht->infoArray[hashval]!=NULL) { if(!(ht->compData(ht->infoArray[hashval]->data, data))) { HashInfoPtr toTrash; /*First record matched -- remove it! */ toTrash=ht->infoArray[hashval]; ht->infoArray[hashval]=toTrash->next; #if defined (_POSIX_SEMAPHORES) && defined (_POSIX_THREADS) { int error = sem_destroy(&(toTrash->cursorListSemaphore)); if (error != 0) perror("hash.c HashDelete sem_destroy"); } #endif free(toTrash); ht->elementCount--; assert( ht->elementCount >= 0 ); retval=1; } else { for( tmp = ht->infoArray[hashval]; /* Continue search for match */ (tmp->next!=NULL) && (ht->compData(tmp->next->data, data)); tmp = tmp->next) ; if(tmp->next!=NULL) { /* If found, remove the matching record. */ HashInfoPtr toTrash; toTrash = tmp->next; tmp->next = toTrash->next; #if defined (_POSIX_SEMAPHORES) && defined (_POSIX_THREADS) { int error = sem_destroy(&(toTrash->cursorListSemaphore)); if (error != 0) perror("hash.c HashDelete sem_destroy"); } #endif free(toTrash); ht->elementCount--; assert( ht->elementCount >= 0 ); retval=1; } } } ErrPopFunc(); return(retval); }
int HashAdd(HashTable ht, void *data) /* Adds data to the specified hashtable. If an equivalent record (according to ht->compData() ) exists, no adding is done. Returns 1 on success, 0 on failure. */ { int retval = 1; unsigned int hashval = ht->calcIndx(data)%ht->size; HashInfoPtr newInfo; ErrPushFunc("HashAdd"); if(FindInfo(ht, data, hashval)) retval=0; else { if( (newInfo = (HashInfoPtr)malloc(sizeof(struct HiPtr))) != NULL ) { int error; newInfo->data = data; newInfo->next = ht->infoArray[hashval]; newInfo->firstCursor = NULL; #if defined (_POSIX_SEMAPHORES) && defined (_POSIX_THREADS) error = sem_init( &(newInfo->cursorListSemaphore), 0, 1 ); if (error != 0) { retval = 0; goto ERR_RETURN; } #endif /* I believe this is an atomic action and therefore needs not be protected by a semaphore to be thread-safe. Can this be guaranteed? What does the pthreads package say about atomicity? Anyway, the elementCount needs to be semaphored methinks. /Erl 981015 */ ht->infoArray[hashval] = newInfo; ht->elementCount++; } else { retval = 0; goto ERR_RETURN; } } ERR_RETURN: ErrPopFunc(); return(retval); }
int HashDestroy(HashTable ht, void *data) /* Removes the record containing 'data' from ht and DESTROYS data. If no such record exists, it returns 0. On success 1 is returned. */ { int retval=0; HashInfoPtr tmp; unsigned int hashval = ht->calcIndx(data)%ht->size; ErrPushFunc("HashDestroy"); if(ht->infoArray[hashval]!=NULL) { if(!(ht->compData(ht->infoArray[hashval]->data, data))) { HashInfoPtr toTrash; /*First record matched -- remove it! */ toTrash=ht->infoArray[hashval]; ht->infoArray[hashval]=toTrash->next; DestroyInfo(ht, toTrash); ht->elementCount--; assert( ht->elementCount >= 0 ); retval=1; } else { for( tmp = ht->infoArray[hashval]; /* Continue search for match */ (tmp->next!=NULL) && (ht->compData(tmp->next->data, data)); tmp = tmp->next ) ; if(tmp->next!=NULL) { /* If found, remove the matching record. */ HashInfoPtr toTrash; toTrash = tmp->next; tmp->next = toTrash->next; DestroyInfo(ht, toTrash); ht->elementCount--; assert( ht->elementCount >= 0 ); retval=1; } } } ErrPopFunc(); return(retval); }