2011-03-11 17:14:54 +01:00
|
|
|
#ifndef GCACHE_PROVIDER_H
|
|
|
|
#define GCACHE_PROVIDER_H
|
|
|
|
|
2011-12-14 18:42:23 +01:00
|
|
|
#include <wrap/system/multithreading/mt.h>
|
2011-03-11 17:14:54 +01:00
|
|
|
#include "dheap.h"
|
|
|
|
#include "door.h"
|
|
|
|
|
|
|
|
#include "token.h"
|
|
|
|
|
|
|
|
/* this cache system enforce the rule that the items in a cache are always in all the cache below */
|
|
|
|
/* two mechanism to remove tokens from the cache:
|
|
|
|
1) set token count to something low
|
|
|
|
2) set maximum number of tokens in the provider
|
|
|
|
*/
|
|
|
|
|
2011-11-26 19:08:30 +01:00
|
|
|
/** Base class for Cache and last cache in the GCache system.
|
2011-03-11 17:14:54 +01:00
|
|
|
You should never interact with this class.
|
|
|
|
*/
|
|
|
|
|
|
|
|
template <typename Token>
|
2011-12-14 18:42:23 +01:00
|
|
|
class Provider: public mt::thread {
|
2011-03-11 17:14:54 +01:00
|
|
|
public:
|
|
|
|
///holds the resources in this cache but not in the cache above
|
2011-11-26 19:08:30 +01:00
|
|
|
PtrDHeap<Token> heap;
|
2011-03-11 17:14:54 +01:00
|
|
|
///tokens above this number will be scheduled for deletion
|
|
|
|
int max_tokens;
|
|
|
|
///signals we need to rebuild heap.
|
2011-11-26 19:08:30 +01:00
|
|
|
bool heap_dirty;
|
|
|
|
///lock this before manipulating heap.
|
2011-12-14 18:42:23 +01:00
|
|
|
mt::mutex heap_lock;
|
2011-03-11 17:14:54 +01:00
|
|
|
///signals (to next cache!) priorities have changed or something is available
|
2011-11-26 19:08:30 +01:00
|
|
|
QDoor check_queue;
|
2011-03-11 17:14:54 +01:00
|
|
|
|
|
|
|
Provider(): max_tokens(-1), heap_dirty(false) {}
|
|
|
|
virtual ~Provider() {}
|
|
|
|
|
2011-12-20 19:25:13 +01:00
|
|
|
/// [should be protected, do not use] called in controller thread!
|
2011-03-11 17:14:54 +01:00
|
|
|
void pushPriorities() {
|
2011-12-20 19:25:13 +01:00
|
|
|
mt::mutexlocker locker(&heap_lock);
|
2011-03-11 17:14:54 +01:00
|
|
|
for(int i = 0; i < heap.size(); i++)
|
|
|
|
heap[i].pushPriority();
|
2011-12-20 19:25:13 +01:00
|
|
|
|
2011-03-11 17:14:54 +01:00
|
|
|
heap_dirty = true;
|
|
|
|
check_queue.open();
|
|
|
|
}
|
|
|
|
/// assumes heap lock is locked, runs in cache thread [should be protected, do not use]
|
|
|
|
void rebuild() {
|
|
|
|
if(!this->heap_dirty) return;
|
|
|
|
|
|
|
|
this->heap.rebuild();
|
2011-12-20 19:25:13 +01:00
|
|
|
this->heap_dirty = false;
|
2011-03-11 17:14:54 +01:00
|
|
|
|
|
|
|
//remove OUTSIDE tokens from bottom of heap
|
|
|
|
if(max_tokens != -1) {
|
|
|
|
while(this->heap.size() > max_tokens) {
|
|
|
|
Token &t = this->heap.min();
|
|
|
|
t.count = Token::OUTSIDE;
|
|
|
|
this->heap.popMin();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
///ensure no locked item are to be removed [should be protected, do not use]
|
|
|
|
template <class FUNCTOR> void flush(FUNCTOR functor) {
|
|
|
|
int count = 0;
|
2011-12-14 18:42:23 +01:00
|
|
|
mt::mutexlocker locker(&(this->heap_lock));
|
2011-03-11 17:14:54 +01:00
|
|
|
for(int k = 0; k < this->heap.size(); k++) {
|
|
|
|
Token *token = &this->heap[k];
|
|
|
|
if(functor(token)) { //drop it
|
|
|
|
token->count = Token::OUTSIDE;
|
|
|
|
} else
|
|
|
|
this->heap.at(count++) = token;
|
|
|
|
}
|
|
|
|
this->heap.resize(count);
|
|
|
|
this->heap_dirty = true;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2011-11-26 19:08:30 +01:00
|
|
|
#endif
|