diff --git a/apps/nexus/extraction.cpp b/apps/nexus/extraction.cpp new file mode 100644 index 00000000..c6d86716 --- /dev/null +++ b/apps/nexus/extraction.cpp @@ -0,0 +1,157 @@ +#include "extraction.h" +#include "metric.h" +#include "nexusmt.h" + +#include + +using namespace std; +using namespace nxs; + +Extraction::Extraction(): target_error(4.0f), extr_max(0xffffffff), + draw_max(640), disk_max(100) { + metric = new FrustumMetric; +} + +Extraction::~Extraction() { + if(metric) delete metric; +} + +void Extraction::Extract(NexusMt *_mt) { + mt = _mt; + + //clear statistics + extr_used = draw_used = disk_used = 0; + + //first we clear the visited flags + visited.clear(); + visited.resize(mt->history.n_nodes(), false); + + heap.clear(); + + History::Node *root = mt->history.Root(); + HeapNode hroot(root, 0); + Diff(hroot); + extr_used += hroot.extr; + draw_used += hroot.draw; + disk_used += hroot.disk; + + Visit(root); + + while(heap.size()) { + pop_heap(heap.begin(), heap.end()); + HeapNode hnode = heap.back(); + heap.pop_back(); + + History::Node *node = hnode.node; + unsigned int id = node - root; + if(visited[id]) continue; + + if(Expand(hnode)) { + extr_used += hnode.extr; + draw_used += hnode.draw; + disk_used += hnode.disk; + Visit(node); + } + } + + Select(); +} + +void Extraction::Select() { + selected.clear(); + History::Node *root = mt->history.Root(); + + History::Node *nodes = mt->history.nodes; + for(unsigned int i = 0; i < visited.size(); i++) { + if(!visited[i]) continue; + History::Node &node = nodes[i]; + + History::Node::iterator n; + for(n = node.out_begin(); n != node.out_end(); n++) { + unsigned int n_out = (*n).node - root; + if(!visited[n_out]) { + History::Link &link = *n; + for(History::Link::iterator k = link.begin(); k != link.end(); k++) { + unsigned int patch = (*k).patch; + selected.push_back(patch); + } + } + } + } +} + +void Extraction::Visit(History::Node *node) { + History::Node *root = mt->history.Root(); + unsigned int n_node = node - root; + if(visited[n_node]) return; + + visited[n_node] = true; + + History::Node::iterator i; + for(i = node->in_begin(); i != node->in_end(); i++) { + unsigned int n_in = (*i).node - root; + if(visited[n_in]) continue; + HeapNode hin((*i).node, 0); + Diff(hin); + extr_used += hin.extr; + draw_used += hin.draw; + disk_used += hin.disk; + Visit((*i).node); + } + + for(i = node->out_begin(); i != node->out_end(); i++) { + float maxerror = 0; + History::Link &link = *i; + for(History::Link::iterator k = link.begin(); k != link.end(); k++) { + Entry &entry = (*mt)[(*k).patch]; + float error = metric->GetError(entry); + if(error > maxerror) maxerror = error; + } + //TODO this check may be dangerous for non saturating things... + if(maxerror > target_error) { + HeapNode hnode((*i).node, maxerror); + Diff(hnode); + heap.push_back(hnode); + push_heap(heap.begin(), heap.end()); + } + } +} + +bool Extraction::Expand(HeapNode &node) { + if(extr_used >= extr_max) return false; + if(draw_used >= draw_max) return false; + // if(disk_used >= disk_max) return false; + return node.error > target_error; +} + +void Extraction::Diff(HeapNode &hnode) { + History::Node &node = *(hnode.node); + History::Node::iterator i; + for(i = node.in_begin(); i != node.in_end(); i++) { + History::Link &link = *i; + for(History::Link::iterator k = link.begin(); k != link.end(); k++) { + unsigned int patch = (*k).patch; + Entry &entry = (*mt)[patch]; + hnode.extr -= entry.ram_size; + vcg::Sphere3f &sphere = entry.sphere; + if(!frustum.IsOutside(sphere.Center(), sphere.Radius())) + hnode.draw -= entry.ram_size; + if(!entry.patch) + hnode.disk -= entry.disk_size; + } + } + + for(i = node.out_begin(); i != node.out_end(); i++) { + History::Link &link = *i; + for(History::Link::iterator k = link.begin(); k != link.end(); k++) { + unsigned int patch = (*k).patch; + Entry &entry = (*mt)[patch]; + hnode.extr += entry.ram_size; + vcg::Sphere3f &sphere = entry.sphere; + if(!frustum.IsOutside(sphere.Center(), sphere.Radius())) + hnode.draw += entry.ram_size; + if(!entry.patch) + hnode.disk += entry.disk_size; + } + } +} diff --git a/apps/nexus/extraction.h b/apps/nexus/extraction.h new file mode 100644 index 00000000..c53179e0 --- /dev/null +++ b/apps/nexus/extraction.h @@ -0,0 +1,61 @@ +#ifndef NXS_EXTRACTION_H +#define NXS_EXTRACTION_H + +#include "history.h" +#include +#include + +namespace nxs { + +class Metric; +class NexusMt; + +class Extraction { + public: + struct HeapNode { + History::Node *node; + float error; + unsigned int extr; + unsigned int draw; + unsigned int disk; + HeapNode(History::Node *_node, float _error): node(_node), error(_error), + extr(0), draw(0), disk(0) {} + bool operator<(const HeapNode &node) const { + return error < node.error; } + }; + + Metric *metric; + + vcg::Frustumf frustum; + + float target_error; + unsigned int extr_used, extr_max; + unsigned int draw_used, draw_max; + unsigned int disk_used, disk_max; + + std::vector visited; + std::vector heap; + std::vector selected; + + Extraction(); + ~Extraction(); + + void Extract(NexusMt *mt); + // void Update(std::vector &selected); + + + protected: + void Select(); + void Visit(History::Node *node); + + bool Expand(HeapNode &node); + void Diff(HeapNode &node); + + private: + NexusMt *mt; +}; + + +}//namespace + +#endif diff --git a/apps/nexus/history.cpp b/apps/nexus/history.cpp new file mode 100644 index 00000000..25668895 --- /dev/null +++ b/apps/nexus/history.cpp @@ -0,0 +1,297 @@ +#include +#include +#include + +#include "history.h" + + +using namespace std; +using namespace nxs; + +History::~History() { + if(buffer) delete []buffer; + nodes = NULL; + in_links= NULL; + out_links = NULL; + frags = NULL; +} + +void History::Clear() { + if(buffer) delete []buffer; + buffer = NULL; + updates.clear(); +} + +void History::ClearQuick() { + if(buffer) delete []buffer; + buffer = NULL; +} + +void History::ClearUpdates() { + updates.clear(); +} + +bool History::Load(unsigned int _size, char *mem) { + if(buffer) delete []buffer; + unsigned int is_quick = *(unsigned int *)mem; + bool success; + if(is_quick == 53) { + // cerr << "Load quick!\n"; + success = LoadQuick(_size, mem); + } else if(is_quick == 32) { + // cerr << "Load updates\n"; + success = LoadUpdates(_size, mem); + } else { + cerr << "Invalid history: " << is_quick << "\n"; + return false; + } + return success; +} + +bool History::LoadQuick(unsigned int _size, char *mem) { + buffer = mem; + nodes = (Node *)(buffer + 5 * sizeof(int)); + in_links = (Link *)(nodes + n_nodes()); + out_links = in_links + n_in_links(); + frags = (Cell *)(out_links + n_out_links()); + + //check size is ok; + assert(n_nodes() * sizeof(Node) + + (n_in_links() + n_out_links()) * sizeof(Link) + + n_frags() * sizeof(Cell) + + 5 * sizeof(int) == size); + size = _size; + return LoadPointers(); +} + +bool History::LoadUpdates(unsigned int _size, char *mem) { + unsigned int *tmp = (unsigned int *)mem; + updates.resize(tmp[1]); + + unsigned int pos = 2; + for(unsigned int i = 0; i < updates.size(); i++) { + unsigned int erased = tmp[pos++]; + unsigned int created = tmp[pos++]; + updates[i].erased.resize(erased); + updates[i].created.resize(created); + for(unsigned int e = 0; e < erased; e++) + updates[i].erased[e] = tmp[pos++]; + for(unsigned int e = 0; e < created; e++) + updates[i].created[e] = tmp[pos++]; + } + delete []mem; + buffer = 0; + return true; +} + +bool History::LoadPointers() { + //now convert integer to pointers + for(unsigned int i = 0; i < n_nodes(); i++) { + Node &node = nodes[i]; + assert(((unsigned int)node.in_link_begin) <= n_in_links()); + assert(((unsigned int)node.out_link_begin) <= n_out_links()); + node.in_link_begin = in_links + (unsigned int)(node.in_link_begin); + node.out_link_begin = out_links + (unsigned int)(node.out_link_begin); + } + + for(unsigned int i = 0; i < n_in_links(); i++) { + Link &link = in_links[i]; + assert(((unsigned int)link.node) <= n_nodes()); + assert(((unsigned int)link.frag_begin) <= n_frags()); + link.node = nodes + (unsigned int)(link.node); + link.frag_begin = frags + (unsigned int)(link.frag_begin); + } + + for(unsigned int i = 0; i < n_out_links(); i++) { + Link &link = out_links[i]; + assert(((unsigned int)link.node) <= n_nodes()); + assert(((unsigned int)link.frag_begin) <= n_frags()); + link.node = nodes + (unsigned int)(link.node); + link.frag_begin = frags + (unsigned int)(link.frag_begin); + } + return true; +} + +char *History::Save(unsigned int &_size) { + if(buffer) { + // cerr << "SaveQuick!\n"; + return SaveQuick(_size); + } else { + // cerr << "Save updates\n"; + return SaveUpdates(_size); + } +} + +char *History::SaveQuick(unsigned int &_size) { + assert(buffer); + for(unsigned int i = 0; i < n_nodes(); i++) { + Node &node = nodes[i]; + node.in_link_begin = (Link *)(node.in_link_begin - in_links); + node.out_link_begin = (Link *)(node.out_link_begin - out_links); + } + + for(unsigned int i = 0; i < n_in_links(); i++) { + Link &link = in_links[i]; + link.node = (Node *)(link.node - nodes); + link.frag_begin = (Cell *)(link.frag_begin - frags); + } + + for(unsigned int i = 0; i < n_out_links(); i++) { + Link &link = out_links[i]; + link.node = (Node *)(link.node - nodes); + link.frag_begin = (Cell *)(link.frag_begin - frags); + } + + _size = size; + char *tmp = buffer; + buffer = NULL; + return tmp; +} + +char *History::SaveUpdates(unsigned int &_size) { + vector buf; + buf.push_back(32); + buf.push_back(updates.size()); + for(unsigned int i = 0; i < updates.size(); i++) { + Update &update = updates[i]; + buf.push_back(update.erased.size()); + buf.push_back(update.created.size()); + for(unsigned int e = 0; e < update.erased.size(); e++) + buf.push_back(update.erased[e]); + for(unsigned int e = 0; e < update.created.size(); e++) + buf.push_back(update.created[e]); + } + + _size = buf.size() * sizeof(unsigned int); + char *mem = new char[_size]; + memcpy(mem, &*buf.begin(), _size); + return mem; +} + +bool History::UpdatesToQuick() { + //maps cell -> node containing it + map cell_node; + //maps node -> Links + map > node_inlinks; + map > node_outlinks; + + vector tmp_nodes; + tmp_nodes.resize(updates.size()); + + vector tmp_in_links; + vector tmp_out_links; + vector tmp_frags; + + unsigned int current_node = 0; + + vector::iterator u; + for(u = updates.begin(); u != updates.end(); u++) { + + Node &node = tmp_nodes[current_node]; + + //created cells belong to this node, we look also for max error. + for(unsigned int i = 0; i < (*u).created.size(); i++) { + unsigned int cell = (*u).created[i]; + cell_node[cell] = current_node; + } + + //Every erased cell already belonged to a node. + //node -> its cells + map > node_erased; + + for(unsigned int i = 0; i < (*u).erased.size(); i++) { + unsigned int cell = (*u).erased[i]; + assert(cell_node.count(cell)); + node_erased[cell_node[cell]].push_back(cell); + } + + + //for every node with erased cells we build a fragment and + //put the corresponding cells in it. + map >::iterator e; + for(e = node_erased.begin(); e != node_erased.end(); e++) { + + //node.in.push_back(innodes.size()); + + unsigned int floor_node = (*e).first; + vector &cells = (*e).second; + + Node &parent = tmp_nodes[floor_node]; + + Link inlink; + inlink.node = (Node *)floor_node; + inlink.frag_begin = (Cell *)(tmp_frags.size()); + inlink.frag_size = cells.size(); + + Link outlink; + outlink.node = (Node *)current_node; + outlink.frag_begin = (Cell *)(tmp_frags.size()); + outlink.frag_size = cells.size(); + + //Fill it with erased cells. + + vector::iterator k; + for(k = cells.begin(); k != cells.end(); k++) { + Cell cell; + cell.patch = (*k); + tmp_frags.push_back(cell); + } + + //Add the new Frag to the node. + + node_outlinks[floor_node].push_back(outlink); + node_inlinks[current_node].push_back(inlink); + + //Update in and out of the nodes. + } + current_node++; + } + + map >::iterator k; + for(k = node_outlinks.begin(); k != node_outlinks.end(); k++) { + unsigned int inode = (*k).first; + vector &links = (*k).second; + tmp_nodes[inode].out_link_begin = (Link *)(tmp_out_links.size()); + tmp_nodes[inode].out_link_size = links.size(); + + for(unsigned int i = 0; i < links.size(); i++) + tmp_out_links.push_back(links[i]); + } + + for(k = node_inlinks.begin(); k != node_inlinks.end(); k++) { + unsigned int inode = (*k).first; + vector &links = (*k).second; + tmp_nodes[inode].in_link_begin = (Link *)(tmp_in_links.size()); + tmp_nodes[inode].in_link_size = links.size(); + + for(unsigned int i = 0; i < links.size(); i++) + tmp_in_links.push_back(links[i]); + } + size = tmp_nodes.size() * sizeof(Node) + + tmp_in_links.size() * sizeof(Link) + + tmp_out_links.size() * sizeof(Link) + + tmp_frags.size() * sizeof(Cell) + + 5 * sizeof(int); + + if(buffer) delete []buffer; + buffer = new char[size]; + + quick() = 53; + n_nodes() = tmp_nodes.size(); + n_in_links() = tmp_in_links.size(); + n_out_links() = tmp_out_links.size(); + n_frags() = tmp_frags.size(); + + nodes = (Node *)(buffer + 5 * sizeof(int)); + in_links = (Link *)(nodes + n_nodes()); + out_links = in_links + n_in_links(); + frags = (Cell *)(out_links + n_out_links()); + + memcpy(nodes, &*tmp_nodes.begin(), tmp_nodes.size()*sizeof(Node)); + memcpy(in_links, &*tmp_in_links.begin(), tmp_in_links.size()*sizeof(Node)); + memcpy(out_links, &*tmp_out_links.begin(), + tmp_out_links.size()*sizeof(Node)); + memcpy(frags, &*tmp_frags.begin(), tmp_frags.size() * sizeof(Cell)); + + return LoadPointers(); +} diff --git a/apps/nexus/history.h b/apps/nexus/history.h new file mode 100644 index 00000000..e0da7913 --- /dev/null +++ b/apps/nexus/history.h @@ -0,0 +1,103 @@ +#ifndef NXS_HISTORY_H +#define NXS_HISTORY_H + +#include + +//TODO fix a bit better the quick <-> updates duality + +namespace nxs { + + class History { + public: + + enum Mode { QUICK = 1, UPDATES = 2 }; + + struct Update { + std::vector erased; + std::vector created; + }; + + struct Cell { + unsigned int patch; + // float error; + }; + + struct Node; + + struct Link { + Node *node; + + typedef Cell *iterator; + iterator begin() { return frag_begin; } + iterator end() { return frag_begin + frag_size; } + unsigned int size() { return frag_size; } + + Cell *frag_begin; + unsigned int frag_size; + }; + + struct Node { + typedef Link *iterator; + + iterator in_begin() { return in_link_begin; } + iterator in_end() { return in_link_begin + in_link_size; } + unsigned int size() { return in_link_size; } + + iterator out_begin() { return out_link_begin; } + iterator out_end() { return out_link_begin + out_link_size; } + unsigned int out_size() { return out_link_size; } + + Link *in_link_begin; + unsigned int in_link_size; + Link *out_link_begin; + unsigned int out_link_size; + }; + + Node *nodes; + Link *in_links; + Link *out_links; + Cell *frags; + + std::vector updates; + + History(): nodes(NULL), in_links(NULL), out_links(NULL), frags(NULL), + buffer(NULL) {} + ~History(); + + Node *Root() { return &nodes[0]; } + + void Clear(); + void ClearQuick(); + void ClearUpdates(); + //Owns memory afterwards.. do not free mem. + bool Load(unsigned int size, char *mem); + bool LoadQuick(unsigned int size, char *mem); + bool LoadUpdates(unsigned int size, char *mem); + + //after these call history is invalid! and memory returned must be freed... + char *Save(unsigned int &size); //autodetect + char *SaveQuick(unsigned int &size); + char *SaveUpdates(unsigned int &size); + + bool QuickToUpdates(); + bool UpdatesToQuick(); + bool IsQuick() { return buffer != NULL; } + + int &quick() { return ((int *)buffer)[0]; } + int &n_nodes() { return ((int *)buffer)[1]; } + int &n_in_links() { return ((int *)buffer)[2]; } + int &n_out_links() { return ((int *)buffer)[3]; } + int &n_frags() { return ((int *)buffer)[4]; } + + typedef Node *iterator; + iterator begin() { return nodes; } + iterator end() { return nodes + n_nodes(); } + protected: + unsigned int size; + char *buffer; + + bool LoadPointers(); + }; + +} +#endif diff --git a/apps/nexus/index_file.h b/apps/nexus/index_file.h new file mode 100644 index 00000000..da6b05f1 --- /dev/null +++ b/apps/nexus/index_file.h @@ -0,0 +1,79 @@ +#ifndef NXS_INDEX_FILE_H +#define NXS_INDEX_FILE_H + +#include + +#include + +#include "mfile.h" + +namespace nxs { + + /* WARINING when subclassing this class you must add a Close() + in the destructor! */ + +template +class IndexFile: public MFile, public std::vector { + + public: + virtual ~IndexFile() {} + + bool Create(const std::string &filename, unsigned int header_size, + unsigned int max_file_size = MFILE_MAX_SIZE) { + clear(); + if(!MFile::Create(filename, max_file_size)) return false; + MFile::Redim(header_size); + offset = header_size; + return true; + } + + bool Load(const std::string &filename, bool readonly = false) { + clear(); + if(!MFile::Load(filename, readonly)) return false; + SetPosition(0); + LoadHeader(); + + SetPosition(offset); + unsigned int tot; + ReadBuffer(&tot, sizeof(unsigned int)); + resize(tot); + ReadBuffer(&*begin(), size() * sizeof(T)); + return true; + } + + void Close() { + if(IsReadOnly()) return; + if(files.size() == 0) return; //not loaded, not created or closed + + MFile::Redim(offset + size() * sizeof(T)); + SetPosition(offset); + unsigned int tot = size(); + WriteBuffer(&tot, sizeof(unsigned int)); + WriteBuffer(&*begin(), size() * sizeof(T)); + SetPosition(0); + SaveHeader(); + MFile::Close(); + } + + int64 Length() { //count the header but not the index... + return offset; + } + + void Redim(int64 size) { + MFile::Redim(size); + offset = size; + assert(MFile::Length() == offset); + } + + protected: + int64 offset; + + //MUST set offset to its correct value + virtual bool LoadHeader() = 0; + //MUST save offset somewhere + virtual void SaveHeader() = 0; +}; + +} //namespace + +#endif diff --git a/apps/nexus/metric.h b/apps/nexus/metric.h new file mode 100644 index 00000000..9de3949f --- /dev/null +++ b/apps/nexus/metric.h @@ -0,0 +1,40 @@ +#ifndef NXS_METRIC_H +#define NXS_METRIC_H + +#include +#include +#include "nexus.h" + +namespace nxs { + + enum MetricKind { FRUSTUM, FLAT, DELTA }; + + class Metric { + public: + virtual void GetView() {} + virtual float GetError(Entry &entry) = 0; + }; + + class FlatMetric: public Metric { + public: + float GetError(Entry &entry) { return entry.error; } + }; + + class FrustumMetric: public Metric { + public: + vcg::Frustumf frustum; + + virtual void GetView() { frustum.GetView(); } + float GetError(Entry &entry) { + vcg::Sphere3f &sphere = entry.sphere; + float dist = Distance(sphere, frustum.ViewPoint()); + if(dist < 0) + return 1e20f; + if(frustum.IsOutside(sphere.Center(), sphere.Radius())) + return -1; + return entry.error/frustum.Resolution(dist); + } + }; +} + +#endif diff --git a/apps/nexus/preload.cpp b/apps/nexus/preload.cpp new file mode 100644 index 00000000..88df625c --- /dev/null +++ b/apps/nexus/preload.cpp @@ -0,0 +1,159 @@ +#include "preload.h" +#include "nexusmt.h" + +using namespace std; +using namespace nxs; + + void Preload::execute() { + assert(mt); + while(!get_signaled()) { + lock.enter(); + while(!queue.size()) { + lock.leave(); + pt::psleep(10); + lock.enter(); + } + //TODO check we are not loading too much memory! + assert(queue.size()); + unsigned int patch = queue.back(); + mt->GetPatch(patch, false); + queue.pop_back(); + lock.leave(); + } + } + +/*void Preload::init(NexusMt *m, std::vector &selected, + std::vector &visited) { + + // cerr << "Init\n"; + + safety.lock(); + mt = m; + missing.clear(); + mt->todraw.clear(); + float loaded = 0; + unsigned int notloaded = 0; + set tmp; + //std::map tmp; + vector flush; + for(unsigned int i = 0; i < selected.size(); i++) { + unsigned int patch = selected[i]; + tmp.insert(patch); + + if(!mt->patches.entries[patch].patch) { + PServer::Entry &entry = mt->patches.entries[patch]; + load.post(patch); + loaded += entry.disk_size; + } else { + PatchInfo &info = mt->index[patch]; + //WORKING QueuePServer::Data &data = mt->patches.Lookup(patch, info.nvert, info.nface, 0.0f, flush); + QueuePServer::Data &data = mt->patches.Lookup(patch, info.nvert, info.nface, flush); + for(unsigned int i = 0; i < flush.size(); i++) { + QueuePServer::Data *data = new QueuePServer::Data; + *data = flush[i]; + draw.post(FLUSH, (unsigned int)data); + } + // WORKING if(flush.size() != 0) { + // cerr << "Flushing!\n"; + // exit(0); + //} + mt->todraw.push_back(&data); + } + //missing.push_back(PServer::Item(patch, 0.0f)); + } + loading = 0.2 * loaded + 0.8 * loading; + + for(unsigned int i = 0; i < visited.size(); i++) { + PServer::Item &item = visited[i]; + if(tmp.count(item.patch)) continue; +// if(mt->patches.entries[item.patch].patch) +// tmp[item.patch] = item.priority; + if(item.priority != 0.0f) + missing.push_back(item); + }*/ + +/* WORKING QueuePServer &ps = mt->patches; + for(unsigned int i = 0; i < ps.heap.size(); i++) { + PServer::Item &item = ps.heap[i]; + if(tmp.count(item.patch)) + item.priority = 0; + else { + if(item.priority == 0) + item.priority = 1; + item.priority *= 1.1; + } + } + make_heap(ps.heap.begin(), ps.heap.end());*/ + +/* sort(missing.begin(), missing.end()); //CRITICAL reverse pero'! + reverse(missing.begin(), missing.end()); + load.post(0xffffffff); + + safety.unlock(); +} + +void Preload::execute() { + + float preload; + prefetching = 0; + loading = 0; + while(1) { + if(get_signaled()) return; + vector flush; + + if(load.get_count() || missing.size() == 0) { + preload = 0; + pt::message *msg = load.getmessage(); + if(msg->id != 0xffffffff) { + safety.lock(); + PatchInfo &info = mt->index[msg->id]; + PServer::Entry &entry = mt->patches.entries[msg->id]; + loading += entry.disk_size; + //posting draw message + //WORKING QueuePServer::Data &data = mt->patches.Lookup(msg->id, info.nvert, info.nface, 0.0f, flush); + QueuePServer::Data &data = mt->patches.Lookup(msg->id, info.nvert, info.nface, flush); + pt::message *msg = new pt::message(DRAW, (unsigned int)&data); + msg->result = msg->id; + draw.post(msg); + + //p;osting flush messages + for(unsigned int i = 0; i < flush.size(); i++) { + QueuePServer::Data *data = new QueuePServer::Data; + *data = flush[i]; + draw.post(FLUSH, (unsigned int)data); + } + safety.unlock(); + } else { + prefetching = 0.2 * preload + 0.8 * prefetching; + } + delete msg; + } else { + safety.lock(); + if(missing.size() != 0) { + PServer::Item item = missing.back(); + missing.pop_back(); + +/*Working if(item.priority > mt->patches.MaxPriority()) { + missing.clear(); + + } else { */ +/*PatchInfo &info = mt->index[item.patch]; + //cerr << "prefetching: " << item.patch << endl; + //WORKING mt->patches.Lookup(item.patch, info.nvert, info.nface, item.priority, flush); + if(!mt->patches.entries[item.patch].patch) { + PServer::Entry &entry = mt->patches.entries[item.patch]; + preload += entry.disk_size; + + mt->patches.Lookup(item.patch, info.nvert, info.nface, flush); + for(unsigned int i = 0; i < flush.size(); i++) { + QueuePServer::Data *data = new QueuePServer::Data; + *data = flush[i]; + draw.post(FLUSH, (unsigned int)data); + } + } + // } + } + safety.unlock(); + } + } +}*/ diff --git a/apps/nexus/preload.h b/apps/nexus/preload.h new file mode 100644 index 00000000..6a532ac8 --- /dev/null +++ b/apps/nexus/preload.h @@ -0,0 +1,40 @@ +#ifndef NXS_PRELOAD_H +#define NXS_PRELOAD_H + +#include + +#include + +#include + +namespace nxs { + +class NexusMt; + +class Preload: public pt::thread{ + public: + + NexusMt *mt; + + pt::mutex lock; + + std::vector queue; + + Preload(): thread(false) {} + ~Preload() { + waitfor(); + } + + void execute(); + + void post(std::vector &patches) { + lock.enter(); + queue = patches; + lock.leave(); + } + + void cleanup() {} +}; + +} +#endif