diff options
author | Marius Kintel <marius@kintel.net> | 2011-09-11 05:33:18 (GMT) |
---|---|---|
committer | Marius Kintel <marius@kintel.net> | 2011-09-11 05:33:18 (GMT) |
commit | c0641d6916775309d64944ca121cc736f0c8d7a1 (patch) | |
tree | 801e0b5d67d13ff4773c5906c9cb68d271a2be02 | |
parent | 09cc0496f7ce61e2bcbce80e067e0fac8054599a (diff) |
Reenabled PolySet caching. Pass shared_ptrs to polysets around to better manage memory
-rw-r--r-- | src/CGALEvaluator.cc | 18 | ||||
-rw-r--r-- | src/CSGTermEvaluator.cc | 20 | ||||
-rw-r--r-- | src/OpenCSGRenderer.cc | 8 | ||||
-rw-r--r-- | src/PolySetEvaluator.cc | 22 | ||||
-rw-r--r-- | src/PolySetEvaluator.h | 9 | ||||
-rw-r--r-- | src/ThrownTogetherRenderer.cc | 2 | ||||
-rw-r--r-- | src/Tree.cc | 15 | ||||
-rw-r--r-- | src/Tree.h | 3 | ||||
-rw-r--r-- | src/csgterm.cc | 15 | ||||
-rw-r--r-- | src/csgterm.h | 9 | ||||
-rw-r--r-- | src/mainwin.cc | 2 | ||||
-rw-r--r-- | src/node.h | 2 |
12 files changed, 66 insertions, 59 deletions
diff --git a/src/CGALEvaluator.cc b/src/CGALEvaluator.cc index 6bd7092..51fe41a 100644 --- a/src/CGALEvaluator.cc +++ b/src/CGALEvaluator.cc @@ -91,8 +91,7 @@ void CGALEvaluator::applyToChildren(const AbstractNode &node, CGALEvaluator::Csg chnode->progress_report(); } } - const std::string &cacheid = this->tree.getString(node); - this->cache.insert(cacheid, N); + this->cache.insert(this->tree.getString(node), N); } extern CGAL_Nef_polyhedron2 *convexhull2(std::list<CGAL_Nef_polyhedron2*> a); @@ -123,8 +122,7 @@ void CGALEvaluator::applyHull(const CgaladvNode &node) if (all2d) { CGAL_Nef_polyhedron N(convexhull2(polys)); - const std::string &cacheid = this->tree.getString(node); - this->cache.insert(cacheid, N); + this->cache.insert(this->tree.getString(node), N); } } } @@ -225,8 +223,7 @@ Response CGALEvaluator::visit(State &state, const TransformNode &node) node.matrix[2], node.matrix[6], node.matrix[10], node.matrix[14], node.matrix[15]); N.p3->transform(t); } - const std::string &cacheid = this->tree.getString(node); - this->cache.insert(cacheid, N); + this->cache.insert(this->tree.getString(node), N); } addToParent(state, node); } @@ -239,7 +236,7 @@ Response CGALEvaluator::visit(State &state, const AbstractPolyNode &node) if (state.isPostfix()) { if (!isCached(node)) { // Apply polyset operation - PolySet *ps = this->psevaluator.getPolySet(node); + shared_ptr<PolySet> ps = this->psevaluator.getPolySet(node, false); CGAL_Nef_polyhedron N; if (ps) { try { @@ -251,8 +248,7 @@ Response CGALEvaluator::visit(State &state, const AbstractPolyNode &node) throw; } } - const std::string &cacheid = this->tree.getString(node); - this->cache.insert(cacheid, N); + this->cache.insert(this->tree.getString(node), N); } addToParent(state, node); } @@ -312,7 +308,7 @@ CGAL_Nef_polyhedron CGALEvaluator::evaluateCGALMesh(const AbstractPolyNode &node // print_messages_push(); - PolySet *ps = this->psevaluator->getPolySet(node); + shared_ptr<PolySet> ps = this->psevaluator->getPolySet(node, false); if (ps) { try { CGAL_Nef_polyhedron N = ps->evaluateCSGMesh(); @@ -320,11 +316,9 @@ CGAL_Nef_polyhedron CGALEvaluator::evaluateCGALMesh(const AbstractPolyNode &node // print_messages_pop(); node.progress_report(); - ps->unlink(); return N; } catch (...) { // Don't leak the PolySet on ProgressCancelException - ps->unlink(); throw; } } diff --git a/src/CSGTermEvaluator.cc b/src/CSGTermEvaluator.cc index 40e46b9..ebea89c 100644 --- a/src/CSGTermEvaluator.cc +++ b/src/CSGTermEvaluator.cc @@ -86,11 +86,11 @@ Response CSGTermEvaluator::visit(State &state, const AbstractIntersectionNode &n } static CSGTerm *evaluate_csg_term_from_ps(const State &state, - vector<CSGTerm*> &highlights, - vector<CSGTerm*> &background, - PolySet *ps, - const ModuleInstantiation *modinst, - const AbstractNode &node) + vector<CSGTerm*> &highlights, + vector<CSGTerm*> &background, + const shared_ptr<PolySet> &ps, + const ModuleInstantiation *modinst, + const AbstractNode &node) { std::stringstream stream; stream << node.name() << node.index(); @@ -109,7 +109,7 @@ Response CSGTermEvaluator::visit(State &state, const AbstractPolyNode &node) if (state.isPostfix()) { CSGTerm *t1 = NULL; if (this->psevaluator) { - PolySet *ps = this->psevaluator->getPolySet(node); + shared_ptr<PolySet> ps = this->psevaluator->getPolySet(node, true); if (ps) { t1 = evaluate_csg_term_from_ps(state, this->highlights, this->background, ps, node.modinst, node); @@ -184,9 +184,9 @@ Response CSGTermEvaluator::visit(State &state, const RenderNode &node) { if (state.isPostfix()) { CSGTerm *t1 = NULL; - PolySet *ps = NULL; + shared_ptr<PolySet> ps; if (this->psevaluator) { - ps = this->psevaluator->getPolySet(node); + ps = this->psevaluator->getPolySet(node, true); } if (ps) { t1 = evaluate_csg_term_from_ps(state, this->highlights, this->background, @@ -203,9 +203,9 @@ Response CSGTermEvaluator::visit(State &state, const CgaladvNode &node) if (state.isPostfix()) { CSGTerm *t1 = NULL; // FIXME: Calling evaluator directly since we're not a PolyNode. Generalize this. - PolySet *ps = NULL; + shared_ptr<PolySet> ps; if (this->psevaluator) { - ps = this->psevaluator->getPolySet(node); + ps = this->psevaluator->getPolySet(node, true); } if (ps) { t1 = evaluate_csg_term_from_ps(state, this->highlights, this->background, diff --git a/src/OpenCSGRenderer.cc b/src/OpenCSGRenderer.cc index a16d920..4a86c5c 100644 --- a/src/OpenCSGRenderer.cc +++ b/src/OpenCSGRenderer.cc @@ -28,6 +28,7 @@ #include "OpenCSGRenderer.h" #include "polyset.h" #include "csgterm.h" +#include "stl-utils.h" #ifdef ENABLE_OPENCSG # include <opencsg.h> #endif @@ -37,13 +38,13 @@ class OpenCSGPrim : public OpenCSG::Primitive public: OpenCSGPrim(OpenCSG::Operation operation, unsigned int convexity) : OpenCSG::Primitive(operation, convexity) { } - PolySet *p; + shared_ptr<PolySet> ps; double *m; int csgmode; virtual void render() { glPushMatrix(); glMultMatrixd(m); - p->render_surface(PolySet::COLORMODE_NONE, PolySet::csgmode_e(csgmode), m); + ps->render_surface(PolySet::COLORMODE_NONE, PolySet::csgmode_e(csgmode), m); glPopMatrix(); } }; @@ -120,11 +121,12 @@ void OpenCSGRenderer::renderCSGChain(CSGChain *chain, GLint *shaderinfo, OpenCSGPrim *prim = new OpenCSGPrim(chain->types[i] == CSGTerm::TYPE_DIFFERENCE ? OpenCSG::Subtraction : OpenCSG::Intersection, chain->polysets[i]->convexity); - prim->p = chain->polysets[i]; + prim->ps = chain->polysets[i]; prim->m = chain->matrices[i]; prim->csgmode = chain->types[i] == CSGTerm::TYPE_DIFFERENCE ? PolySet::CSGMODE_DIFFERENCE : PolySet::CSGMODE_NORMAL; if (highlight) prim->csgmode += 20; else if (background) prim->csgmode += 10; primitives.push_back(prim); } + std::for_each(primitives.begin(), primitives.end(), del_fun<OpenCSG::Primitive>()); } diff --git a/src/PolySetEvaluator.cc b/src/PolySetEvaluator.cc index 6426d6e..a2bdca5 100644 --- a/src/PolySetEvaluator.cc +++ b/src/PolySetEvaluator.cc @@ -11,18 +11,26 @@ QCache<std::string, PolySetEvaluator::cache_entry> PolySetEvaluator::cache(100000); -PolySet *PolySetEvaluator::getPolySet(const AbstractNode &node) +/*! + Factory method returning a PolySet from the given node. If the + node is already cached, the cached PolySet will be returned + otherwise a new PolySet will be created from the node. If cache is + true, the newly created PolySet will be cached. + */ +shared_ptr<PolySet> PolySetEvaluator::getPolySet(const AbstractNode &node, bool cache) { - const string &cacheid = this->tree.getString(node); - if (cache.contains(cacheid)) return cache[cacheid]->ps; + std::string cacheid = this->tree.getString(node); + if (this->cache.contains(cacheid)) { + PRINTF("Cache hit: %s", cacheid.substr(0, 40).c_str()); + return this->cache[cacheid]->ps; + } - PolySet *ps = node.evaluate_polyset(this); - cache.insert(cacheid, new cache_entry(ps), ps?ps->polygons.size():0); + shared_ptr<PolySet> ps(node.evaluate_polyset(this)); + if (cache) this->cache.insert(cacheid, new cache_entry(ps), ps?ps->polygons.size():0); return ps; } -PolySetEvaluator::cache_entry::cache_entry(PolySet *ps) - : ps(ps) +PolySetEvaluator::cache_entry::cache_entry(const shared_ptr<PolySet> &ps) : ps(ps) { if (print_messages_stack.size() > 0) this->msg = print_messages_stack.last(); } diff --git a/src/PolySetEvaluator.h b/src/PolySetEvaluator.h index b7c490d..6319e55 100644 --- a/src/PolySetEvaluator.h +++ b/src/PolySetEvaluator.h @@ -5,6 +5,7 @@ #include "node.h" #include "Tree.h" #include <QCache> +#include "memory.h" class PolySetEvaluator { @@ -14,7 +15,7 @@ public: const Tree &getTree() const { return this->tree; } - virtual PolySet *getPolySet(const class AbstractNode &); + virtual shared_ptr<PolySet> getPolySet(const class AbstractNode &, bool cache); virtual PolySet *evaluatePolySet(const class ProjectionNode &) { return NULL; } virtual PolySet *evaluatePolySet(const class DxfLinearExtrudeNode &) { return NULL; } @@ -22,16 +23,16 @@ public: virtual PolySet *evaluatePolySet(const class CgaladvNode &) { return NULL; } virtual PolySet *evaluatePolySet(const class RenderNode &) { return NULL; } - void clearCache() { + static void clearCache() { cache.clear(); } void printCache(); protected: struct cache_entry { - class PolySet *ps; + shared_ptr<class PolySet> ps; QString msg; - cache_entry(PolySet *ps); + cache_entry(const shared_ptr<PolySet> &ps); ~cache_entry() { } }; diff --git a/src/ThrownTogetherRenderer.cc b/src/ThrownTogetherRenderer.cc index c3ba2a6..956fc11 100644 --- a/src/ThrownTogetherRenderer.cc +++ b/src/ThrownTogetherRenderer.cc @@ -63,7 +63,7 @@ void ThrownTogetherRenderer::renderCSGChain(CSGChain *chain, bool highlight, glDepthFunc(GL_LEQUAL); QHash<QPair<PolySet*,double*>,int> polySetVisitMark; for (size_t i = 0; i < chain->polysets.size(); i++) { - if (polySetVisitMark[QPair<PolySet*,double*>(chain->polysets[i], chain->matrices[i])]++ > 0) + if (polySetVisitMark[QPair<PolySet*,double*>(chain->polysets[i].get(), chain->matrices[i])]++ > 0) continue; double *m = chain->matrices[i]; double *c = chain->colors[i]; diff --git a/src/Tree.cc b/src/Tree.cc index a451f24..7615a3d 100644 --- a/src/Tree.cc +++ b/src/Tree.cc @@ -2,12 +2,18 @@ #include "nodedumper.h" #include <assert.h> +#include <algorithm> + +static bool filter(char c) +{ + return c == ' ' || c == '\n' || c == '\t' || c == '\r'; +} /*! - Returns the cached string representation of the subtree rootet by \a node. + Returns the cached string representation of the subtree rooted by \a node. If node is not cached, the cache will be rebuilt. */ -const std::string &Tree::getString(const AbstractNode &node) const +const std::string Tree::getString(const AbstractNode &node) const { assert(this->root_node); if (!this->nodecache.contains(node)) { @@ -17,7 +23,10 @@ const std::string &Tree::getString(const AbstractNode &node) const assert(this->nodecache.contains(*this->root_node) && "NodeDumper failed to create a cache"); } - return this->nodecache[node]; + std::string str = this->nodecache[node]; + str.erase(std::remove_if(str.begin(), str.end(), filter), str.end()); + + return str; } /*! @@ -20,8 +20,7 @@ public: void setRoot(const AbstractNode *root); const AbstractNode *root() const { return this->root_node; } - // FIXME: Really return a reference? - const string &getString(const AbstractNode &node) const; + const string getString(const AbstractNode &node) const; private: const AbstractNode *root_node; diff --git a/src/csgterm.cc b/src/csgterm.cc index 91497b4..8306aaf 100644 --- a/src/csgterm.cc +++ b/src/csgterm.cc @@ -47,24 +47,17 @@ */ -CSGTerm::CSGTerm(PolySet *polyset, const double matrix[16], const double color[4], const std::string &label) +CSGTerm::CSGTerm(const shared_ptr<PolySet> &polyset, const double matrix[16], const double color[4], const std::string &label) + : type(TYPE_PRIMITIVE), polyset(polyset), label(label), left(NULL), right(NULL) { - this->type = TYPE_PRIMITIVE; - this->polyset = polyset; - this->label = label; - this->left = NULL; - this->right = NULL; for (int i = 0; i < 16; i++) this->m[i] = matrix[i]; for (int i = 0; i < 4; i++) this->color[i] = color[i]; refcounter = 1; } CSGTerm::CSGTerm(type_e type, CSGTerm *left, CSGTerm *right) + : type(type), left(left), right(right) { - this->type = type; - this->polyset = NULL; - this->left = left; - this->right = right; refcounter = 1; } @@ -195,7 +188,7 @@ CSGChain::CSGChain() { } -void CSGChain::add(PolySet *polyset, double *m, double *color, CSGTerm::type_e type, std::string label) +void CSGChain::add(const shared_ptr<PolySet> &polyset, double *m, double *color, CSGTerm::type_e type, std::string label) { polysets.push_back(polyset); matrices.push_back(m); diff --git a/src/csgterm.h b/src/csgterm.h index 2a89ef1..c12b7ae 100644 --- a/src/csgterm.h +++ b/src/csgterm.h @@ -4,6 +4,7 @@ #include <string> #include <vector> #include "polyset.h" +#include "memory.h" class CSGTerm { @@ -16,7 +17,7 @@ public: }; type_e type; - PolySet *polyset; + shared_ptr<PolySet> polyset; std::string label; CSGTerm *left; CSGTerm *right; @@ -24,7 +25,7 @@ public: double color[4]; int refcounter; - CSGTerm(PolySet *polyset, const double matrix[16], const double color[4], const std::string &label); + CSGTerm(const shared_ptr<PolySet> &polyset, const double matrix[16], const double color[4], const std::string &label); CSGTerm(type_e type, CSGTerm *left, CSGTerm *right); CSGTerm *normalize(); @@ -38,7 +39,7 @@ public: class CSGChain { public: - std::vector<PolySet*> polysets; + std::vector<shared_ptr<PolySet> > polysets; std::vector<double*> matrices; std::vector<double*> colors; std::vector<CSGTerm::type_e> types; @@ -46,7 +47,7 @@ public: CSGChain(); - void add(PolySet *polyset, double *m, double *color, CSGTerm::type_e type, std::string label); + void add(const shared_ptr<PolySet> &polyset, double *m, double *color, CSGTerm::type_e type, std::string label); void import(CSGTerm *term, CSGTerm::type_e type = CSGTerm::TYPE_UNION); std::string dump(); diff --git a/src/mainwin.cc b/src/mainwin.cc index 2fd876c..e4d9684 100644 --- a/src/mainwin.cc +++ b/src/mainwin.cc @@ -1497,7 +1497,7 @@ void MainWindow::actionExportImage() void MainWindow::actionFlushCaches() { // FIXME: Polycache -> PolySetEvaluator -// FIXME: PolySetEvaluator->clearCache(); + PolySetEvaluator::clearCache(); #ifdef ENABLE_CGAL // FIXME: Flush caches through whatever channels we have // CGALEvaluator::evaluator()->getCache().clear(); @@ -37,7 +37,7 @@ public: Used for human-readable output. */ virtual std::string name() const; /*! Should return a PolySet of the given geometry. Returns NULL if smth. goes wrong */ - virtual class PolySet *evaluate_polyset(class PolySetEvaluator *evaluator) const { return NULL; } + virtual class PolySet *evaluate_polyset(class PolySetEvaluator *) const { return NULL; } // FIXME: Make return value a reference const std::vector<AbstractNode*> &getChildren() const { |