fixed changed and some docs
This commit is contained in:
parent
059152baba
commit
42208fe186
|
@ -4,6 +4,7 @@
|
|||
#include <iostream>
|
||||
#include <limits.h>
|
||||
#include <vector>
|
||||
#include <list>
|
||||
|
||||
#include <QThread>
|
||||
#include "provider.h"
|
||||
|
@ -21,20 +22,24 @@ using namespace std;
|
|||
template <typename Token>
|
||||
class Cache: public Provider<Token> {
|
||||
|
||||
public:
|
||||
bool final; //true if this is the last cache (the one we use the data from)
|
||||
bool quit; //graceful exit
|
||||
bool changed;
|
||||
public:
|
||||
///true if this is the last cache (the one we use the data from)
|
||||
bool final;
|
||||
//if true the cache will exit at the first opportunity
|
||||
bool quit;
|
||||
///keeps track of changes (if 1 then something was loaded or dropped
|
||||
QAtomicInt changed;
|
||||
|
||||
///data is fetched from here
|
||||
Provider<Token> *input;
|
||||
Provider<Token> *input;
|
||||
|
||||
protected:
|
||||
protected:
|
||||
///max space available
|
||||
quint64 s_max;
|
||||
quint64 s_max;
|
||||
///current space used
|
||||
quint64 s_curr;
|
||||
quint64 s_curr;
|
||||
|
||||
public:
|
||||
public:
|
||||
Cache(quint64 _capacity = INT_MAX):
|
||||
final(false), quit(false), changed(false), input(NULL), s_max(_capacity), s_curr(0) {}
|
||||
virtual ~Cache() {}
|
||||
|
@ -43,15 +48,15 @@ class Cache: public Provider<Token> {
|
|||
quint64 capacity() { return s_max; }
|
||||
quint64 size() { return s_curr; }
|
||||
void setCapacity(quint64 c) { s_max = c; }
|
||||
|
||||
///return true if the cache is waiting for priority to change
|
||||
bool isChanged() {
|
||||
bool r = changed;
|
||||
changed = false;
|
||||
bool r = changed.testAndSetOrdered(1, 0); //if changed is 1, r is true
|
||||
return r;
|
||||
//return input->check_queue.isWaiting();
|
||||
}
|
||||
|
||||
///empty the cache. Make sure no resource is locked before calling this. Require pause or stop before.
|
||||
///empty the cache. Make sure no resource is locked before calling this.
|
||||
/// Require pause or stop before. Ensure there no locked item
|
||||
void flush() {
|
||||
std::vector<Token *> tokens;
|
||||
{
|
||||
|
@ -78,7 +83,8 @@ class Cache: public Provider<Token> {
|
|||
}
|
||||
}
|
||||
|
||||
///ensure there no locked item
|
||||
///empty the cache. Make sure no resource is locked before calling this.
|
||||
/// Require pause or stop before. Ensure there no locked item
|
||||
template <class FUNCTOR> void flush(FUNCTOR functor) {
|
||||
std::vector<Token *> tokens;
|
||||
{
|
||||
|
@ -106,15 +112,15 @@ class Cache: public Provider<Token> {
|
|||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
protected:
|
||||
///return the space used in the cache by the loaded resource
|
||||
virtual int size(Token *token) = 0;
|
||||
///returns amount of space used in cache -1 for failed transfer
|
||||
virtual int get(Token *token) = 0;
|
||||
///return amount removed
|
||||
virtual int drop(Token *token) = 0;
|
||||
///
|
||||
virtual Token *ready() { return NULL; }
|
||||
|
||||
|
||||
|
||||
///called in as first thing in run()
|
||||
virtual void begin() {}
|
||||
|
@ -135,7 +141,7 @@ class Cache: public Provider<Token> {
|
|||
if(this->quit) break;
|
||||
|
||||
if(unload() || load()) {
|
||||
changed = true; //some modification happened
|
||||
changed.testAndSetOrdered(0, 1); //if not changed, set as changed
|
||||
input->check_queue.open(); //we signal ourselves to check again
|
||||
}
|
||||
}
|
||||
|
@ -146,7 +152,9 @@ class Cache: public Provider<Token> {
|
|||
|
||||
|
||||
|
||||
///should be protected
|
||||
/** Checks wether we need to make room in the cache because of:
|
||||
size() - sizeof(lowest priority item) > capacity()
|
||||
**/
|
||||
bool unload() {
|
||||
Token *remove = NULL;
|
||||
//make room int the cache checking that:
|
||||
|
@ -181,18 +189,18 @@ class Cache: public Provider<Token> {
|
|||
}
|
||||
|
||||
if(remove) {
|
||||
int size = drop(remove);
|
||||
assert(size >= 0);
|
||||
s_curr -= size;
|
||||
|
||||
{
|
||||
QMutexLocker input_locker(&(input->heap_lock));
|
||||
int size = drop(remove);
|
||||
assert(size >= 0);
|
||||
s_curr -= size;
|
||||
input->heap.push(remove);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
///should be protected
|
||||
bool load() {
|
||||
Token *insert = NULL;
|
||||
|
@ -215,7 +223,7 @@ class Cache: public Provider<Token> {
|
|||
if(input->heap.size()) { //we need something in input to tranfer.
|
||||
Token &first = input->heap.max();
|
||||
if(first.count > Token::REMOVE &&
|
||||
(!last || last->priority < first.priority)) { //if !last we already decided we want a transfer., otherwise check for a swap
|
||||
(!last || last->priority < first.priority)) { //if !last we already decided we want a transfer., otherwise check for a swap
|
||||
insert = input->heap.popMax(); //remove item from heap, while we transfer it.
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,10 +10,12 @@
|
|||
template <class Token>
|
||||
class Controller {
|
||||
public:
|
||||
///should be private
|
||||
std::vector<Token *> tokens; //tokens waiting to be added
|
||||
bool quit; //gracefully terminate.
|
||||
///tokens waiting to be added, should be private
|
||||
std::vector<Token *> tokens;
|
||||
/// threads still running, but no door is open in caches,
|
||||
///transfers might still be going on!
|
||||
bool paused;
|
||||
///all cache threads are stopped
|
||||
bool stopped;
|
||||
|
||||
public:
|
||||
|
@ -22,11 +24,11 @@ class Controller {
|
|||
///should be protected
|
||||
std::vector<Cache<Token> *> caches;
|
||||
|
||||
Controller(): quit(false), paused(false), stopped(true) {}
|
||||
Controller(): paused(false), stopped(true) {}
|
||||
~Controller() { finish(); }
|
||||
|
||||
///called before the cache is started to add a cache in the chain
|
||||
/** The order in which the caches are added is from the lowest to the highest. */
|
||||
/** The order in which the caches are added is from the lowest to the highest. */
|
||||
void addCache(Cache<Token> *cache) {
|
||||
if(caches.size() == 0)
|
||||
cache->setInputCache(&provider);
|
||||
|
@ -35,6 +37,7 @@ class Controller {
|
|||
assert(cache->input);
|
||||
caches.push_back(cache);
|
||||
}
|
||||
|
||||
///insert the token in the cache if not already present (actual insertion is done on updatePriorities)
|
||||
bool addToken(Token *token) {
|
||||
if(token->count.testAndSetOrdered(Token::OUTSIDE, Token::CACHE)) {
|
||||
|
@ -110,8 +113,9 @@ class Controller {
|
|||
void pause() {
|
||||
if(paused) return;
|
||||
provider.check_queue.lock();
|
||||
for(unsigned int i = 0; i < caches.size()-1; i++)
|
||||
for(unsigned int i = 0; i < caches.size()-1; i++) {
|
||||
caches[i]->check_queue.lock();
|
||||
}
|
||||
/* provider.heap_lock.lock();
|
||||
for(unsigned int i = 0; i < caches.size(); i++)
|
||||
caches[i]->heap_lock.lock(); */
|
||||
|
@ -131,11 +135,13 @@ class Controller {
|
|||
}
|
||||
///empty all caches AND REMOVES ALL TOKENS!
|
||||
void flush() {
|
||||
pause();
|
||||
bool running = !stopped;
|
||||
stop();
|
||||
for(int i = (int)caches.size()-1; i >= 0; i--)
|
||||
caches[i]->flush();
|
||||
provider.heap.clear();
|
||||
resume();
|
||||
if(running)
|
||||
start();
|
||||
}
|
||||
bool isChanged() {
|
||||
bool c = false;
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
* *
|
||||
* All rights reserved. *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
|
@ -42,6 +42,7 @@ class QDoor {
|
|||
QSemaphore _close;
|
||||
public:
|
||||
QDoor(): _open(0), _close(1) {} //this means closed
|
||||
|
||||
void open() {
|
||||
if(_close.tryAcquire(1)) //check it is not open
|
||||
_open.release(1); //open
|
||||
|
@ -53,21 +54,23 @@ class QDoor {
|
|||
void enter(bool close = false) {
|
||||
_open.acquire(1);
|
||||
if(close)
|
||||
_close.release(1); //and close door behind
|
||||
_close.release(1); //close door behind
|
||||
else
|
||||
_open.release(1); //and leave door opened
|
||||
|
||||
_open.release(1); //leave door opened
|
||||
}
|
||||
bool isOpen() { return _open.available() == 1; }
|
||||
|
||||
void lock() {
|
||||
//door might be open or closed, but we might happen just in the middle
|
||||
//of someone opening, closing or entering it.
|
||||
while(!_open.tryAcquire(1) && !_close.tryAcquire(1)) {}
|
||||
//no resources left
|
||||
//no resources left, door is locked
|
||||
}
|
||||
void unlock() {
|
||||
//unlock will not open the door, but allow someone to open it.
|
||||
_close.release(1);
|
||||
void unlock(bool open = false) {
|
||||
if(open)
|
||||
_open.release(1)
|
||||
else
|
||||
_close.release(1);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -96,15 +99,15 @@ class QDoor {
|
|||
}
|
||||
|
||||
///attempt to enter the door. if the door is closed the thread will wait until the door is opened.
|
||||
/** if close is true, the door will be closed after the thread is awakened, this allows to
|
||||
/** if close is true, the door will be closed after the thread is awakened, this allows to
|
||||
have only one thread entering the door each time open() is called */
|
||||
void enter(bool close = false) {
|
||||
m.lock();
|
||||
waiting = true;
|
||||
while (!doorOpen)
|
||||
c.wait(&(m));
|
||||
|
||||
if(close)
|
||||
|
||||
if(close)
|
||||
doorOpen = false;
|
||||
waiting = false;
|
||||
m.unlock();
|
||||
|
@ -118,7 +121,8 @@ class QDoor {
|
|||
void lock() { //prevend door opening and entering
|
||||
m.lock();
|
||||
}
|
||||
void unlock() { //reverse effect of lock
|
||||
void unlock(bool open = false) { //reverse effect of lock
|
||||
doorOpen = open;
|
||||
m.unlock();
|
||||
}
|
||||
private:
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
2) set maximum number of tokens in the provider
|
||||
*/
|
||||
|
||||
/** Base class for Cache and last cache in the GCache system.
|
||||
/** Base class for Cache and last cache in the GCache system.
|
||||
You should never interact with this class.
|
||||
*/
|
||||
|
||||
|
@ -22,17 +22,17 @@ template <typename Token>
|
|||
class Provider: public QThread {
|
||||
public:
|
||||
///holds the resources in this cache but not in the cache above
|
||||
PtrDHeap<Token> heap;
|
||||
PtrDHeap<Token> heap;
|
||||
///tokens above this number will be scheduled for deletion
|
||||
int max_tokens;
|
||||
///signals we need to rebuild heap.
|
||||
bool heap_dirty;
|
||||
///lock this before manipulating heap.
|
||||
QMutex heap_lock;
|
||||
///used to sincronize priorities update
|
||||
QMutex priority_lock;
|
||||
bool heap_dirty;
|
||||
///lock this before manipulating heap.
|
||||
QMutex heap_lock;
|
||||
///used to sincronize priorities update
|
||||
QMutex priority_lock;
|
||||
///signals (to next cache!) priorities have changed or something is available
|
||||
QDoor check_queue;
|
||||
QDoor check_queue;
|
||||
|
||||
Provider(): max_tokens(-1), heap_dirty(false) {}
|
||||
virtual ~Provider() {}
|
||||
|
@ -84,4 +84,4 @@ class Provider: public QThread {
|
|||
};
|
||||
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue