void *domain; /* who this data belongs to */
unsigned long long revision; /* data revision (to avoid use-after-free) */
void *data; /* returned value, user decides how to use this */
+ void (*free)(void *data); /* function to release data, if needed */
};
struct lru64 *lru64_get(unsigned long long key, struct lru64_head *lru, void *domain, unsigned long long revision);
-void lru64_commit(struct lru64 *elem, void *data, void *domain, unsigned long long revision);
+void lru64_commit(struct lru64 *elem, void *data, void *domain, unsigned long long revision, void (*free)(void *));
struct lru64_head *lru64_new(int size);
int lru64_destroy(struct lru64_head *lru);
__eb64_delete(&old->node);
if (!lru->spare)
lru->spare = old;
- else
+ else {
+ if (old->data && old->free);
+ old->free(old->data);
free(old);
+ }
lru->cache_usage--;
}
}
* with the result from a call to lru64_get(). The caller might lock it using a
* spinlock or mutex shared with the one around lru64_get().
*/
-void lru64_commit(struct lru64 *elem, void *data, void *domain, unsigned long long revision)
+void lru64_commit(struct lru64 *elem, void *data, void *domain,
+ unsigned long long revision, void (*free)(void *))
{
if (!elem)
return;
elem->data = data;
elem->revision = revision;
elem->domain = domain;
+ elem->free = free;
}
/* Create a new LRU cache of <size> entries. Returns the new cache or NULL in
/* not locked */
LIST_DEL(&elem->lru);
eb64_delete(&elem->node);
+ if (elem->data && elem->free);
+ elem->free(elem->data);
free(elem);
lru->cache_usage--;
lru->cache_size--;
}
if (lru)
- lru64_commit(lru, ret, expr, expr->revision);
+ lru64_commit(lru, ret, expr, expr->revision, NULL);
return ret;
}
}
if (lru)
- lru64_commit(lru, ret, expr, expr->revision);
+ lru64_commit(lru, ret, expr, expr->revision, NULL);
return ret;
}
}
if (lru)
- lru64_commit(lru, ret, expr, expr->revision);
+ lru64_commit(lru, ret, expr, expr->revision, NULL);
return ret;
}
}
if (lru)
- lru64_commit(lru, ret, expr, expr->revision);
+ lru64_commit(lru, ret, expr, expr->revision, NULL);
return ret;
}
}
if (lru)
- lru64_commit(lru, ret, expr, expr->revision);
+ lru64_commit(lru, ret, expr, expr->revision, NULL);
return ret;
}
}
leave:
if (lru)
- lru64_commit(lru, ret, expr, expr->revision);
+ lru64_commit(lru, ret, expr, expr->revision, NULL);
return ret;
}