Files
epics-base/src/libCom/bucketLib.c
1994-04-13 18:00:06 +00:00

422 lines
6.9 KiB
C
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/*
* Author: Jeffrey O. Hill
* hill@atdiv.lanl.gov
* (505) 665 1831
* Date: 9-93
*
* Experimental Physics and Industrial Control System (EPICS)
*
* Copyright 1991, the Regents of the University of California,
* and the University of Chicago Board of Governors.
*
* This software was produced under U.S. Government contracts:
* (W-7405-ENG-36) at the Los Alamos National Laboratory,
* and (W-31-109-ENG-38) at Argonne National Laboratory.
*
* Initial development by:
* The Controls and Automation Group (AT-8)
* Ground Test Accelerator
* Accelerator Technology Division
* Los Alamos National Laboratory
*
* Co-developed with
* The Controls and Computing Group
* Accelerator Systems Division
* Advanced Photon Source
* Argonne National Laboratory
*
* Modification Log:
* -----------------
* .01 091493 joh fixed overzealous parameter check
* .02 121693 joh added bucketFree()
*/
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
#include <bucketLib.h>
#ifndef NBBY
#define NBBY 8
#endif /* NBBY */
#ifndef TRUE
#define TRUE 1
#endif /* TRUE */
#ifndef FALSE
#define FALSE 0
#endif /* FALSE */
#define BUCKET_IX_WIDTH 12
#define BUCKET_IX_N (1<<BUCKET_IX_WIDTH)
#define BUCKET_IX_MASK (BUCKET_IX_N-1)
#ifdef DEBUG
main()
{
BUCKETID id;
int s;
BUCKET *pb;
char *pValSave;
char *pVal;
unsigned i;
pb = bucketCreate(NBBY*sizeof(BUCKETID));
if(!pb){
return BUCKET_FAILURE;
}
id = 444;
pValSave = "fred";
s = bucketAddItem(pb, id, pValSave);
if(s != BUCKET_SUCCESS){
return BUCKET_FAILURE;
}
printf("Begin\n");
for(i=0; i<500000; i++){
pVal = bucketLookupItem(pb, id);
if(pVal != pValSave){
printf("failure\n");
break;
}
pVal = bucketLookupItem(pb, id);
if(pVal != pValSave){
printf("failure\n");
break;
}
pVal = bucketLookupItem(pb, id);
if(pVal != pValSave){
printf("failure\n");
break;
}
pVal = bucketLookupItem(pb, id);
if(pVal != pValSave){
printf("failure\n");
break;
}
pVal = bucketLookupItem(pb, id);
if(pVal != pValSave){
printf("failure\n");
break;
}
pVal = bucketLookupItem(pb, id);
if(pVal != pValSave){
printf("failure\n");
break;
}
pVal = bucketLookupItem(pb, id);
if(pVal != pValSave){
printf("failure\n");
break;
}
pVal = bucketLookupItem(pb, id);
if(pVal != pValSave){
printf("failure\n");
break;
}
pVal = bucketLookupItem(pb, id);
if(pVal != pValSave){
printf("failure\n");
break;
}
pVal = bucketLookupItem(pb, id);
if(pVal != pValSave){
printf("failure\n");
break;
}
}
printf("End\n");
return BUCKET_SUCCESS;
}
#endif
/*
* bucketCreate()
*/
#ifdef __STDC__
BUCKET *bucketCreate(unsigned indexWidth)
#else
BUCKET *bucketCreate(indexWidth)
unsigned indexWidth;
#endif
{
BUCKET *pb;
/*
* indexWidth must be specified at least one
* bit less than the bit size of type BUCKETID
*/
if(indexWidth>sizeof(BUCKETID)*NBBY){
printf("%s at %d: Requested index width=%d is to large. max=%d\n" ,
__FILE__,
__LINE__,
indexWidth,
sizeof(BUCKETID)*NBBY-1);
return NULL;
}
pb = (BUCKET *) calloc(1, sizeof(*pb));
if(!pb){
return pb;
}
if(indexWidth>BUCKET_IX_WIDTH){
pb->indexShift = indexWidth - BUCKET_IX_WIDTH;
}
else{
pb->indexShift = 0;
}
pb->nextIndexMask = (1<<pb->indexShift)-1;
pb->nEntries = 1<<(indexWidth-pb->indexShift);
if(indexWidth == sizeof(BUCKETID)*NBBY){
pb->indexMask = 0;
pb->indexMask = ~pb->indexMask;
}
else{
pb->indexMask = (1<<indexWidth)-1;
}
pb->pTable = (ITEMPTR *) calloc(
pb->nEntries,
sizeof(ITEMPTR));
if(!pb->pTable){
free(pb);
return NULL;
}
return pb;
}
/*
* bucketFree()
*/
#ifdef __STDC__
int bucketFree(BUCKET *prb)
#else
int bucketFree(prb)
BUCKET *prb;
#endif
{
/*
* deleting a bucket with entries in use
* will cause memory leaks and is not allowed
*/
if(prb->nInUse){
return BUCKET_FAILURE;
}
free(prb->pTable);
free(prb);
return BUCKET_SUCCESS;
}
/*
* bucketAddItem()
*/
#ifdef __STDC__
int bucketAddItem(BUCKET *prb, BUCKETID id, void *pItem)
#else
int bucketAddItem(prb, id, pItem)
BUCKET *prb;
BUCKETID id;
void *pItem;
#endif
{
int s;
ITEMPTR *pi;
/*
* is the id to big ?
*/
if(id&~prb->indexMask){
return BUCKET_FAILURE;
}
if(prb->indexShift){
int new;
BUCKET *pb;
pi = &prb->pTable[id>>prb->indexShift];
pb = pi->pBucket;
if(!pb){
pb = bucketCreate(prb->indexShift);
if(!pb){
return BUCKET_FAILURE;
}
pi->pBucket = pb;
prb->nInUse++;
new = TRUE;
}
else{
new = FALSE;
}
s = bucketAddItem(
pb,
id&prb->nextIndexMask,
pItem);
/*
* if memory cant be allocated at a lower
* level dont leak everything allocated for this new
* item so far
*/
if(s != BUCKET_SUCCESS && new){
s = bucketFree(pb);
assert(s == BUCKET_SUCCESS);
pi->pBucket = NULL;
prb->nInUse--;
}
return s;
}
pi = &prb->pTable[id];
if(pi->pItem){
return BUCKET_FAILURE;
}
pi->pItem = pItem;
prb->nInUse++;
return BUCKET_SUCCESS;
}
/*
* bucketRemoveItem()
*/
#ifdef __STDC__
int bucketRemoveItem (BUCKET *prb, BUCKETID id, void *pItem)
#else
int bucketRemoveItem (prb, id, pItem)
BUCKET *prb;
BUCKETID id;
void *pItem;
#endif
{
ITEMPTR *ppi;
/*
* is the id to big ?
*/
if(id&~prb->indexMask){
return BUCKET_FAILURE;
}
if(prb->indexShift){
BUCKET *pb;
int s;
ppi = &prb->pTable[id>>prb->indexShift];
pb = ppi->pBucket;
if(!pb){
return BUCKET_FAILURE;
}
s = bucketRemoveItem(
pb,
id&prb->nextIndexMask,
pItem);
if(s!=BUCKET_SUCCESS){
return s;
}
if(pb->nInUse==0){
free(pb->pTable);
free(pb);
ppi->pBucket = NULL;
prb->nInUse--;
}
return s;
}
ppi = &prb->pTable[id];
if(ppi->pItem != pItem){
return BUCKET_FAILURE;
}
prb->nInUse--;
ppi->pItem = NULL;
return BUCKET_SUCCESS;
}
/*
* bucketLookupItem()
*/
#ifdef __STDC__
void *bucketLookupItem(BUCKET *pb, BUCKETID id)
#else
void *bucketLookupItem(pb, id)
BUCKET *pb;
BUCKETID id;
#endif
{
unsigned shift;
/*
* is the id to big ?
*/
if(id&~pb->indexMask){
return NULL;
}
while(shift = pb->indexShift){
BUCKETID nextId;
nextId = id & pb->nextIndexMask;
pb = pb->pTable[id>>shift].pBucket;
if(!pb){
return pb;
}
id = nextId;
}
return pb->pTable[id].pItem;
}
/*
* bucketShow()
*/
#ifdef __STDC__
int bucketShow(BUCKET *pb)
#else
int bucketShow(pb)
BUCKET *pb;
#endif
{
ITEMPTR *pi;
pi = pb->pTable;
printf( "Bucket: mask=%x entries in use=%d bytes in use=%d\n",
(pb->nEntries-1)<<pb->indexShift,
pb->nInUse,
sizeof(*pb)+pb->nEntries*sizeof(*pi));
if(pb->indexShift){
for( pi = pb->pTable;
pi<&pb->pTable[pb->nEntries];
pi++){
if(pi->pBucket){
bucketShow(pi->pBucket);
}
}
}
return BUCKET_SUCCESS;
}