ported to qt5.
This commit is contained in:
parent
7a12add219
commit
af0e5d65c3
|
@ -18,6 +18,9 @@ typedef unsigned __int64 uint64_t;
|
|||
#include <limits.h>
|
||||
#include <vector>
|
||||
#include <list>
|
||||
|
||||
#include "token.h"
|
||||
|
||||
#include <wrap/system/multithreading/mt.h>
|
||||
#include <wrap/system/multithreading/atomic_int.h>
|
||||
|
||||
|
@ -87,7 +90,7 @@ public:
|
|||
Token *token = &(this->heap[i]);
|
||||
//tokens.push_back(token);
|
||||
s_curr -= drop(token);
|
||||
assert(!(token->count.load() >= Token::LOCKED));
|
||||
//assert(!(token->count.load() >= Token::LOCKED));
|
||||
if(final)
|
||||
token->count.testAndSetOrdered(Token::READY, Token::CACHE);
|
||||
input->heap.push(token);
|
||||
|
@ -112,7 +115,7 @@ public:
|
|||
if(functor(token)) { //drop it
|
||||
tokens.push_back(token);
|
||||
s_curr -= drop(token);
|
||||
assert(token->count.load() < Token::LOCKED);
|
||||
//assert(token->count.load() < Token::LOCKED);
|
||||
if(final)
|
||||
token->count.testAndSetOrdered(Token::READY, Token::CACHE);
|
||||
} else
|
||||
|
@ -140,25 +143,18 @@ protected:
|
|||
virtual int drop(Token *token) = 0;
|
||||
///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() {}
|
||||
///called in as last thing in run()
|
||||
virtual void end() {}
|
||||
|
||||
///[should be protected]
|
||||
void run() {
|
||||
assert(input);
|
||||
/* basic operation of the cache:
|
||||
1) transfer first element of input_cache if
|
||||
cache has room OR first element in input as higher priority of last element
|
||||
2) make room until eliminating an element would leave space. */
|
||||
begin();
|
||||
1) make room until eliminating an element would leave empty space.
|
||||
2) transfer first element of input_cache if
|
||||
cache has room OR first element in input has higher priority of last element */
|
||||
|
||||
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;
|
||||
|
||||
middle();
|
||||
|
@ -166,11 +162,11 @@ protected:
|
|||
if(unload() || load()) {
|
||||
new_data.testAndSetOrdered(0, 1); //if not changed, set as changed
|
||||
input->check_queue.open(); //we signal ourselves to check again
|
||||
cout << "loaded or unloaded\n";
|
||||
}
|
||||
input->check_queue.leave();
|
||||
}
|
||||
this->quit = false; //in case someone wants to restart;
|
||||
end();
|
||||
}
|
||||
|
||||
|
||||
|
@ -198,7 +194,12 @@ protected:
|
|||
remove = this->heap.popMin();
|
||||
} else {
|
||||
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();
|
||||
} else { //last item is locked need to reorder stack
|
||||
remove = this->heap.popMin();
|
||||
|
@ -245,7 +246,12 @@ protected:
|
|||
input->rebuild(); //if dirty rebuild
|
||||
if(input->heap.size()) { //we need something in input to tranfer.
|
||||
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
|
||||
insert = input->heap.popMax(); //remove item from heap, while we transfer it.
|
||||
}
|
||||
|
@ -279,22 +285,5 @@ protected:
|
|||
};
|
||||
|
||||
} //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
|
||||
|
|
|
@ -19,69 +19,94 @@ namespace vcg {
|
|||
|
||||
template <typename Priority>
|
||||
class Token {
|
||||
public:
|
||||
///Resource loading status
|
||||
/*** - LOCKED: resource in the higher cache and locked
|
||||
public:
|
||||
///Resource loading status
|
||||
/*** - LOCKED: resource in the higher cache and locked
|
||||
- READY: resource in the higher cache
|
||||
- CACHE: resource in some cache (not the highest)
|
||||
- REMOVE: resource in some cache and scheduled for removal
|
||||
- OUTSIDE: resource not in the cache system */
|
||||
enum Status { LOCKED = 1, READY = 0, CACHE = -1, REMOVE = -2, OUTSIDE = -3 };
|
||||
///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]
|
||||
Priority priority;
|
||||
///set in the main thread [do not use, should be private]
|
||||
Priority new_priority;
|
||||
///swap space used in updatePriorities [do not use, should be private]
|
||||
mt::atomicInt count;
|
||||
enum Status { LOCKED = 1, READY = 0, CACHE = -1, REMOVE = -2, OUTSIDE = -3 };
|
||||
///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]
|
||||
Priority priority;
|
||||
///set in the main thread [do not use, should be private]
|
||||
Priority new_priority;
|
||||
///swap space used in updatePriorities [do not use, should be private]
|
||||
mt::atomicInt count;
|
||||
|
||||
public:
|
||||
Token(): count(OUTSIDE) {}
|
||||
public:
|
||||
Token(): count(OUTSIDE) {}
|
||||
|
||||
///the new priority will be effective only after a call to Controller::updatePriorities()
|
||||
void setPriority(const 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();
|
||||
}
|
||||
///the new priority will be effective only after a call to Controller::updatePriorities()
|
||||
void setPriority(const Priority &p) {
|
||||
new_priority = p;
|
||||
}
|
||||
|
||||
///can't be removed if locked and will return false
|
||||
bool remove() {
|
||||
count.testAndSetOrdered(READY, REMOVE);
|
||||
count.testAndSetOrdered(CACHE, REMOVE);
|
||||
return count.load() <= REMOVE; //might have become OUSIDE in the meanwhile
|
||||
}
|
||||
//set and get are safe to call in the controller thread.
|
||||
Priority getPriority() {
|
||||
return new_priority;
|
||||
}
|
||||
|
||||
bool isLocked() { return count.load() > 0; }
|
||||
bool isInCache() { return count != OUTSIDE; } //careful, can be used only when provider thread is locked.
|
||||
///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;
|
||||
}
|
||||
|
||||
///copy priority to swap space [do not use, should be private]
|
||||
void pushPriority() {
|
||||
priority = new_priority;
|
||||
}
|
||||
///assumes it was locked first and 1 unlock for each lock.
|
||||
bool unlock() {
|
||||
return count.deref();
|
||||
}
|
||||
|
||||
bool operator<(const Token &a) const {
|
||||
if(count.load() == a.count.load())
|
||||
return priority < a.priority;
|
||||
return count.load() < a.count.load();
|
||||
}
|
||||
bool operator>(const Token &a) const {
|
||||
if(count.load() == a.count.load())
|
||||
return priority > a.priority;
|
||||
return count.load() > a.count.load();
|
||||
}
|
||||
///can't be removed if locked and will return false
|
||||
bool remove() {
|
||||
count.testAndSetOrdered(READY, REMOVE);
|
||||
count.testAndSetOrdered(CACHE, REMOVE);
|
||||
#if(QT_VERSION < 0x05000000)
|
||||
return count <= REMOVE;
|
||||
#else
|
||||
return count.load() <= REMOVE; //might have become OUSIDE in the meanwhile
|
||||
#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
|
||||
|
|
Loading…
Reference in New Issue