void GWEN_MemCache_PurgeEntries(GWEN_MEMCACHE *mc, uint32_t id, uint32_t mask) { GWEN_IDMAP_RESULT res; uint32_t currentId; assert(mc); GWEN_MemCache_Lock(mc); res=GWEN_MemCacheEntry_IdMap_GetFirst(mc->idMap, ¤tId); while(res==GWEN_IdMapResult_Ok) { uint32_t nextId; nextId=currentId; res=GWEN_MemCacheEntry_IdMap_GetNext(mc->idMap, &nextId); if ((currentId & mask)==id) { GWEN_MEMCACHE_ENTRY *me; me=GWEN_MemCacheEntry_IdMap_Find(mc->idMap, currentId); if (me) { me->isValid=0; GWEN_MemCacheEntry_IdMap_Remove(mc->idMap, currentId); if (me->useCounter==0) GWEN_MemCacheEntry_free(me); } } currentId=nextId; } GWEN_MemCache_Unlock(mc); }
void GWEN_MemCacheEntry_EndUse(GWEN_MEMCACHE_ENTRY *me) { int rv; assert(me); rv=GWEN_MemCache_Lock(me->memCache); if (rv) { DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv); assert(0); } if (me->useCounter>0) { me->useCounter--; if (me->useCounter==0) { if (!(me->isValid)) { GWEN_MemCacheEntry_free(me); } else me->unusedSince=time(0); } } else { DBG_ERROR(GWEN_LOGDOMAIN, "Use counter < 1, aborting"); GWEN_MemCache_Unlock(me->memCache); assert(me->useCounter>0); } GWEN_MemCache_Unlock(me->memCache); }
GWEN_MEMCACHE_ENTRY *GWEN_MemCache_CreateEntry(GWEN_MEMCACHE *mc, uint32_t id, void *dataPtr, size_t dataLen) { GWEN_MEMCACHE_ENTRY *me; assert(mc); GWEN_MemCache_Lock(mc); /* invalidate possibly existing entry in any case */ me=GWEN_MemCacheEntry_IdMap_Find(mc->idMap, id); if (me) { me->isValid=0; GWEN_MemCacheEntry_IdMap_Remove(mc->idMap, id); if (me->useCounter==0) GWEN_MemCacheEntry_free(me); } /* check for limits: entry count */ if (mc->currentCacheEntries>=mc->maxCacheEntries) { int rv; /* release unused entries (at least 1 byte) */ rv=GWEN_MemCache__MakeRoom(mc, 1); if (rv) { DBG_WARN(GWEN_LOGDOMAIN, "Too many entries in use"); GWEN_MemCache_Unlock(mc); return NULL; } } /* check for limits: memory in use */ if ((mc->currentCacheMemory+dataLen)>=mc->maxCacheMemory) { size_t diff; int rv; diff=(mc->currentCacheMemory+dataLen)-mc->maxCacheMemory; /* release unused entries */ rv=GWEN_MemCache__MakeRoom(mc, diff); if (rv) { DBG_WARN(GWEN_LOGDOMAIN, "Too much memory in use"); GWEN_MemCache_Unlock(mc); return NULL; } } /* create new entry */ me=GWEN_MemCacheEntry_new(mc, id, dataPtr, dataLen); assert(me); me->useCounter++; GWEN_MemCacheEntry_IdMap_Insert(mc->idMap, id, me); GWEN_MemCache_Unlock(mc); return me; }
void GWEN_MemCache_PurgeEntry(GWEN_MEMCACHE *mc, uint32_t id) { GWEN_MEMCACHE_ENTRY *me; assert(mc); GWEN_MemCache_Lock(mc); me=GWEN_MemCacheEntry_IdMap_Find(mc->idMap, id); if (me) { me->isValid=0; GWEN_MemCacheEntry_IdMap_Remove(mc->idMap, id); if (me->useCounter==0) GWEN_MemCacheEntry_free(me); } GWEN_MemCache_Unlock(mc); }
int GWEN_MemCache__MakeRoom(GWEN_MEMCACHE *mc, size_t neededSize) { assert(mc); /* release unused entries until there is enough memory */ while (neededSize) { GWEN_MEMCACHE_ENTRY *oldestEntry; GWEN_IDMAP_RESULT res; uint32_t currentId; /* get oldest entry */ oldestEntry=NULL; res=GWEN_MemCacheEntry_IdMap_GetFirst(mc->idMap, ¤tId); while (res==GWEN_IdMapResult_Ok) { GWEN_MEMCACHE_ENTRY *me; me=GWEN_MemCacheEntry_IdMap_Find(mc->idMap, currentId); if (me) { if (me->isValid && me->useCounter==0) { if (oldestEntry==NULL) oldestEntry=me; else { if (me->unusedSince<oldestEntry->unusedSince) oldestEntry=me; } } } res=GWEN_MemCacheEntry_IdMap_GetNext(mc->idMap, ¤tId); } if (oldestEntry==NULL) /* no unused entry found */ break; /* subtract size of to-be-removed entry from needed size */ if (neededSize<oldestEntry->dataLen) neededSize=0; else neededSize-=oldestEntry->dataLen; /* remove oldest entry (it is unused, so we also delete it here) */ GWEN_MemCacheEntry_IdMap_Remove(mc->idMap, oldestEntry->id); GWEN_MemCacheEntry_free(oldestEntry); } return (neededSize==0)?0:GWEN_ERROR_MEMORY_FULL; }