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,69 +19,94 @@ 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
- CACHE: resource in some cache (not the highest) - CACHE: resource in some cache (not the highest)
- REMOVE: resource in some cache and scheduled for removal - REMOVE: resource in some cache and scheduled for removal
- OUTSIDE: resource not in the cache system */ - OUTSIDE: resource not in the cache system */
enum Status { LOCKED = 1, READY = 0, CACHE = -1, REMOVE = -2, OUTSIDE = -3 }; enum Status { LOCKED = 1, READY = 0, CACHE = -1, REMOVE = -2, OUTSIDE = -3 };
///Do not access these members directly. Will be moved to private shortly. ///Do not access these members directly. Will be moved to private shortly.
///used by various cache threads to sort objects [do not use, should be private] ///used by various cache threads to sort objects [do not use, should be private]
Priority priority; Priority priority;
///set in the main thread [do not use, should be private] ///set in the main thread [do not use, should be private]
Priority new_priority; Priority new_priority;
///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.
Priority getPriority() {
return new_priority;
}
///return false if resource not in highest query. remember to unlock when done
bool lock() {
if(count.fetchAndAddAcquire(1) >= 0) return true;
count.deref();
return false;
}
///assumes it was locked first and 1 unlock for each lock.
bool unlock() {
return count.deref();
}
///can't be removed if locked and will return false //set and get are safe to call in the controller thread.
bool remove() { Priority getPriority() {
count.testAndSetOrdered(READY, REMOVE); return new_priority;
count.testAndSetOrdered(CACHE, REMOVE); }
return count.load() <= REMOVE; //might have become OUSIDE in the meanwhile
}
bool isLocked() { return count.load() > 0; } ///return false if resource not in highest query. remember to unlock when done
bool isInCache() { return count != OUTSIDE; } //careful, can be used only when provider thread is locked. bool lock() {
if(count.fetchAndAddAcquire(1) >= 0) return true;
count.deref();
return false;
}
///copy priority to swap space [do not use, should be private] ///assumes it was locked first and 1 unlock for each lock.
void pushPriority() { bool unlock() {
priority = new_priority; return count.deref();
} }
bool operator<(const Token &a) const { ///can't be removed if locked and will return false
if(count.load() == a.count.load()) bool remove() {
return priority < a.priority; count.testAndSetOrdered(READY, REMOVE);
return count.load() < a.count.load(); count.testAndSetOrdered(CACHE, REMOVE);
} #if(QT_VERSION < 0x05000000)
bool operator>(const Token &a) const { return count <= REMOVE;
if(count.load() == a.count.load()) #else
return priority > a.priority; return count.load() <= REMOVE; //might have become OUSIDE in the meanwhile
return count.load() > a.count.load(); #endif
} }
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.
///copy priority to swap space [do not use, should be private]
void pushPriority() {
priority = new_priority;
}
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())
return priority < a.priority;
return count.load() < a.count.load();
#endif
}
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())
return priority > a.priority;
return count.load() > a.count.load();
#endif
}
}; };
} //namespace } //namespace