moved from sandbox

This commit is contained in:
Federico Ponchio 2011-03-11 16:14:54 +00:00
parent 127caef1a6
commit f206cd649d
16 changed files with 5861 additions and 0 deletions

240
wrap/gcache/cache.h Normal file
View File

@ -0,0 +1,240 @@
#ifndef GCACHE_CACHE_H
#define GCACHE_CACHE_H
#include <limits.h>
#include <vector>
#include <QThread>
#include "provider.h"
/* this cache system enforce the rule that the items in a cache are always in all the cache below */
/* two mechanism to remove tokens from the cache:
1) set token count to something low
2) set maximum number of tokens in the provider
*/
/** Cache virtual base class. You are required to implement the pure virtual functions get, drop and size.
*/
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 waiting;
///data is fetched from here
Provider<Token> *input;
protected:
///max space available
quint64 s_max;
///current space used
quint64 s_curr;
public:
Cache(quint64 _capacity = INT_MAX):
final(false), quit(false), waiting(false), input(NULL), s_max(_capacity), s_curr(0) {}
virtual ~Cache() {}
void setInputCache(Provider<Token> *p) { input = p; }
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 isWaiting() { return waiting; }
///empty the cache. Make sure no resource is locked before calling this.
void flush() {
std::vector<Token *> tokens;
{
QMutexLocker locker(&(this->heap_lock));
for(int i = 0; i < this->heap.size(); i++) {
Token *token = &(this->heap[i]);
tokens.push_back(token);
s_curr -= drop(token);
assert(!(token->count >= Token::LOCKED));
if(final)
token->count.testAndSetOrdered(Token::READY, Token::CACHE);
}
this->heap.clear();
}
assert(s_curr == 0);
{
QMutexLocker locker(&(input->heap_lock));
for(unsigned int i = 0; i < tokens.size(); i++) {
input->heap.push(tokens[i]);
}
}
}
///ensure there no locked item
template <class FUNCTOR> void flush(FUNCTOR functor) {
std::vector<Token *> tokens;
{
int count = 0;
QMutexLocker locker(&(this->heap_lock));
for(int k = 0; k < this->heap.size(); k++) {
Token *token = &this->heap[k];
if(functor(token)) { //drop it
tokens.push_back(token);
s_curr -= drop(token);
assert(!token->count >= Token::LOCKED);
if(final)
token->count.testAndSetOrdered(Token::READY, Token::CACHE);
} else
this->heap.at(count++) = token;
}
this->heap.resize(count);
this->heap_dirty = true;
}
{
QMutexLocker locker(&(input->heap_lock));
for(unsigned int i = 0; i < tokens.size(); i++) {
input->heap.push(tokens[i]);
}
}
}
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;
///called in as first thing in run()
virtual void begin() {}
///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();
while(!this->quit) {
waiting = true;
input->check_queue.enter(true); //wait for cache below to load someghing or priorities to change
waiting = false;
if(this->quit) break;
if(unload() || load())
input->check_queue.open(); //we signal ourselves to check again
}
flush();
this->quit = false; //in case someone wants to restart;
end();
}
///should be protected
bool unload() {
Token *remove = NULL;
//make room int the cache checking that:
//1 we need to make room (capacity < current)
if(size() > capacity()) {
QMutexLocker locker(&(this->heap_lock));
//2 we have some element not in the upper caches (heap.size() > 0
if(this->heap.size()) {
Token &last = this->heap.min();
int itemsize = size(&last);
//3 after removing the item, we are still full (avoids bouncing items)
if(size() - itemsize > capacity()) {
//4 item to remove is not locked. (only in last cache. you can't lock object otherwise)
if(!final) { //not final we can drop when we want
remove = this->heap.popMin();
} else {
last.count.testAndSetOrdered(Token::READY, Token::CACHE);
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();
this->heap.push(remove);
return true;
}
}
}
}
}
if(remove) {
int size = drop(remove);
assert(size >= 0);
s_curr -= size;
{
QMutexLocker input_locker(&(input->heap_lock));
input->heap.push(remove);
}
return true;
}
return false;
}
///should be protected
bool load() {
Token *insert = NULL;
Token *last = NULL; //we want to lock only one heap at once to avoid deadlocks.
/* check wether we have room (curr < capacity) or heap is empty.
empty heap is bad: we cannot drop anything to make room, and cache above has nothing to get.
this should not happen if we set correct cache sizes, but if it happens.... */
{
QMutexLocker locker(&(this->heap_lock));
this->rebuild();
if(size() > capacity() && this->heap.size() > 0) {
last = &(this->heap.min()); //no room, set last so we might check for a swap.
}
}
{
QMutexLocker input_locker(&(input->heap_lock));
input->rebuild(); //if dirty rebuild
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
insert = input->heap.popMax(); //remove item from heap, while we transfer it.
}
}
}
if(insert) { //we want to fetch something
int size = get(insert);
if(size >= 0) { //success
s_curr += size;
{
QMutexLocker locker(&(this->heap_lock));
if(final)
insert->count.ref(); //now lock is 0 and can be locked
this->heap.push(insert);
}
this->check_queue.open(); //we should signal the parent cache that we have a new item
return true;
} else { //failed transfer put it back, we will keep trying to transfer it...
QMutexLocker input_locker(&(input->heap_lock));
input->heap.push(insert);
return false;
}
}
return false;
}
};
#endif // GCACHE_H

131
wrap/gcache/controller.h Normal file
View File

@ -0,0 +1,131 @@
#ifndef GCACHE_CONTROLLER_H
#define GCACHE_CONTROLLER_H
#include "cache.h"
/** Allows to insert tokens, update priorities and generally control the cache.
*/
template <class Token>
class Controller {
public:
///should be private
std::vector<Token *> tokens; //tokens waiting to be added
bool quit; //gracefully terminate.
bool paused;
bool stopped;
public:
///should be protected
Provider<Token> provider;
///should be protected
std::vector<Cache<Token> *> caches;
Controller(): quit(false), 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. */
void addCache(Cache<Token> *cache) {
if(caches.size() == 0)
cache->setInputCache(&provider);
else
cache->setInputCache(caches.back());
assert(cache->input);
caches.push_back(cache);
}
///insert a token in the last provider (actual insertion is done on updatePriorities)
void addToken(Token *token) {
token->count = Token::CACHE;
tokens.push_back(token);
}
///WARNING: migh stall for the time needed to drop tokens from cache.
//FUNCTOR has bool operator(Token *) and return true to remove
template<class FUNCTOR> void removeTokens(FUNCTOR functor) {
stop();
std::vector<Token *> tmp;
for(quint32 i = 0; i < caches.size(); i++)
caches[i]->flush(functor);
provider.flush(functor);
start();
}
///if more tokens than m present in the provider, lowest priority ones will be removed
void setMaxTokens(int m) {
QMutexLocker l(&provider.heap_lock);
provider.max_tokens = m;
}
///ensure that added tokens are processed and existing ones have their priority updated.
void updatePriorities() {
if(tokens.size()) {
QMutexLocker l(&provider.heap_lock);
for(unsigned int i = 0; i < tokens.size(); i++)
provider.heap.push(tokens[i]);
tokens.clear();
}
provider.pushPriorities();
for(unsigned int i = 0; i < caches.size(); i++)
caches[i]->pushPriorities();
}
///start the various cache threads.
void start() {
if(!stopped) return;
assert(!paused);
assert(caches.size() > 1);
caches.back()->final = true;
for(unsigned int i = 0; i < caches.size(); i++) //cache 0 is a provider, and his thread is not running.
caches[i]->start();
stopped = false;
}
///stops the ache threads
void stop() {
if(stopped) return;
if(paused) resume();
//stop threads
for(int i = caches.size()-1; i >= 0; i--) {
caches[i]->quit = true; //hmmmmmmmmmmmmmm not very clean.
if(i == 0)
provider.check_queue.open();
else
caches[i-1]->check_queue.open(); //cache i listens on queue i-1
caches[i]->wait();
}
stopped = true;
}
void finish() {
stop();
}
void pause() {
if(paused) return;
provider.heap_lock.lock();
for(unsigned int i = 0; i < caches.size(); i++)
caches[i]->heap_lock.lock();
paused = true;
}
void resume() {
if(!paused) return;
provider.heap_lock.unlock();
for(unsigned int i = 0; i < caches.size(); i++)
caches[i]->heap_lock.unlock();
paused = false;
}
///empty all caches
void flush() {
for(unsigned int i = caches.size()-1; i >= 0; i--)
caches[i]->flush();
}
};
#endif // CONTROLLER_H

274
wrap/gcache/dheap.h Normal file
View File

@ -0,0 +1,274 @@
/****************************************************************************
* GCache *
* Author: Federico Ponchio *
* *
* Copyright(C) 2011 *
* Visual Computing Lab *
* ISTI - Italian National Research Council *
* *
* All rights reserved. *
* *
* 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. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License (http://www.gnu.org/licenses/gpl.txt) *
* for more details. *
* *
****************************************************************************/
#ifndef DD_HEAP_H
#define DD_HEAP_H
/**
Double ended heap inspired by
Min-Max Heaps and Generalized Priority Queues
M. D. ATKINSON,J.-R. SACK, N. SANTORO,and T. STROTHOTTE
This structure allows for quick extraction of biggest and smaller item out of a set
with linear reconstruction of the ordering.
DHeap exposes the public interface of vector. (push_back(), resize() etc.).
Compared to a stl heap, rebuild is 15% longer, extraction is 2x longer,
but you get both min and max extraction in log(n) time.
*/
#include <assert.h>
#include <vector>
template <class T>
class DHeap: public std::vector<T> {
public:
void push(const T& elt) {
push_back(elt);
bubbleUp(this->size()-1);
}
T &min() { return this->front(); } //root is smallest element
T popMin() {
T elt = this->front();
//move the last element to the root and
this->front() = this->back();
this->pop_back();
//enforce minmax heap property
trickleDownMin(0);
return elt;
}
//max is second element
T &max() {
if(this->size() == 1) return at(0);
return at(1);
}
T popMax() {
int p = 1;
if(this->size() == 1) p = 0;
T elt = at(p);
//max is replaced with last item.
at(p) = this->back();
this->pop_back();
trickleDownMax(p); //enforce minmax heap property
return elt;
}
//just reinsert all elements
void rebuild() {
for(unsigned int i = 0; i < this->size(); i++)
bubbleUp(i);
}
protected:
T &at(int n) { return std::vector<T>::at(n); }
int isMax(int e) const { return e & 1; }
int parentMin(int i) const { return (((i+2)>>2)<<1) - 2; }
int parentMax(int i) const { return (((i+2)>>2)<<1) - 1; }
int leftChildMin(int i) const { return (((i+2)>>1)<<2) -2; }
int leftChildMax(int i) const { return (((i+2)>>1)<<2) -1; }
void swap(int a, int b) { T tmp = at(a); at(a) = at(b); at(b) = tmp; }
//returns smallest elemennt of children intervals (or self if no children)
int smallestChild(int i) {
int l = leftChildMin(i);
if(l >= this->size()) return i; //no children, return self
int r = l+2; //right child
if(r < this->size() && at(r) < at(l))
return r;
return l;
}
//return biggest children or self if no children
int greatestChild(int i) {
int l = leftChildMax(i);
if(l >= this->size()) return i; //no children, return self
int r = l+2; //right child
if(r < this->size() && at(r) > at(l))
return r;
return l;
}
//all stuff involving swaps could be optimized perofming circular swaps
// but you mantain the code after :)
void trickleDownMin(int i) {
while(1) {
//find smallest child
unsigned int m = leftChildMin(i);
if(m >= this->size()) break;
unsigned int r = m+2;
if(r < this->size() && at(r) < at(m))
m = r;
if(at(m) < at(i)) { //if child is smaller swap
swap(i, m);
i = m; //check swapped children
} else //no swap? finish
break;
m = i+1; //enforce order in interval
if(m >= this->size()) break;
if(at(m) < at(i))
swap(i, m);
}
}
void trickleDownMax(int i) {
while(1) {
//find greatest child
unsigned int m = leftChildMax(i);
if(m >= this->size()) break;
unsigned int r = m+2;
if(r < this->size() && at(r) > at(m))
m = r;
if(at(m) > at(i)) {
swap(i, m);
i = m;
} else
break;
m = i-1; //enforce order in interval
if(m >= this->size()) break;
if(at(m) > at(i)) {
swap(i, m);
}
}
}
void bubbleUpMin(int i) {
while(1) {
int m = parentMin(i);
if(m < 0) break;
if(at(m) > at(i)) {
swap(i, m);
i = m;
} else
break;
}
}
void bubbleUpMax(int i) {
while(1) {
int m = parentMax(i);
if(m < 0) break;
if(at(m) < at(i)) {
swap(i, m);
i = m;
} else
break;
}
}
void bubbleUp(int i) {
if(isMax(i)) {
int m = i-1;
if(at(m) > at(i)) {
swap(i, m);
bubbleUpMin(m);
} else
bubbleUpMax(i);
} else {
int m = parentMax(i);
if(m < 0) return;
if(at(m) < at(i)) {
swap(i, m);
bubbleUpMax(m);
} else
bubbleUpMin(i);//just reinsert all elements, (no push back necessary, of course
}
}
/* DEBUG */
public:
///check the double heap conditions are met, mainly for debugging purpouses
bool isHeap() { //checks everything is in order
int s = this->size();
for(int i = 0; i < s; i += 2) {
if(i+1 < s && at(i) > at(i+1)) return false;
int l = leftChildMin(i);
if(l < s && at(i) > at(l)) return false;
int r = l + 2;
if(r < s && at(i) > at(r)) return false;
}
for(int i = 1; i < s; i += 2) {
int l = leftChildMax(i);
if(l < s && at(i) < at(l)) return false;
int r = l + 2;
if(r < s && at(i) < at(r)) return false;
}
return true;
}
};
/** Same functionality as IHeap, but storing pointers instead of the objects */
template <class T>
class PtrDHeap {
private:
class Item {
public:
T *value;
Item(T *val): value(val) {}
bool operator<(const Item &i) const { return *value < *i.value; }
bool operator>(const Item &i) const { return *value > *i.value; }
};
DHeap<Item> heap;
public:
T *push(T *t) {
Item i(t);
heap.push(i);
return i.value;
}
void push_back(T *t) {
heap.push_back(Item(t));
}
int size() { return heap.size(); }
void resize(int n) { assert(n < (int)heap.size()); return heap.resize(n, Item(NULL)); }
void clear() { heap.clear(); }
T &min() { Item &i = heap.min(); return *i.value; }
T *popMin() { Item i = heap.popMin(); return i.value; }
T &max() { Item &i = heap.max(); return *i.value; }
T *popMax() { Item i = heap.popMax(); return i.value; }
void rebuild() { heap.rebuild(); }
T &operator[](int i) {
return *(heap[i].value);
}
Item &at(int i) { return heap[i]; }
bool isHeap() { return heap.isHeap(); }
};
#endif

1600
wrap/gcache/docs/Doxyfile Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,16 @@
.str,.atv{color:#080}
.kwd,.tag{color:#008}
.com{color:#800}
.typ,.atn,.dec{color:#606}
.lit{color:#066}
.pun{color:#660}
.pln{color:#000}
pre.prettyprint{padding:2px;border:1px solid #888}
@media print{.str{color:#060}
.kwd,.tag{color:#006;font-weight:bold}
.com{color:#600;font-style:italic}
.typ{font-weight:bold}
.lit{color:#044}
.pun{color:#440}
.atn,.typ{color:#404}
.atv{color:#060}}

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

File diff suppressed because it is too large Load Diff

After

Width:  |  Height:  |  Size: 114 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.3 KiB

View File

@ -0,0 +1,458 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="744.09448819"
height="1052.3622047"
id="svg2"
version="1.1"
inkscape:version="0.47 r22583"
sodipodi:docname="New document 1">
<defs
id="defs4">
<inkscape:perspective
sodipodi:type="inkscape:persp3d"
inkscape:vp_x="0 : 526.18109 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_z="744.09448 : 526.18109 : 1"
inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
id="perspective10" />
<inkscape:perspective
id="perspective3624"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
<inkscape:perspective
id="perspective3669"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
<inkscape:perspective
id="perspective3726"
inkscape:persp3d-origin="0.5 : 0.33333333 : 1"
inkscape:vp_z="1 : 0.5 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_x="0 : 0.5 : 1"
sodipodi:type="inkscape:persp3d" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="0.98994949"
inkscape:cx="328.49695"
inkscape:cy="963.98253"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:object-paths="true"
inkscape:object-nodes="true"
inkscape:window-width="1366"
inkscape:window-height="739"
inkscape:window-x="0"
inkscape:window-y="1"
inkscape:window-maximized="1" />
<metadata
id="metadata7">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1">
<text
xml:space="preserve"
style="font-size:24px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:Arial;-inkscape-font-specification:Arial"
x="56.568542"
y="48.270554"
id="text2816"><tspan
sodipodi:role="line"
id="tspan2818"
x="56.568542"
y="48.270554" /></text>
<g
id="g3857">
<text
id="text3600"
y="84.636047"
x="309.30972"
style="font-size:18px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:Arial;-inkscape-font-specification:Arial;stroke-opacity:1"
xml:space="preserve"><tspan
y="84.636047"
x="309.30972"
id="tspan3602"
sodipodi:role="line">Capacity</tspan></text>
<text
id="text3604"
y="84.636047"
x="235.36554"
style="font-size:18px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:Arial;-inkscape-font-specification:Arial;stroke-opacity:1"
xml:space="preserve"><tspan
y="84.636047"
x="235.36554"
id="tspan3606"
sodipodi:role="line">Size</tspan></text>
<path
id="path3608"
d="m 254.55844,105.84925 0,-17.772785"
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
<path
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
d="m 348.50269,105.84925 0,-17.772783"
id="path3610" />
<text
id="text3612"
y="123.36304"
x="419.70758"
style="font-size:18px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:Arial;-inkscape-font-specification:Arial"
xml:space="preserve"><tspan
y="123.36304"
x="419.70758"
id="tspan3614"
sodipodi:role="line">Load</tspan></text>
<g
style="stroke:#000000;stroke-opacity:1"
id="g3786">
<rect
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
id="rect2820"
width="309.10672"
height="23.233515"
x="39.39595"
y="105.84925" />
<rect
style="fill:#008000;fill-opacity:0.99555556000000001;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
id="rect3598"
width="29.7995"
height="23.233513"
x="224.75897"
y="105.84925" />
<rect
y="105.84925"
x="39.39595"
height="23.233513"
width="28.284269"
id="rect3643"
style="fill:#008000;fill-opacity:0.99555556000000001;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
<rect
y="105.84925"
x="67.680222"
height="23.233513"
width="17.172592"
id="rect3645"
style="fill:#008000;fill-opacity:0.99555556000000001;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
<rect
y="105.84925"
x="84.852814"
height="23.233513"
width="16.667517"
id="rect3647"
style="fill:#008000;fill-opacity:0.99555556000000001;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
<rect
y="105.84925"
x="101.52033"
height="23.233513"
width="19.697973"
id="rect3649"
style="fill:#008000;fill-opacity:0.99555556000000001;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
<rect
y="105.84925"
x="121.21831"
height="23.233513"
width="25.758888"
id="rect3651"
style="fill:#008000;fill-opacity:0.99555556000000001;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
<rect
y="105.84925"
x="146.9772"
height="23.233513"
width="16.162447"
id="rect3653"
style="fill:#008000;fill-opacity:0.99555556000000001;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
<rect
y="105.84925"
x="163.13965"
height="23.233513"
width="18.68784"
id="rect3655"
style="fill:#008000;fill-opacity:0.99555556000000001;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
<rect
y="105.84925"
x="181.82748"
height="23.233513"
width="23.738588"
id="rect3657"
style="fill:#008000;fill-opacity:0.99555556000000001;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
<rect
y="105.84925"
x="205.56607"
height="23.233513"
width="19.192902"
id="rect3659"
style="fill:#008000;fill-opacity:0.99555556000000001;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
</g>
<g
style="stroke:#000000;stroke-opacity:1"
transform="translate(1.0921666,12)"
id="g3814">
<rect
style="fill:#008000;fill-opacity:1;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
id="rect2820-3"
width="68.185295"
height="23.233521"
x="279.22516"
y="175.03113" />
<rect
style="fill:#800000;fill-opacity:1;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
id="rect3641"
width="30.609148"
height="23.233521"
x="361.42856"
y="175.03113" />
<rect
style="fill:#008000;fill-opacity:0.99555556000000001;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
id="rect3598-6"
width="29.7995"
height="23.233513"
x="223.66682"
y="175.03113" />
<rect
y="175.03113"
x="38.303783"
height="23.233513"
width="28.284269"
id="rect3643-7"
style="fill:#008000;fill-opacity:0.99555556000000001;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
<rect
y="175.03113"
x="66.588058"
height="23.233513"
width="17.172592"
id="rect3645-2"
style="fill:#008000;fill-opacity:0.99555556000000001;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
<rect
y="175.03113"
x="83.760651"
height="23.233513"
width="16.667517"
id="rect3647-7"
style="fill:#008000;fill-opacity:0.99555556000000001;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
<rect
y="175.03113"
x="100.42818"
height="23.233513"
width="19.697973"
id="rect3649-4"
style="fill:#008000;fill-opacity:0.99555556000000001;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
<rect
y="175.03113"
x="120.12614"
height="23.233513"
width="25.758888"
id="rect3651-1"
style="fill:#008000;fill-opacity:0.99555556000000001;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
<rect
y="175.03113"
x="145.88504"
height="23.233513"
width="16.162447"
id="rect3653-0"
style="fill:#008000;fill-opacity:0.99555556000000001;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
<rect
y="175.03113"
x="162.04749"
height="23.233513"
width="18.68784"
id="rect3655-0"
style="fill:#008000;fill-opacity:0.99555556000000001;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
<rect
y="175.03113"
x="180.73532"
height="23.233513"
width="23.738588"
id="rect3657-6"
style="fill:#008000;fill-opacity:0.99555556000000001;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
<rect
y="175.03113"
x="204.47391"
height="23.233513"
width="19.192902"
id="rect3659-4"
style="fill:#008000;fill-opacity:0.99555556000000001;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
<rect
y="175.03113"
x="253.46632"
height="23.233521"
width="25.758841"
id="rect3710"
style="fill:#008000;fill-opacity:1;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
<rect
y="175.03113"
x="308.0145"
height="23.233521"
width="53.414062"
id="rect3712"
style="fill:#d45500;fill-opacity:1;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
</g>
<text
id="text3714"
y="204.54492"
x="419.18903"
style="font-size:18px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:Arial;-inkscape-font-specification:Arial"
xml:space="preserve"><tspan
y="204.54492"
x="419.18903"
id="tspan3716"
sodipodi:role="line">Unload</tspan></text>
<g
style="stroke:#000000;stroke-opacity:1"
transform="translate(0,6)"
id="g3799">
<rect
style="fill:#008000;fill-opacity:1;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
id="rect2820-3-1"
width="68.185295"
height="23.233521"
x="280.31732"
y="141.08276" />
<rect
style="fill:#008000;fill-opacity:0.99555556000000001;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
id="rect3598-6-5"
width="29.7995"
height="23.233513"
x="224.75899"
y="141.08276" />
<rect
y="141.08276"
x="39.39595"
height="23.233513"
width="28.284269"
id="rect3643-7-3"
style="fill:#008000;fill-opacity:0.99555556000000001;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
<rect
y="141.08276"
x="67.680222"
height="23.233513"
width="17.172592"
id="rect3645-2-2"
style="fill:#008000;fill-opacity:0.99555556000000001;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
<rect
y="141.08276"
x="84.852821"
height="23.233513"
width="16.667517"
id="rect3647-7-1"
style="fill:#008000;fill-opacity:0.99555556000000001;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
<rect
y="141.08276"
x="101.52034"
height="23.233513"
width="19.697973"
id="rect3649-4-9"
style="fill:#008000;fill-opacity:0.99555556000000001;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
<rect
y="141.08276"
x="121.21831"
height="23.233513"
width="25.758888"
id="rect3651-1-7"
style="fill:#008000;fill-opacity:0.99555556000000001;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
<rect
y="141.08276"
x="146.9772"
height="23.233513"
width="16.162447"
id="rect3653-0-6"
style="fill:#008000;fill-opacity:0.99555556000000001;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
<rect
y="141.08276"
x="163.13965"
height="23.233513"
width="18.68784"
id="rect3655-0-8"
style="fill:#008000;fill-opacity:0.99555556000000001;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
<rect
y="141.08276"
x="181.82748"
height="23.233513"
width="23.738588"
id="rect3657-6-2"
style="fill:#008000;fill-opacity:0.99555556000000001;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
<rect
y="141.08276"
x="205.56607"
height="23.233513"
width="19.192902"
id="rect3659-4-0"
style="fill:#008000;fill-opacity:0.99555556000000001;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
<rect
y="141.08276"
x="254.55849"
height="23.233521"
width="25.758841"
id="rect3710-6"
style="fill:#008000;fill-opacity:1;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
<rect
y="141.08276"
x="309.10669"
height="23.233521"
width="53.414062"
id="rect3712-4"
style="fill:#d45500;fill-opacity:1;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
</g>
<path
sodipodi:nodetypes="cc"
id="path3830"
d="m 348.50269,89.686811 0,139.401039"
style="fill:#d45500;fill-opacity:1;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" />
<path
style="fill:#d45500;fill-opacity:1;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0"
d="m 39.396011,90.949502 0,139.401038"
id="path3847"
sodipodi:nodetypes="cc" />
<text
id="text3849"
y="161.0282"
x="419.28571"
style="font-size:18px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:Arial;-inkscape-font-specification:Arial"
xml:space="preserve"><tspan
y="161.0282"
x="419.28571"
id="tspan3851"
sodipodi:role="line">Load if higher priority</tspan></text>
</g>
<text
xml:space="preserve"
style="font-size:18px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;fill:#000000;fill-opacity:1;stroke:none;font-family:Arial;-inkscape-font-specification:Arial"
x="156.41992"
y="41.647896"
id="text3853"><tspan
sodipodi:role="line"
id="tspan3855"
x="156.41992"
y="41.647896"
style="font-size:24px">Cache overflow management</tspan></text>
</g>
</svg>

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 248 B

View File

@ -0,0 +1,16 @@
.str,.atv{color:#080}
.kwd,.tag{color:#008}
.com{color:#800}
.typ,.atn,.dec{color:#606}
.lit{color:#066}
.pun{color:#660}
.pln{color:#000}
pre.prettyprint{padding:2px;border:1px solid #888}
@media print{.str{color:#060}
.kwd,.tag{color:#006;font-weight:bold}
.com{color:#600;font-style:italic}
.typ{font-weight:bold}
.lit{color:#044}
.pun{color:#440}
.atn,.typ{color:#404}
.atv{color:#060}}

View File

@ -0,0 +1,46 @@
window.PR_SHOULD_USE_CONTINUATION=true,window.PR_TAB_WIDTH=8,window.PR_normalizedHtml=window.PR=window.prettyPrintOne=window.prettyPrint=void
0,window._pr_isIE6=function(){var a=navigator&&navigator.userAgent&&navigator.userAgent.match(/\bMSIE ([678])\./);return a=a?+a[1]:false,window._pr_isIE6=function(){return a},a},(function(){var
a=true,b=null,c='break continue do else for if return while auto case char const default double enum extern float goto int long register short signed sizeof static struct switch typedef union unsigned void volatile catch class delete false import new operator private protected public this throw true try typeof ',d=c+'alignof align_union asm axiom bool '+'concept concept_map const_cast constexpr decltype '+'dynamic_cast explicit export friend inline late_check '+'mutable namespace nullptr reinterpret_cast static_assert static_cast '+'template typeid typename using virtual wchar_t where ',e=c+'abstract boolean byte extends final finally implements import '+'instanceof null native package strictfp super synchronized throws '+'transient ',f=e+'as base by checked decimal delegate descending event '+'fixed foreach from group implicit in interface internal into is lock '+'object out override orderby params partial readonly ref sbyte sealed '+'stackalloc string select uint ulong unchecked unsafe ushort var ',g=c+'debugger eval export function get null set undefined var with '+'Infinity NaN ',h='caller delete die do dump elsif eval exit foreach for goto if import last local my next no our print package redo require sub undef unless until use wantarray while BEGIN END ',i='break continue do else for if return while and as assert class def del elif except exec finally from global import in is lambda nonlocal not or pass print raise try with yield False True None ',j='break continue do else for if return while alias and begin case class def defined elsif end ensure false in module next nil not or redo rescue retry self super then true undef unless until when yield BEGIN END ',k='break continue do else for if return while case done elif esac eval fi function in local set then until ',l=d+f+g+h+i+j+k,m=(function(){var
a=['!','!=','!==','#','%','%=','&','&&','&&=','&=','(','*','*=','+=',',','-=','->','/','/=',':','::',';','<','<<','<<=','<=','=','==','===','>','>=','>>','>>=','>>>','>>>=','?','@','[','^','^=','^^','^^=','{','|','|=','||','||=','~','break','case','continue','delete','do','else','finally','instanceof','return','throw','try','typeof'],b='(?:^^|[+-]',c;for(c=0;c<a.length;++c)b+='|'+a[c].replace(/([^=<>:&a-z])/g,'\\$1');return b+=')\\s*',b})(),n=/&/g,o=/</g,p=/>/g,q=/\"/g,r,s,t,u,v,w,x,y,z,A,B,C,D,E,F;function
G(a){return a.replace(n,'&amp;').replace(o,'&lt;').replace(p,'&gt;').replace(q,'&quot;')}function
H(a){return a.replace(n,'&amp;').replace(o,'&lt;').replace(p,'&gt;')}C=/&lt;/g,B=/&gt;/g,w=/&apos;/g,E=/&quot;/g,v=/&amp;/g,D=/&nbsp;/g;function
I(a){var b=a.indexOf('&'),c,d,e,f;if(b<0)return a;for(--b;(b=a.indexOf('&#',b+1))>=0;)d=a.indexOf(';',b),d>=0&&(e=a.substring(b+3,d),f=10,e&&e.charAt(0)==='x'&&(e=e.substring(1),f=16),c=parseInt(e,f),isNaN(c)||(a=a.substring(0,b)+String.fromCharCode(c)+a.substring(d+1)));return a.replace(C,'<').replace(B,'>').replace(w,'\'').replace(E,'\"').replace(D,' ').replace(v,'&')}function
J(a){return'XMP'===a.tagName}u=/[\r\n]/g;function K(c,d){var e;return'PRE'===c.tagName?a:u.test(d)?(e='',c.currentStyle?(e=c.currentStyle.whiteSpace):window.getComputedStyle&&(e=window.getComputedStyle(c,b).whiteSpace),!e||e==='pre'):a}function
L(a,b){var c,d,e,f;switch(a.nodeType){case 1:f=a.tagName.toLowerCase(),b.push('<',f);for(e=0;e<a.attributes.length;++e){c=a.attributes[e];if(!c.specified)continue;b.push(' '),L(c,b)}b.push('>');for(d=a.firstChild;d;d=d.nextSibling)L(d,b);(a.firstChild||!/^(?:br|link|img)$/.test(f))&&b.push('</',f,'>');break;case
2:b.push(a.name.toLowerCase(),'=\"',G(a.value),'\"');break;case 3:case 4:b.push(H(a.nodeValue))}}function
M(b){var c=0,d=false,e=false,f,g,h,i;for(f=0,g=b.length;f<g;++f){h=b[f];if(h.ignoreCase)e=a;else
if(/[a-z]/i.test(h.source.replace(/\\u[0-9a-f]{4}|\\x[0-9a-f]{2}|\\[^ux]/gi,''))){d=a,e=false;break}}function
j(a){if(a.charAt(0)!=='\\')return a.charCodeAt(0);switch(a.charAt(1)){case'b':return 8;case't':return 9;case'n':return 10;case'v':return 11;case'f':return 12;case'r':return 13;case'u':case'x':return parseInt(a.substring(2),16)||a.charCodeAt(1);case'0':case'1':case'2':case'3':case'4':case'5':case'6':case'7':return parseInt(a.substring(1),8);default:return a.charCodeAt(1)}}function
k(a){var b;return a<32?(a<16?'\\x0':'\\x')+a.toString(16):(b=String.fromCharCode(a),(b==='\\'||b==='-'||b==='['||b===']')&&(b='\\'+b),b)}function
l(a){var b=a.substring(1,a.length-1).match(new RegExp('\\\\u[0-9A-Fa-f]{4}|\\\\x[0-9A-Fa-f]{2}|\\\\[0-3][0-7]{0,2}|\\\\[0-7]{1,2}|\\\\[\\s\\S]|-|[^-\\\\]','g')),c=[],d=[],e=b[0]==='^',f,g,h,i,m,n,o,p,q;for(h=e?1:0,m=b.length;h<m;++h){o=b[h];switch(o){case'\\B':case'\\b':case'\\D':case'\\d':case'\\S':case'\\s':case'\\W':case'\\w':c.push(o);continue}q=j(o),h+2<m&&'-'===b[h+1]?(g=j(b[h+2]),h+=2):(g=q),d.push([q,g]),g<65||q>122||(g<65||q>90||d.push([Math.max(65,q)|32,Math.min(g,90)|32]),g<97||q>122||d.push([Math.max(97,q)&-33,Math.min(g,122)&-33]))}d.sort(function(a,b){return a[0]-b[0]||b[1]-a[1]}),f=[],i=[NaN,NaN];for(h=0;h<d.length;++h)p=d[h],p[0]<=i[1]+1?(i[1]=Math.max(i[1],p[1])):f.push(i=p);n=['['],e&&n.push('^'),n.push.apply(n,c);for(h=0;h<f.length;++h)p=f[h],n.push(k(p[0])),p[1]
>p[0]&&(p[1]+1>p[0]&&n.push('-'),n.push(k(p[1])));return n.push(']'),n.join('')}function
m(a){var b=a.source.match(new RegExp('(?:\\[(?:[^\\x5C\\x5D]|\\\\[\\s\\S])*\\]|\\\\u[A-Fa-f0-9]{4}|\\\\x[A-Fa-f0-9]{2}|\\\\[0-9]+|\\\\[^ux0-9]|\\(\\?[:!=]|[\\(\\)\\^]|[^\\x5B\\x5C\\(\\)\\^]+)','g')),e=b.length,f=[],g,h,i,j,k;for(j=0,i=0;j<e;++j)k=b[j],k==='('?++i:'\\'===k.charAt(0)&&(h=+k.substring(1),h&&h<=i&&(f[h]=-1));for(j=1;j<f.length;++j)-1===f[j]&&(f[j]=++c);for(j=0,i=0;j<e;++j)k=b[j],k==='('?(++i,f[i]===void
0&&(b[j]='(?:')):'\\'===k.charAt(0)&&(h=+k.substring(1),h&&h<=i&&(b[j]='\\'+f[i]));for(j=0,i=0;j<e;++j)'^'===b[j]&&'^'!==b[j+1]&&(b[j]='');if(a.ignoreCase&&d)for(j=0;j<e;++j)k=b[j],g=k.charAt(0),k.length>=2&&g==='['?(b[j]=l(k)):g!=='\\'&&(b[j]=k.replace(/[a-zA-Z]/g,function(a){var
b=a.charCodeAt(0);return'['+String.fromCharCode(b&-33,b|32)+']'}));return b.join('')}i=[];for(f=0,g=b.length;f<g;++f){h=b[f];if(h.global||h.multiline)throw new
Error(''+h);i.push('(?:'+m(h)+')')}return new RegExp(i.join('|'),e?'gi':'g')}r=b;function
N(a){var c,d,e,f;b===r&&(f=document.createElement('PRE'),f.appendChild(document.createTextNode('<!DOCTYPE foo PUBLIC \"foo bar\">\n<foo />')),r=!/</.test(f.innerHTML));if(r)return d=a.innerHTML,J(a)?(d=H(d)):K(a,d)||(d=d.replace(/(<br\s*\/?>)[\r\n]+/g,'$1').replace(/(?:[\r\n]+[ \t]*)+/g,' ')),d;e=[];for(c=a.firstChild;c;c=c.nextSibling)L(c,e);return e.join('')}function
O(a){var c=0;return function(d){var e=b,f=0,g,h,i,j;for(h=0,i=d.length;h<i;++h){g=d.charAt(h);switch(g){case' ':e||(e=[]),e.push(d.substring(f,h)),j=a-c%a,c+=j;for(;j>=0;j-=' '.length)e.push(' '.substring(0,j));f=h+1;break;case'\n':c=0;break;default:++c}}return e?(e.push(d.substring(f)),e.join('')):d}}z=new
RegExp('[^<]+|<!--[\\s\\S]*?-->|<!\\[CDATA\\[[\\s\\S]*?\\]\\]>|</?[a-zA-Z](?:[^>\"\']|\'[^\']*\'|\"[^\"]*\")*>|<','g'),A=/^<\!--/,y=/^<!\[CDATA\[/,x=/^<br\b/i,F=/^<(\/?)([a-zA-Z][a-zA-Z0-9]*)/;function
P(a){var b=a.match(z),c=[],d=0,e=[],f,g,h,i,j,k,l,m;if(b)for(g=0,k=b.length;g<k;++g){j=b[g];if(j.length>1&&j.charAt(0)==='<'){if(A.test(j))continue;if(y.test(j))c.push(j.substring(9,j.length-3)),d+=j.length-12;else
if(x.test(j))c.push('\n'),++d;else if(j.indexOf('nocode')>=0&&Q(j)){l=(j.match(F))[2],f=1;for(h=g+1;h<k;++h){m=b[h].match(F);if(m&&m[2]===l)if(m[1]==='/'){if(--f===0)break}else++f}h<k?(e.push(d,b.slice(g,h+1).join('')),g=h):e.push(d,j)}else
e.push(d,j)}else i=I(j),c.push(i),d+=i.length}return{source:c.join(''),tags:e}}function
Q(a){return!!a.replace(/\s(\w+)\s*=\s*(?:\"([^\"]*)\"|'([^\']*)'|(\S+))/g,' $1=\"$2$3$4\"').match(/[cC][lL][aA][sS][sS]=\"[^\"]*\bnocode\b/)}function
R(a,b,c,d){var e;if(!b)return;e={source:b,basePos:a},c(e),d.push.apply(d,e.decorations)}function
S(a,c){var d={},e,f,g,h;return(function(){var e=a.concat(c),f=[],g={},i,j,k,l,m,n,o;for(j=0,l=e.length;j<l;++j){m=e[j],o=m[3];if(o)for(i=o.length;--i>=0;)d[o.charAt(i)]=m;n=m[1],k=''+n,g.hasOwnProperty(k)||(f.push(n),g[k]=b)}f.push(/[\0-\uffff]/),h=M(f)})(),f=c.length,g=/\S/,e=function(a){var
b=a.source,g=a.basePos,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y;i=[g,'pln'],s=0,y=b.match(h)||[],u={};for(v=0,q=y.length;v<q;++v){w=y[v],t=u[w],p=void
0;if(typeof t==='string')n=false;else{r=d[w.charAt(0)];if(r)p=w.match(r[1]),t=r[0];else{for(m=0;m<f;++m){r=c[m],p=w.match(r[1]);if(p){t=r[0];break}}p||(t='pln')}n=t.length>=5&&'lang-'===t.substring(0,5),n&&!(p&&typeof
p[1]==='string')&&(n=false,t='src'),n||(u[w]=t)}x=s,s+=w.length,n?(j=p[1],l=w.indexOf(j),k=l+j.length,p[2]&&(k=w.length-p[2].length,l=k-j.length),o=t.substring(5),R(g+x,w.substring(0,l),e,i),R(g+x+l,j,W(o,j),i),R(g+x+k,w.substring(k),e,i)):i.push(g+x,t)}a.decorations=i},e}function
T(a){var c=[],d=[],e,f;return a.tripleQuotedStrings?c.push(['str',/^(?:\'\'\'(?:[^\'\\]|\\[\s\S]|\'{1,2}(?=[^\']))*(?:\'\'\'|$)|\"\"\"(?:[^\"\\]|\\[\s\S]|\"{1,2}(?=[^\"]))*(?:\"\"\"|$)|\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$))/,b,'\'\"']):a.multiLineStrings?c.push(['str',/^(?:\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$)|\`(?:[^\\\`]|\\[\s\S])*(?:\`|$))/,b,'\'\"`']):c.push(['str',/^(?:\'(?:[^\\\'\r\n]|\\.)*(?:\'|$)|\"(?:[^\\\"\r\n]|\\.)*(?:\"|$))/,b,'\"\'']),a.verbatimStrings&&d.push(['str',/^@\"(?:[^\"]|\"\")*(?:\"|$)/,b]),a.hashComments&&(a.cStyleComments?(c.push(['com',/^#(?:(?:define|elif|else|endif|error|ifdef|include|ifndef|line|pragma|undef|warning)\b|[^\r\n]*)/,b,'#']),d.push(['str',/^<(?:(?:(?:\.\.\/)*|\/?)(?:[\w-]+(?:\/[\w-]+)+)?[\w-]+\.h|[a-z]\w*)>/,b])):c.push(['com',/^#[^\r\n]*/,b,'#'])),a.cStyleComments&&(d.push(['com',/^\/\/[^\r\n]*/,b]),d.push(['com',/^\/\*[\s\S]*?(?:\*\/|$)/,b])),a.regexLiterals&&(e='/(?=[^/*])(?:[^/\\x5B\\x5C]|\\x5C[\\s\\S]|\\x5B(?:[^\\x5C\\x5D]|\\x5C[\\s\\S])*(?:\\x5D|$))+/',d.push(['lang-regex',new
RegExp('^'+m+'('+e+')')])),f=a.keywords.replace(/^\s+|\s+$/g,''),f.length&&d.push(['kwd',new
RegExp('^(?:'+f.replace(/\s+/g,'|')+')\\b'),b]),c.push(['pln',/^\s+/,b,' \r\n \xa0']),d.push(['lit',/^@[a-z_$][a-z_$@0-9]*/i,b],['typ',/^@?[A-Z]+[a-z][A-Za-z_$@0-9]*/,b],['pln',/^[a-z_$][a-z_$@0-9]*/i,b],['lit',new
RegExp('^(?:0x[a-f0-9]+|(?:\\d(?:_\\d+)*\\d*(?:\\.\\d*)?|\\.\\d\\+)(?:e[+\\-]?\\d+)?)[a-z]*','i'),b,'0123456789'],['pun',/^.[^\s\w\.$@\'\"\`\/\#]*/,b]),S(c,d)}s=T({keywords:l,hashComments:a,cStyleComments:a,multiLineStrings:a,regexLiterals:a});function
U(c){var d=c.source,e=c.extractedTags,f=c.decorations,g=[],h=0,i=b,j=b,k=0,l=0,m=O(window.PR_TAB_WIDTH),n=/([\r\n ]) /g,o=/(^| ) /gm,p=/\r\n?|\n/g,q=/[ \r\n]$/,r=a,s;function
t(a){var c,e;a>h&&(i&&i!==j&&(g.push('</span>'),i=b),!i&&j&&(i=j,g.push('<span class=\"',i,'\">')),c=H(m(d.substring(h,a))).replace(r?o:n,'$1&nbsp;'),r=q.test(c),e=window._pr_isIE6()?'&nbsp;<br />':'<br />',g.push(c.replace(p,e)),h=a)}while(a){k<e.length?l<f.length?(s=e[k]<=f[l]):(s=a):(s=false);if(s)t(e[k]),i&&(g.push('</span>'),i=b),g.push(e[k+1]),k+=2;else
if(l<f.length)t(f[l]),j=f[l+1],l+=2;else break}t(d.length),i&&g.push('</span>'),c.prettyPrintedHtml=g.join('')}t={};function
V(a,b){var c,d;for(d=b.length;--d>=0;)c=b[d],t.hasOwnProperty(c)?'console'in window&&console.warn('cannot override language handler %s',c):(t[c]=a)}function
W(a,b){return a&&t.hasOwnProperty(a)||(a=/^\s*</.test(b)?'default-markup':'default-code'),t[a]}V(s,['default-code']),V(S([],[['pln',/^[^<?]+/],['dec',/^<!\w[^>]*(?:>|$)/],['com',/^<\!--[\s\S]*?(?:-\->|$)/],['lang-',/^<\?([\s\S]+?)(?:\?>|$)/],['lang-',/^<%([\s\S]+?)(?:%>|$)/],['pun',/^(?:<[%?]|[%?]>)/],['lang-',/^<xmp\b[^>]*>([\s\S]+?)<\/xmp\b[^>]*>/i],['lang-js',/^<script\b[^>]*>([\s\S]*?)(<\/script\b[^>]*>)/i],['lang-css',/^<style\b[^>]*>([\s\S]*?)(<\/style\b[^>]*>)/i],['lang-in.tag',/^(<\/?[a-z][^<>]*>)/i]]),['default-markup','htm','html','mxml','xhtml','xml','xsl']),V(S([['pln',/^[\s]+/,b,' \r\n'],['atv',/^(?:\"[^\"]*\"?|\'[^\']*\'?)/,b,'\"\'']],[['tag',/^^<\/?[a-z](?:[\w.:-]*\w)?|\/?>$/i],['atn',/^(?!style[\s=]|on)[a-z](?:[\w:-]*\w)?/i],['lang-uq.val',/^=\s*([^>\'\"\s]*(?:[^>\'\"\s\/]|\/(?=\s)))/],['pun',/^[=<>\/]+/],['lang-js',/^on\w+\s*=\s*\"([^\"]+)\"/i],['lang-js',/^on\w+\s*=\s*\'([^\']+)\'/i],['lang-js',/^on\w+\s*=\s*([^\"\'>\s]+)/i],['lang-css',/^style\s*=\s*\"([^\"]+)\"/i],['lang-css',/^style\s*=\s*\'([^\']+)\'/i],['lang-css',/^style\s*=\s*([^\"\'>\s]+)/i]]),['in.tag']),V(S([],[['atv',/^[\s\S]+/]]),['uq.val']),V(T({keywords:d,hashComments:a,cStyleComments:a}),['c','cc','cpp','cxx','cyc','m']),V(T({keywords:'null true false'}),['json']),V(T({keywords:f,hashComments:a,cStyleComments:a,verbatimStrings:a}),['cs']),V(T({keywords:e,cStyleComments:a}),['java']),V(T({keywords:k,hashComments:a,multiLineStrings:a}),['bsh','csh','sh']),V(T({keywords:i,hashComments:a,multiLineStrings:a,tripleQuotedStrings:a}),['cv','py']),V(T({keywords:h,hashComments:a,multiLineStrings:a,regexLiterals:a}),['perl','pl','pm']),V(T({keywords:j,hashComments:a,multiLineStrings:a,regexLiterals:a}),['rb']),V(T({keywords:g,cStyleComments:a,regexLiterals:a}),['js']),V(S([],[['str',/^[\s\S]+/]]),['regex']);function
X(a){var b=a.sourceCodeHtml,c=a.langExtension,d,e;a.prettyPrintedHtml=b;try{e=P(b),d=e.source,a.source=d,a.basePos=0,a.extractedTags=e.tags,W(c,d)(a),U(a)}catch(f){'console'in
window&&(console.log(f),console.trace())}}function Y(a,b){var c={sourceCodeHtml:a,langExtension:b};return X(c),c.prettyPrintedHtml}function
Z(c){var d=window._pr_isIE6(),e=d===6?'\r\n':'\r',f=[document.getElementsByTagName('pre'),document.getElementsByTagName('code'),document.getElementsByTagName('xmp')],g=[],h,i,j,k,l,m;for(i=0;i<f.length;++i)for(j=0,l=f[i].length;j<l;++j)g.push(f[i][j]);f=b,h=Date,h.now||(h={now:function(){return(new
Date).getTime()}}),k=0;function n(){var b=window.PR_SHOULD_USE_CONTINUATION?h.now()+250:Infinity,d,e,f,i,j;for(;k<g.length&&h.now()<b;++k){e=g[k];if(e.className&&e.className.indexOf('prettyprint')>=0){f=e.className.match(/\blang-(\w+)\b/),f&&(f=f[1]),i=false;for(j=e.parentNode;j;j=j.parentNode)if((j.tagName==='pre'||j.tagName==='code'||j.tagName==='xmp')&&j.className&&j.className.indexOf('prettyprint')>=0){i=a;break}i||(d=N(e),d=d.replace(/(?:\r\n?|\n)$/,''),m={sourceCodeHtml:d,langExtension:f,sourceNode:e},X(m),o())}}k<g.length?setTimeout(n,250):c&&c()}function
o(){var a=m.prettyPrintedHtml,b,c,f,g,h,i,j,k;if(!a)return;f=m.sourceNode;if(!J(f))f.innerHTML=a;else{k=document.createElement('PRE');for(g=0;g<f.attributes.length;++g)b=f.attributes[g],b.specified&&(c=b.name.toLowerCase(),c==='class'?(k.className=b.value):k.setAttribute(b.name,b.value));k.innerHTML=a,f.parentNode.replaceChild(k,f),f=k}if(d&&f.tagName==='PRE'){j=f.getElementsByTagName('br');for(h=j.length;--h>=0;)i=j[h],i.parentNode.replaceChild(document.createTextNode(e),i)}}n()}window.PR_normalizedHtml=L,window.prettyPrintOne=Y,window.prettyPrint=Z,window.PR={combinePrefixPatterns:M,createSimpleLexer:S,registerLangHandler:V,sourceDecorator:T,PR_ATTRIB_NAME:'atn',PR_ATTRIB_VALUE:'atv',PR_COMMENT:'com',PR_DECLARATION:'dec',PR_KEYWORD:'kwd',PR_LITERAL:'lit',PR_NOCODE:'nocode',PR_PLAIN:'pln',PR_PUNCTUATION:'pun',PR_SOURCE:'src',PR_STRING:'str',PR_TAG:'tag',PR_TYPE:'typ'}})()

View File

@ -0,0 +1,175 @@
<html>
<head>
<link rel="stylesheet" href="css/prettify.css" type="text/css" media="all"/>
<script type="text/javascript" src="js/prettify.js"></script>
<style>
body { background-color:#fff; color: #555; font-family:Verdana; font-size:14px; }
h1, h2, h3 { color:#333; font-family:Trebuchet MS}
a:link, a:visited { text-decoration:none; color:#a00; }
a:hover { text-decoration:none; color:#e00; }
.container { width:700px; margin:auto; font-size:90%;}
.comment { color:#070; }
pre.prettyprint { border:1px solid #ddd;}
</style>
</head>
<body onload="prettyPrint()">
<div class="container" id="page">
<h1>Generic cache system</h1>
<h2>Overview</h2>
<p>
GCache is a generic multilevel priority based cache system which is useful for allocating resources
across RAM, GPU, disk, network etc.</p>
<p><a href="html/index.html">Class documentation</a> created using Doxyigen is available in the <em>docs/html/</em> directory</p>
<p>A quick example might better explain the concept; see <a href="#example">a more detailed example</a>
for source code and in depth comments. we want to implement a priority cache for our
database of 10000 images. We will use 2 levels of caching, RAM and GPU while the images will be stored on disk.</p>
<ul>
<li>Each image is managed through a <em>token</em> which holds the pointer to the data and is used to assign a priority
to the image.</li>
<li>We subclass <em>Cache</em> to our RamCache and GpuCache and define function for loading from disk and
uploading the texture to the GPU</li>
<li>We can set priorities for the images according to our strategy.</li>
<li>Before rendering the image we lock the token and unlock it when done</li>
</ul>
<h2>Design</h2>
<p>GCache is designed for very frequent priority updates where the majority of
resurces are involved. All the system is designed to minimize the computations
required to change priorities and sorting them.</p>
<div style="text-align:center; margin-bottom:20px;">
<img src="img/architecture.png">
</div>
<h3>Token</h3>
<p>Each resource is managed through a pointer to a subclass of <code>Token&lt;Priority&gt;</code>.
Token pointers are transferred between caches but never created or deleted by the cache system.
The user is responsible for storage of the tokens. </p>
<p>
Adding tokens to the cache is done using the function <code>Controller::addToken(Token *)</code>;
the tokens can be scheduled for removal using the function <code>Token::remove()</code> or be dropped
when the max number of tokens in the controller is reached
as set by <code>Controller::setMaxTokens(int)</code>. Use <code>Token::isInCache()</code> to check
for actual removal.</p>
<h3>Priority</h3>
<p>The <code>Token</code> class is templated over a <code>typename Priority</code> which usually
it is a floating point number, but it can be anything sortable through <code>Priority::operator<(const Priority &)</code>.
The goal of the cache system is to juggle resources around so to have the highest priority tokens in the higher cache.</p>
<p>Use function <code>Token::setPriority(Priority)</code> to set tokens priority; it does not require mutexing and it is
therefore vert fast. The change will take effect only upon a call to <code>Controller::updatePriorities()</code>.</p>
<p>Each cache holds a double heap of Tokens (see architecture picture), 'sorted' accordingly to priority. A double heap is a data structure with similar
properties to a heap but which allows quick extraction of both min and max element.</p>
<p>Priorities are sorted with a lazy approach, only when needed (usually when checking if a transfer should be performed. This
results in the higher, smaller caches being sorted more frequently than the larger lower caches.</p>
<h3>Caches</h3>
<p>The user needs to subclass the <code>Cache</code> class and override the virtual functions <code>get(Token *),
drop(Token *) and size(Token *)</code>. Each cache runs its own thread. Resource transfers (reading a file content, uploading a texture, etc)
are performed in that thread using blocking calls.</p>
<p>Cache are added to the controller using the function <code>Controller::addCache(Cache *)</code></p>
<p>The GCache employs a nested cache model: if a resource is present in a cache is also present in all the lower ones,
and thus each cache should have more capacity than the lower one. For sake of simplicity and performances each cache
is allowed to overflow its capacity by at most one resource. (see picture)</p>
<div style="text-align:center; margin-bottom:20px;">
<img src="img/overflow.png">
</div>
<h3>Locking</h3>
<p>Resources must be locked before use, to prevent cache threads to unload them while in use. An object can be locked
only if already loaded in the highest cache, otherwise the <code>lock()</code> function will return false.</p>
<p>Unlock allows the resource to be eventually dropped from the cache. Locks are recursive which means Tokens keep track
of how many time <code>lock()</code> have been called and release the resource only after <code>unlock()</code>
is called that many times.</p>
<p>Loking and unlocking costs basically zero (we are using <code>QAtomicInt</code>).</p>
<h2><a name="example"></a>Minimal example</h2>
<p>This is a minimal pseudo-code example, just to quickly cover the basis. For a real example, involving
also sending resources to the GPU using a share context check the <em>example/my_widget.h</em> file.
</p>
<pre class="prettyprint">
class MyToken: public Token&lt;float&gt; {
public:
MyData *data;
GLUint texture;
};
class RamCache: public Cache&lt;MyToken&gt; {
public:
//return size of object. return -1 on error
int get(MyToken *token) { fread(someting into something); return 1; }
//return size of objecy, cannot fail
int drop(MyToken *token) { delete memory; return 1; }
int size(MyToken *token) { return 1; }
};
class GpuCache: public Cache&lt;MyToken&gt; {
public:
int get(MyToken *token) { glCreate + glTexture;return 1; }
int drop(MyToken *token) { glDelete; return 1; }
int size(MyToken *token) { return 1; }
};
//generate tokens
vector&lt;MyToken&gt; tokens;
for(int i = 0; i &lt; 10000; i++)
tokens.push_back(MyToken(i));
//create ram and gpu caches
RamCache ram;
ram.setCapacity(5000);
GpuCache gpu;
gpu.setCapacity(1000);
//create controller and add caches
Controller&lt;MyToken&gt; controller;
controller.addCache(&ram);
controller.addCache(&gpu);
//tell controller about tokens and start
for(int i = 0; i &lt; tokens.size(); i++) {
tokens[i].setPriority(rand()/((double)RAND_MAX));
controller.addToken(&tokens[i]);
}
controller.start();
//change priorities
for(int i = 0; i &lt; tokens.size(); i++)
tokens[i].setPriority(rand());
controller.updatePriorities();
//lock and use the tokens
for(int i = 0; i &lt; tokens.size(); i++) {
bool success = tokens[i].lock();
if(success) {
//use the token as you see fit
tokens[i].unlock();
}
}
</pre>
</div>
</body>
</html>

101
wrap/gcache/door.h Normal file
View File

@ -0,0 +1,101 @@
/****************************************************************************
* GCache *
* Author: Federico Ponchio *
* *
* Copyright(C) 2011 *
* Visual Computing Lab *
* ISTI - Italian National Research Council *
* *
* All rights reserved. *
* *
* 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. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License (http://www.gnu.org/licenses/gpl.txt) *
* for more details. *
* *
****************************************************************************/
#ifndef CACHE_DOOR_H
#define CACHE_DOOR_H
/*
//a door needs to be open for the thread to continue,
//if it is open the thread enter and closes the door
//this mess is to avoid [if(!open.available()) open.release(1)]
#include <QSemaphore>
class QDoor {
private:
QSemaphore _open;
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
}
void close() {
if(_open.tryAcquire(1)) //check not already cloed
_close.release(1);
}
void enter(bool close = false) {
_open.acquire(1);
if(close)
_close.release(1); //and close door behind
else
_open.release(1); //and leave door opened
}
bool isOpen() { return _open.available() == 1; }
};
*/
#include <QMutex>
#include <QWaitCondition>
/**
A wait condition class that works as a door.
Should check if the semaphore version is faster.
*/
class QDoor {
public:
QDoor(void) : doorOpen(false) {}
///opens the door. Threads trying to enter will be awakened
void open(void) {
this->m.lock();
this->doorOpen = true;
this->m.unlock();
this->c.wakeAll();
}
///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
have only one thread entering the door each time open() is called */
void enter(bool close = false) {
this->m.lock();
while (!this->doorOpen)
this->c.wait(&(this->m));
if(close)
this->doorOpen = false;
this->m.unlock();
}
private:
QMutex m;
QWaitCondition c;
bool doorOpen;
};
#endif

87
wrap/gcache/provider.h Normal file
View File

@ -0,0 +1,87 @@
#ifndef GCACHE_PROVIDER_H
#define GCACHE_PROVIDER_H
#include <QMutex>
#include "dheap.h"
#include "door.h"
#include "token.h"
/* this cache system enforce the rule that the items in a cache are always in all the cache below */
/* two mechanism to remove tokens from the cache:
1) set token count to something low
2) set maximum number of tokens in the provider
*/
/** Base class for Cache and last cache in the GCache system.
You should never interact with this class.
*/
template <typename Token>
class Provider: public QThread {
public:
///holds the resources in this cache but not in the cache above
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;
///signals (to next cache!) priorities have changed or something is available
QDoor check_queue;
Provider(): max_tokens(-1), heap_dirty(false) {}
virtual ~Provider() {}
/// [should be protected, do not use]
void pushPriorities() {
QMutexLocker locker(&priority_lock);
for(int i = 0; i < heap.size(); i++)
heap[i].pushPriority();
heap_dirty = true;
check_queue.open();
}
/// assumes heap lock is locked, runs in cache thread [should be protected, do not use]
void rebuild() {
if(!this->heap_dirty) return;
{
QMutexLocker locker(&priority_lock);
for(int i = 0; i < this->heap.size(); i++)
this->heap[i].pullPriority();
this->heap_dirty = false;
}
this->heap.rebuild();
//remove OUTSIDE tokens from bottom of heap
if(max_tokens != -1) {
while(this->heap.size() > max_tokens) {
Token &t = this->heap.min();
t.count = Token::OUTSIDE;
this->heap.popMin();
}
}
}
///ensure no locked item are to be removed [should be protected, do not use]
template <class FUNCTOR> void flush(FUNCTOR functor) {
int count = 0;
QMutexLocker locker(&(this->heap_lock));
for(int k = 0; k < this->heap.size(); k++) {
Token *token = &this->heap[k];
if(functor(token)) { //drop it
token->count = Token::OUTSIDE;
} else
this->heap.at(count++) = token;
}
this->heap.resize(count);
this->heap_dirty = true;
}
};
#endif

91
wrap/gcache/token.h Normal file
View File

@ -0,0 +1,91 @@
#ifndef GCACHE_TOKEN_H
#define GCACHE_TOKEN_H
#include <QAtomicInt>
/* QAtomic int count keep trak of token status:
>0: locked (possibly multiple times)
0: data ready in last cache
-1: not in last cache
-2: to removed from all caches
-3: out of caches
*/
/** Holds the resources to be cached.
The Priority template argument can simply be a floating point number
or something more complex, (frame and error in pixel); the only
requirement is the existence of a < comparison operator */
template <typename Priority>
class Token {
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]
Priority tmp_priority;
///reference count of locked items [do not use, should be private]
QAtomicInt count;
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;
}
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
bool remove() {
count.testAndSetOrdered(READY, REMOVE);
count.testAndSetOrdered(CACHE, REMOVE);
return count <= REMOVE; //might have become OUSIDE in the meanwhile
}
bool isLocked() { return count > 0; }
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() {
tmp_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 {
if(count == a.count)
return priority < a.priority;
return count < a.count;
}
bool operator>(const Token &a) const {
if(count == a.count)
return priority > a.priority;
return count > a.count;
}
};
#endif // GCACHE_H