fixed changed and some docs

This commit is contained in:
Federico Ponchio 2011-11-26 18:08:30 +00:00
parent 059152baba
commit 42208fe186
4 changed files with 71 additions and 53 deletions

View File

@ -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.
}
}

View File

@ -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;

View File

@ -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:

View File

@ -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