Cache limiter cleanup and small fixes
- Made code a bit less cluttered to follow - Fixed possible deadlock when enforcing limit and highest priority element is still referenced.
This commit is contained in:
parent
dde5e5ce25
commit
aeee7118ae
@ -138,8 +138,8 @@ public:
|
|||||||
typedef size_t (*MEM_CacheLimiter_DataSize_Func) (void *data);
|
typedef size_t (*MEM_CacheLimiter_DataSize_Func) (void *data);
|
||||||
typedef int (*MEM_CacheLimiter_ItemPriority_Func) (void *item, int default_priority);
|
typedef int (*MEM_CacheLimiter_ItemPriority_Func) (void *item, int default_priority);
|
||||||
|
|
||||||
MEM_CacheLimiter(MEM_CacheLimiter_DataSize_Func getDataSize_)
|
MEM_CacheLimiter(MEM_CacheLimiter_DataSize_Func data_size_func)
|
||||||
: getDataSize(getDataSize_) {
|
: data_size_func(data_size_func) {
|
||||||
}
|
}
|
||||||
|
|
||||||
~MEM_CacheLimiter() {
|
~MEM_CacheLimiter() {
|
||||||
@ -162,10 +162,16 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
size_t get_memory_in_use() {
|
size_t get_memory_in_use() {
|
||||||
if (getDataSize)
|
size_t size = 0;
|
||||||
return total_size();
|
if (data_size_func) {
|
||||||
else
|
for (iterator it = queue.begin(); it != queue.end(); it++) {
|
||||||
return MEM_get_memory_in_use();
|
size += data_size_func((*it)->get()->get_data());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
size = MEM_get_memory_in_use();
|
||||||
|
}
|
||||||
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
void enforce_limits() {
|
void enforce_limits() {
|
||||||
@ -188,15 +194,15 @@ public:
|
|||||||
if (!elem)
|
if (!elem)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (getDataSize) {
|
if (data_size_func) {
|
||||||
cur_size = getDataSize(elem->get()->get_data());
|
cur_size = data_size_func(elem->get()->get_data());
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
cur_size = mem_in_use;
|
cur_size = mem_in_use;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (elem->destroy_if_possible()) {
|
if (elem->destroy_if_possible()) {
|
||||||
if (getDataSize) {
|
if (data_size_func) {
|
||||||
mem_in_use -= cur_size;
|
mem_in_use -= cur_size;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -207,15 +213,21 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
void touch(MEM_CacheLimiterHandle<T> * handle) {
|
void touch(MEM_CacheLimiterHandle<T> * handle) {
|
||||||
queue.push_back(handle);
|
/* If we're using custom priority callback re-arranging the queue
|
||||||
queue.erase(handle->me);
|
* doesn't make much sense because we'll iterate it all to get
|
||||||
iterator it = queue.end();
|
* least priority element anyway.
|
||||||
--it;
|
*/
|
||||||
handle->me = it;
|
if (item_priority_func == NULL) {
|
||||||
|
queue.push_back(handle);
|
||||||
|
queue.erase(handle->me);
|
||||||
|
iterator it = queue.end();
|
||||||
|
--it;
|
||||||
|
handle->me = it;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_item_priority_func(MEM_CacheLimiter_ItemPriority_Func item_priority_func) {
|
void set_item_priority_func(MEM_CacheLimiter_ItemPriority_Func item_priority_func) {
|
||||||
getItemPriority = item_priority_func;
|
this->item_priority_func = item_priority_func;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -223,41 +235,42 @@ private:
|
|||||||
typedef std::list<MEM_CacheElementPtr, MEM_Allocator<MEM_CacheElementPtr> > MEM_CacheQueue;
|
typedef std::list<MEM_CacheElementPtr, MEM_Allocator<MEM_CacheElementPtr> > MEM_CacheQueue;
|
||||||
typedef typename MEM_CacheQueue::iterator iterator;
|
typedef typename MEM_CacheQueue::iterator iterator;
|
||||||
|
|
||||||
size_t total_size() {
|
|
||||||
size_t size = 0;
|
|
||||||
for (iterator it = queue.begin(); it != queue.end(); it++) {
|
|
||||||
size+= getDataSize((*it)->get()->get_data());
|
|
||||||
}
|
|
||||||
return size;
|
|
||||||
}
|
|
||||||
|
|
||||||
MEM_CacheElementPtr get_least_priority_destroyable_element(void) {
|
MEM_CacheElementPtr get_least_priority_destroyable_element(void) {
|
||||||
if (queue.empty())
|
if (queue.empty())
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (!getItemPriority)
|
|
||||||
return *queue.begin();
|
|
||||||
|
|
||||||
MEM_CacheElementPtr best_match_elem = NULL;
|
MEM_CacheElementPtr best_match_elem = NULL;
|
||||||
int best_match_priority = 0;
|
|
||||||
iterator it;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (it = queue.begin(), i = 0; it != queue.end(); it++, i++) {
|
if (!item_priority_func) {
|
||||||
MEM_CacheElementPtr elem = *it;
|
for (iterator it = queue.begin(); it != queue.end(); it++) {
|
||||||
|
MEM_CacheElementPtr elem = *it;
|
||||||
if (!elem->can_destroy())
|
if (!elem->can_destroy())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* by default 0 means highest priority element */
|
|
||||||
/* casting a size type to int is questionable,
|
|
||||||
but unlikely to cause problems */
|
|
||||||
int priority = -((int)(queue.size()) - i - 1);
|
|
||||||
priority = getItemPriority(elem->get()->get_data(), priority);
|
|
||||||
|
|
||||||
if (priority < best_match_priority || best_match_elem == NULL) {
|
|
||||||
best_match_priority = priority;
|
|
||||||
best_match_elem = elem;
|
best_match_elem = elem;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
int best_match_priority = 0;
|
||||||
|
iterator it;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (it = queue.begin(), i = 0; it != queue.end(); it++, i++) {
|
||||||
|
MEM_CacheElementPtr elem = *it;
|
||||||
|
|
||||||
|
if (!elem->can_destroy())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* by default 0 means highest priority element */
|
||||||
|
/* casting a size type to int is questionable,
|
||||||
|
but unlikely to cause problems */
|
||||||
|
int priority = -((int)(queue.size()) - i - 1);
|
||||||
|
priority = item_priority_func(elem->get()->get_data(), priority);
|
||||||
|
|
||||||
|
if (priority < best_match_priority || best_match_elem == NULL) {
|
||||||
|
best_match_priority = priority;
|
||||||
|
best_match_elem = elem;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -265,8 +278,8 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
MEM_CacheQueue queue;
|
MEM_CacheQueue queue;
|
||||||
MEM_CacheLimiter_DataSize_Func getDataSize;
|
MEM_CacheLimiter_DataSize_Func data_size_func;
|
||||||
MEM_CacheLimiter_ItemPriority_Func getItemPriority;
|
MEM_CacheLimiter_ItemPriority_Func item_priority_func;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // __MEM_CACHELIMITER_H__
|
#endif // __MEM_CACHELIMITER_H__
|
||||||
|
Loading…
Reference in New Issue
Block a user