diff --git a/src/util/inc/tref.h b/src/util/inc/tref.h index 6619ff407e2aad2322e952ce3ef43c87eba64bb2..1ac7cd87bdd8b42580b5ef206fbbf1cdf5ceefa9 100644 --- a/src/util/inc/tref.h +++ b/src/util/inc/tref.h @@ -21,15 +21,41 @@ extern "C" { #endif -int taosOpenRef(int max, void (*fp)(void *)); // return refId which will be used by other APIs +// open an instance, return refId which will be used by other APIs +int taosOpenRef(int max, void (*fp)(void *)); + +// close the Ref instance void taosCloseRef(int refId); -int taosListRef(); // return the number of references in system + +// add ref, p is the pointer to resource or pointer ID int taosAddRef(int refId, void *p); +#define taosRemoveRef taosReleaseRef + +// acquire ref, p is the pointer to resource or pointer ID int taosAcquireRef(int refId, void *p); + +// release ref, p is the pointer to resource or pinter ID void taosReleaseRef(int refId, void *p); -#define taosRemoveRef taosReleaseRef +// return the first if p is null, otherwise return the next after p +void *taosIterateRef(int refId, void *p); +// return the number of references in system +int taosListRef(); + +/* sample code to iterate the refs + +void demoIterateRefs(int refId) { + + void *p = taosGetRefNext(refId, NULL); + while (p) { + + // process P + + p = taosGetRefNext(refId, p); + } +} +*/ #ifdef __cplusplus } diff --git a/src/util/src/tref.c b/src/util/src/tref.c index 4c3b8363407326b724c0b2706231bd751e43e110..23a7210e99105a1e0e9919939da2d6d186e09e26 100644 --- a/src/util/src/tref.c +++ b/src/util/src/tref.c @@ -143,8 +143,6 @@ int taosAddRef(int refId, void *p) return TSDB_CODE_REF_INVALID_ID; } - uTrace("refId:%d p:%p try to add", refId, p); - pSet = tsRefSetList + refId; taosIncRefCount(pSet); if (pSet->state != TSDB_REF_STATE_ACTIVE) { @@ -203,8 +201,6 @@ int taosAcquireRef(int refId, void *p) return TSDB_CODE_REF_INVALID_ID; } - uTrace("refId:%d p:%p try to acquire", refId, p); - pSet = tsRefSetList + refId; taosIncRefCount(pSet); if (pSet->state != TSDB_REF_STATE_ACTIVE) { @@ -254,8 +250,6 @@ void taosReleaseRef(int refId, void *p) return; } - uTrace("refId:%d p:%p try to release", refId, p); - pSet = tsRefSetList + refId; if (pSet->state == TSDB_REF_STATE_EMPTY) { uTrace("refId:%d p:%p failed to release, cleaned", refId, p); @@ -305,6 +299,75 @@ void taosReleaseRef(int refId, void *p) if (released) taosDecRefCount(pSet); } +// if p is NULL, return the first p in hash list, otherwise, return the next after p +void *taosIterateRef(int refId, void *p) { + SRefNode *pNode = NULL; + SRefSet *pSet; + + if (refId < 0 || refId >= TSDB_REF_OBJECTS) { + uTrace("refId:%d p:%p failed to iterate, refId not valid", refId, p); + return NULL; + } + + pSet = tsRefSetList + refId; + taosIncRefCount(pSet); + if (pSet->state != TSDB_REF_STATE_ACTIVE) { + uTrace("refId:%d p:%p failed to iterate, not active", refId, p); + taosDecRefCount(pSet); + return NULL; + } + + int hash = 0; + if (p) { + hash = taosHashRef(pSet, p); + taosLockList(pSet->lockedBy+hash); + + pNode = pSet->nodeList[hash]; + while (pNode) { + if (pNode->p == p) break; + pNode = pNode->next; + } + + if (pNode == NULL) { + uError("refId:%d p:%p not there, quit", refId, p); + taosUnlockList(pSet->lockedBy+hash); + return NULL; + } + + // p is there + pNode = pNode->next; + if (pNode == NULL) { + taosUnlockList(pSet->lockedBy+hash); + hash++; + } + } + + if (pNode == NULL) { + for (; hash < pSet->max; ++hash) { + taosLockList(pSet->lockedBy+hash); + pNode = pSet->nodeList[hash]; + if (pNode) break; + taosUnlockList(pSet->lockedBy+hash); + } + } + + void *newP = NULL; + if (pNode) { + pNode->count++; // acquire it + newP = pNode->p; + taosUnlockList(pSet->lockedBy+hash); + uTrace("refId:%d p:%p is returned", refId, p); + } else { + uTrace("refId:%d p:%p the list is over", refId, p); + } + + if (p) taosReleaseRef(refId, p); // release the current one + + taosDecRefCount(pSet); + + return newP; +} + int taosListRef() { SRefSet *pSet; SRefNode *pNode; diff --git a/src/util/tests/trefTest.c b/src/util/tests/trefTest.c index 486f9f6d6d8cbde6f130aebc96efb209c5b26997..09ffccd7b5fc4ea1c2a645a8ff6d8ec0c70cc8f2 100644 --- a/src/util/tests/trefTest.c +++ b/src/util/tests/trefTest.c @@ -17,6 +17,19 @@ typedef struct { void **p; } SRefSpace; +void iterateRefs(int refId) { + int count = 0; + + void *p = taosIterateRef(refId, NULL); + while (p) { + // process P + count++; + p = taosIterateRef(refId, p); + } + + printf(" %d ", count); +} + void *takeRefActions(void *param) { SRefSpace *pSpace = (SRefSpace *)param; int code, id; @@ -44,6 +57,9 @@ void *takeRefActions(void *param) { usleep(id % 5 + 1); taosReleaseRef(pSpace->refId, pSpace->p[id]); } + + id = random() % pSpace->refNum; + iterateRefs(id); } for (int i=0; i < pSpace->refNum; ++i) { @@ -63,7 +79,7 @@ void *openRefSpace(void *param) { SRefSpace *pSpace = (SRefSpace *)param; printf("c"); - pSpace->refId = taosOpenRef(10000, myfree); + pSpace->refId = taosOpenRef(50, myfree); if (pSpace->refId < 0) { printf("failed to open ref, reson:%s\n", tstrerror(pSpace->refId));