Go to the documentation of this file.00001 #ifndef GCACHE_CACHE_H
00002 #define GCACHE_CACHE_H
00003
00004 #ifdef _MSC_VER
00005
00006 typedef __int16 int16_t;
00007 typedef unsigned __int16 uint16_t;
00008 typedef __int32 int32_t;
00009 typedef unsigned __int32 uint32_t;
00010 typedef __int64 int64_t;
00011 typedef unsigned __int64 uint64_t;
00012
00013 #else
00014 #include <stdint.h>
00015 #endif
00016
00017 #include <iostream>
00018 #include <limits.h>
00019 #include <vector>
00020 #include <list>
00021
00022 #include "token.h"
00023
00024 #include <wrap/system/multithreading/mt.h>
00025 #include <wrap/system/multithreading/atomic_int.h>
00026
00027 #include "provider.h"
00028
00029 using namespace std;
00030
00031
00032
00033
00034
00035
00039 namespace vcg {
00040
00041 template <typename Token> class Transfer;
00042
00043 template <typename Token>
00044 class Cache: public Provider<Token> {
00045
00046 public:
00048 bool final;
00049
00050 bool quit;
00052 mt::atomicInt new_data;
00054 void (*callback)(void *data);
00055
00057 Provider<Token> *input;
00058
00060 std::vector<Transfer<Token> *> transfers;
00061
00062 protected:
00064 uint64_t s_max;
00066 uint64_t s_curr;
00067
00068 public:
00069 Cache(uint64_t _capacity = INT_MAX):
00070 final(false), quit(false), new_data(false), input(NULL), s_max(_capacity), s_curr(0) {}
00071 virtual ~Cache() {}
00072
00073 void setInputCache(Provider<Token> *p) { input = p; }
00074 uint64_t capacity() { return s_max; }
00075 uint64_t size() { return s_curr; }
00076 void setCapacity(uint64_t c) { s_max = c; }
00077
00079 bool newData() {
00080 bool r = new_data.testAndSetOrdered(1, 0);
00081 return r;
00082 }
00083
00086 void flush() {
00087
00088 {
00089 for(int i = 0; i < this->heap.size(); i++) {
00090 Token *token = &(this->heap[i]);
00091
00092 s_curr -= drop(token);
00093
00094 if(final)
00095 token->count.testAndSetOrdered(Token::READY, Token::CACHE);
00096 input->heap.push(token);
00097 }
00098 this->heap.clear();
00099 }
00100 if(!s_curr == 0) {
00101 std::cerr << "Cache size after flush is not ZERO!\n";
00102 s_curr = 0;
00103 }
00104 }
00105
00108 template <class FUNCTOR> void flush(FUNCTOR functor) {
00109 std::vector<Token *> tokens;
00110 {
00111 int count = 0;
00112 mt::mutexlocker locker(&(this->heap_lock));
00113 for(int k = 0; k < this->heap.size(); k++) {
00114 Token *token = &this->heap[k];
00115 if(functor(token)) {
00116 tokens.push_back(token);
00117 s_curr -= drop(token);
00118
00119 if(final)
00120 token->count.testAndSetOrdered(Token::READY, Token::CACHE);
00121 } else
00122 this->heap.at(count++) = token;
00123 }
00124 this->heap.resize(count);
00125 this->heap_dirty = true;
00126 }
00127 {
00128 mt::mutexlocker locker(&(input->heap_lock));
00129 for(unsigned int i = 0; i < tokens.size(); i++) {
00130 input->heap.push(tokens[i]);
00131 }
00132 }
00133 }
00134
00135 virtual void abort() {}
00136
00137 protected:
00139 virtual int size(Token *token) = 0;
00141 virtual int get(Token *token) = 0;
00143 virtual int drop(Token *token) = 0;
00145
00146
00147
00148
00150 virtual void begin() {}
00151 virtual void middle() {}
00153 virtual void end() {}
00154
00156 void run() {
00157 assert(input);
00158
00159
00160
00161
00162 begin();
00163 while(!this->quit) {
00164 input->check_queue.enter();
00165 if(this->quit) break;
00166
00167 middle();
00168
00169 if(unload() || load()) {
00170 new_data.testAndSetOrdered(0, 1);
00171 input->check_queue.open();
00172 cout << "loaded or unloaded\n";
00173 }
00174 input->check_queue.leave();
00175 }
00176 this->quit = false;
00177 end();
00178 }
00179
00180
00181
00185 bool unload() {
00186 Token *remove = NULL;
00187
00188
00189 if(size() > capacity()) {
00190 mt::mutexlocker locker(&(this->heap_lock));
00191
00192
00193 if(this->heap.size()) {
00194 Token &last = this->heap.min();
00195 int itemsize = size(&last);
00196
00197
00198 if(size() - itemsize > capacity()) {
00199
00200
00201 if(!final) {
00202 remove = this->heap.popMin();
00203 } else {
00204 last.count.testAndSetOrdered(Token::READY, Token::CACHE);
00205 #if(QT_VERSION < 0x050000)
00206 int last_count = last.count;
00207 #else
00208 int last_count = last.count.load();
00209 #endif
00210 if(last_count <= Token::CACHE) {
00211 remove = this->heap.popMin();
00212 } else {
00213 remove = this->heap.popMin();
00214 this->heap.push(remove);
00215 cout << "Reordering stack something (what?)\n";
00216 return true;
00217 }
00218 }
00219 }
00220 }
00221 }
00222
00223 if(remove) {
00224 {
00225 mt::mutexlocker input_locker(&(input->heap_lock));
00226 int size = drop(remove);
00227 assert(size >= 0);
00228 s_curr -= size;
00229 input->heap.push(remove);
00230 }
00231 return true;
00232 }
00233 return false;
00234 }
00235
00237 bool load() {
00238 Token *insert = NULL;
00239 Token *last = NULL;
00240
00241
00242
00243
00244 {
00245 mt::mutexlocker locker(&(this->heap_lock));
00246 this->rebuild();
00247 if(size() > capacity() && this->heap.size() > 0) {
00248 last = &(this->heap.min());
00249 }
00250 }
00251
00252 {
00253 mt::mutexlocker input_locker(&(input->heap_lock));
00254 input->rebuild();
00255 if(input->heap.size()) {
00256 Token &first = input->heap.max();
00257 #if(QT_VERSION < 0x050000)
00258 int first_count = first.count;
00259 #else
00260 int first_count = first.count.load();
00261 #endif
00262 if(first_count > Token::REMOVE &&
00263 (!last || first.priority > last->priority)) {
00264 insert = input->heap.popMax();
00265 }
00266 }
00267 }
00268
00269 if(insert) {
00270
00271 int size = get(insert);
00272
00273 if(size >= 0) {
00274 s_curr += size;
00275 {
00276 mt::mutexlocker locker(&(this->heap_lock));
00277 if(final)
00278 insert->count.ref();
00279
00280 this->heap.push(insert);
00281 }
00282 this->check_queue.open();
00283 return true;
00284
00285 } else {
00286 mt::mutexlocker input_locker(&(input->heap_lock));
00287 input->heap.push(insert);
00288 return false;
00289 }
00290 }
00291 return false;
00292 }
00293 };
00294
00295 }
00296
00297 #endif // GCACHE_H