hopefully fixed race condition updating priorities

This commit is contained in:
Federico Ponchio 2011-12-20 18:25:13 +00:00
parent b853e5fd3f
commit 17fbc7d1ca
4 changed files with 12 additions and 21 deletions

View File

@ -169,6 +169,7 @@ protected:
mt::mutexlocker locker(&(this->heap_lock)); mt::mutexlocker locker(&(this->heap_lock));
//2 we have some element not in the upper caches (heap.size() > 0 //2 we have some element not in the upper caches (heap.size() > 0
assert(this->heap.size());
if(this->heap.size()) { if(this->heap.size()) {
Token &last = this->heap.min(); Token &last = this->heap.min();
int itemsize = size(&last); int itemsize = size(&last);
@ -228,7 +229,7 @@ protected:
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 > Token::REMOVE && 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 || 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.
} }
} }

View File

@ -64,6 +64,7 @@ class Controller {
} }
///ensure that added tokens are processed and existing ones have their priority updated. ///ensure that added tokens are processed and existing ones have their priority updated.
///potential bug! update is done on the heaps, if something is in transit...
void updatePriorities() { void updatePriorities() {
if(tokens.size()) { if(tokens.size()) {

View File

@ -28,19 +28,18 @@ class Provider: public mt::thread {
bool heap_dirty; bool heap_dirty;
///lock this before manipulating heap. ///lock this before manipulating heap.
mt::mutex heap_lock; mt::mutex heap_lock;
///used to sincronize priorities update
mt::mutex priority_lock;
///signals (to next cache!) priorities have changed or something is available ///signals (to next cache!) priorities have changed or something is available
QDoor check_queue; QDoor check_queue;
Provider(): max_tokens(-1), heap_dirty(false) {} Provider(): max_tokens(-1), heap_dirty(false) {}
virtual ~Provider() {} virtual ~Provider() {}
/// [should be protected, do not use] /// [should be protected, do not use] called in controller thread!
void pushPriorities() { void pushPriorities() {
mt::mutexlocker locker(&priority_lock); mt::mutexlocker locker(&heap_lock);
for(int i = 0; i < heap.size(); i++) for(int i = 0; i < heap.size(); i++)
heap[i].pushPriority(); heap[i].pushPriority();
heap_dirty = true; heap_dirty = true;
check_queue.open(); check_queue.open();
} }
@ -48,13 +47,8 @@ class Provider: public mt::thread {
void rebuild() { void rebuild() {
if(!this->heap_dirty) return; if(!this->heap_dirty) return;
{
mt::mutexlocker locker(&priority_lock);
for(int i = 0; i < this->heap.size(); i++)
this->heap[i].pullPriority();
this->heap_dirty = false;
}
this->heap.rebuild(); this->heap.rebuild();
this->heap_dirty = false;
//remove OUTSIDE tokens from bottom of heap //remove OUTSIDE tokens from bottom of heap
if(max_tokens != -1) { if(max_tokens != -1) {

View File

@ -28,12 +28,10 @@ class Token {
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]
Priority tmp_priority;
///reference count of locked items [do not use, should be private]
mt::atomicInt count; mt::atomicInt count;
public: public:
@ -43,6 +41,7 @@ class Token {
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() { Priority getPriority() {
return new_priority; return new_priority;
} }
@ -53,7 +52,7 @@ class Token {
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();
} }
@ -69,11 +68,7 @@ class Token {
///copy priority to swap space [do not use, should be private] ///copy priority to swap space [do not use, should be private]
void pushPriority() { void pushPriority() {
tmp_priority = new_priority; priority = new_priority;
}
///copy priority from swap space [do not use, should be private]
void pullPriority() {
priority = tmp_priority;
} }
bool operator<(const Token &a) const { bool operator<(const Token &a) const {