ported to qt5.

This commit is contained in:
Federico Ponchio 2013-03-19 19:14:33 +00:00
parent 7a12add219
commit af0e5d65c3
2 changed files with 101 additions and 87 deletions

View File

@ -18,6 +18,9 @@ typedef unsigned __int64 uint64_t;
#include <limits.h> #include <limits.h>
#include <vector> #include <vector>
#include <list> #include <list>
#include "token.h"
#include <wrap/system/multithreading/mt.h> #include <wrap/system/multithreading/mt.h>
#include <wrap/system/multithreading/atomic_int.h> #include <wrap/system/multithreading/atomic_int.h>
@ -87,7 +90,7 @@ public:
Token *token = &(this->heap[i]); Token *token = &(this->heap[i]);
//tokens.push_back(token); //tokens.push_back(token);
s_curr -= drop(token); s_curr -= drop(token);
assert(!(token->count.load() >= Token::LOCKED)); //assert(!(token->count.load() >= Token::LOCKED));
if(final) if(final)
token->count.testAndSetOrdered(Token::READY, Token::CACHE); token->count.testAndSetOrdered(Token::READY, Token::CACHE);
input->heap.push(token); input->heap.push(token);
@ -112,7 +115,7 @@ public:
if(functor(token)) { //drop it if(functor(token)) { //drop it
tokens.push_back(token); tokens.push_back(token);
s_curr -= drop(token); s_curr -= drop(token);
assert(token->count.load() < Token::LOCKED); //assert(token->count.load() < Token::LOCKED);
if(final) if(final)
token->count.testAndSetOrdered(Token::READY, Token::CACHE); token->count.testAndSetOrdered(Token::READY, Token::CACHE);
} else } else
@ -140,25 +143,18 @@ protected:
virtual int drop(Token *token) = 0; virtual int drop(Token *token) = 0;
///make sure the get function do not access token after abort is returned. ///make sure the get function do not access token after abort is returned.
///called in as first thing in run()
virtual void begin() {}
virtual void middle() {} virtual void middle() {}
///called in as last thing in run()
virtual void end() {}
///[should be protected] ///[should be protected]
void run() { void run() {
assert(input); assert(input);
/* basic operation of the cache: /* basic operation of the cache:
1) transfer first element of input_cache if 1) make room until eliminating an element would leave empty space.
cache has room OR first element in input as higher priority of last element 2) transfer first element of input_cache if
2) make room until eliminating an element would leave space. */ cache has room OR first element in input has higher priority of last element */
begin();
while(!this->quit) { while(!this->quit) {
input->check_queue.enter(true); //wait for cache below to load something or priorities to change input->check_queue.enter(); //wait for cache below to load something or priorities to change
if(this->quit) break; if(this->quit) break;
middle(); middle();
@ -166,11 +162,11 @@ protected:
if(unload() || load()) { if(unload() || load()) {
new_data.testAndSetOrdered(0, 1); //if not changed, set as changed new_data.testAndSetOrdered(0, 1); //if not changed, set as changed
input->check_queue.open(); //we signal ourselves to check again input->check_queue.open(); //we signal ourselves to check again
cout << "loaded or unloaded\n";
} }
input->check_queue.leave(); input->check_queue.leave();
} }
this->quit = false; //in case someone wants to restart; this->quit = false; //in case someone wants to restart;
end();
} }
@ -198,7 +194,12 @@ protected:
remove = this->heap.popMin(); remove = this->heap.popMin();
} else { } else {
last.count.testAndSetOrdered(Token::READY, Token::CACHE); last.count.testAndSetOrdered(Token::READY, Token::CACHE);
if(last.count.load() <= Token::CACHE) { //was not locked and now can't be locked, remove it. #if(QT_VERSION < 0x05000000)
int last_count = last.count;
#else
int last_count = last.count.load();
#endif
if(last_count <= Token::CACHE) { //was not locked and now can't be locked, remove it.
remove = this->heap.popMin(); remove = this->heap.popMin();
} else { //last item is locked need to reorder stack } else { //last item is locked need to reorder stack
remove = this->heap.popMin(); remove = this->heap.popMin();
@ -245,7 +246,12 @@ protected:
input->rebuild(); //if dirty rebuild input->rebuild(); //if dirty rebuild
if(input->heap.size()) { //we need something in input to tranfer. if(input->heap.size()) { //we need something in input to tranfer.
Token &first = input->heap.max(); Token &first = input->heap.max();
if(first.count.load() > Token::REMOVE && #if(QT_VERSION < 0x05000000)
int first_count = first.count;
#else
int first_count = first.count.load();
#endif
if(first_count > Token::REMOVE &&
(!last || first.priority > last->priority)) { //if !last we already decided we want a transfer., otherwise check for a swap (!last || first.priority > last->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. insert = input->heap.popMax(); //remove item from heap, while we transfer it.
} }
@ -279,22 +285,5 @@ protected:
}; };
} //namespace } //namespace
/* TODO use the following class to allow multiple cache transfers at the same time */
/*
template<typename Token>
class Transfer: public mt::thread {
public:
Transfer(Cache<Token> *_cache): cache(_cache) {}
private:
Cache<Token> *cache;
void run() {
cache->loop();
//end();
}
};
*/
#endif // GCACHE_H #endif // GCACHE_H

View File

@ -19,7 +19,7 @@ namespace vcg {
template <typename Priority> template <typename Priority>
class Token { class Token {
public: public:
///Resource loading status ///Resource loading status
/*** - LOCKED: resource in the higher cache and locked /*** - LOCKED: resource in the higher cache and locked
- READY: resource in the higher cache - READY: resource in the higher cache
@ -35,23 +35,26 @@ class Token {
///swap space used in updatePriorities [do not use, should be private] ///swap space used in updatePriorities [do not use, should be private]
mt::atomicInt count; mt::atomicInt count;
public: public:
Token(): count(OUTSIDE) {} Token(): count(OUTSIDE) {}
///the new priority will be effective only after a call to Controller::updatePriorities() ///the new priority will be effective only after a call to Controller::updatePriorities()
void setPriority(const Priority &p) { void setPriority(const Priority &p) {
new_priority = p; new_priority = p;
} }
//set and get are safe to call in the controller thread. //set and get are safe to call in the controller thread.
Priority getPriority() { Priority getPriority() {
return new_priority; return new_priority;
} }
///return false if resource not in highest query. remember to unlock when done ///return false if resource not in highest query. remember to unlock when done
bool lock() { bool lock() {
if(count.fetchAndAddAcquire(1) >= 0) return true; if(count.fetchAndAddAcquire(1) >= 0) return true;
count.deref(); count.deref();
return false; return false;
} }
///assumes it was locked first and 1 unlock for each lock. ///assumes it was locked first and 1 unlock for each lock.
bool unlock() { bool unlock() {
return count.deref(); return count.deref();
@ -61,10 +64,20 @@ class Token {
bool remove() { bool remove() {
count.testAndSetOrdered(READY, REMOVE); count.testAndSetOrdered(READY, REMOVE);
count.testAndSetOrdered(CACHE, REMOVE); count.testAndSetOrdered(CACHE, REMOVE);
#if(QT_VERSION < 0x05000000)
return count <= REMOVE;
#else
return count.load() <= REMOVE; //might have become OUSIDE in the meanwhile return count.load() <= REMOVE; //might have become OUSIDE in the meanwhile
#endif
} }
bool isLocked() { return count.load() > 0; } bool isLocked() {
#if(QT_VERSION < 0x05000000)
return count > 0;
#else
return count.load() > 0;
#endif
}
bool isInCache() { return count != OUTSIDE; } //careful, can be used only when provider thread is locked. bool isInCache() { return count != OUTSIDE; } //careful, can be used only when provider thread is locked.
///copy priority to swap space [do not use, should be private] ///copy priority to swap space [do not use, should be private]
@ -73,14 +86,26 @@ class Token {
} }
bool operator<(const Token &a) const { bool operator<(const Token &a) const {
#if(QT_VERSION < 0x05000000)
if(count == a.count)
return priority < a.priority;
return count < a.count;
#else
if(count.load() == a.count.load()) if(count.load() == a.count.load())
return priority < a.priority; return priority < a.priority;
return count.load() < a.count.load(); return count.load() < a.count.load();
#endif
} }
bool operator>(const Token &a) const { bool operator>(const Token &a) const {
#if(QT_VERSION < 0x05000000)
if(count == a.count)
return priority > a.priority;
return count > a.count;
#else
if(count.load() == a.count.load()) if(count.load() == a.count.load())
return priority > a.priority; return priority > a.priority;
return count.load() > a.count.load(); return count.load() > a.count.load();
#endif
} }
}; };