Skip to content

Commit

Permalink
manage heap memory in DependencyGraph with unique_ptrs
Browse files Browse the repository at this point in the history
  • Loading branch information
mgieseki committed Oct 27, 2017
1 parent 307e5bb commit 009880e
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 35 deletions.
56 changes: 28 additions & 28 deletions src/DependencyGraph.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,16 @@
#define DEPENDENCYGRAPH_HPP

#include <map>
#include <memory>
#include <vector>
#include "utility.hpp"

template <typename T>
class DependencyGraph
{
class DependencyGraph {
struct GraphNode {
using Dependees = typename std::vector<GraphNode*>;

GraphNode (const T &k) : key(k), dependent(0) {}
GraphNode (const T &k) : key(k), dependent() {}

void addDependee (GraphNode *node) {
if (node) {
Expand All @@ -39,57 +40,56 @@ class DependencyGraph
}
}

void deleteDependentsAndSelf () {
if (dependent)
dependent->deleteDependentsAndSelf();
for (typename Dependees::iterator it = dependees.begin(); it != dependees.end(); ++it)
(*it)->dependent = 0;
delete this;
void unlinkDependees () {
for (GraphNode *dependee : dependees)
dependee->dependent = nullptr;
}

T key;
GraphNode *dependent;
Dependees dependees;
};

using NodeMap = std::map<T, GraphNode*>;
using NodeMap = std::map<T, std::unique_ptr<GraphNode>>;

public:
~DependencyGraph() {
for (auto &nmpair : _nodeMap)
delete nmpair.second;
}

/** Inserts a new isolated node into the dependency graph. */
void insert (const T &key) {
if (!contains(key))
_nodeMap[key] = new GraphNode(key);
_nodeMap.emplace(key, util::make_unique<GraphNode>(key));
}

void insert (const T &depKey, const T &key) {
if (contains(key))
return;
auto it = _nodeMap.find(depKey);
if (it != _nodeMap.end()) {
GraphNode *node = new GraphNode(key);
it->second->addDependee(node);
_nodeMap[key] = node;
/** Inserts a new node to the graph and adds a dependency on an existing one to it.
* @param[in] key ID of new node to insert
* @param[in] dependantKey ID of node the new node should depend on */
void insert (const T &dependentKey, const T &key) {
if (!contains(key)) {
auto dependentIter = _nodeMap.find(dependentKey);
if (dependentIter != _nodeMap.end()) {
auto node = util::make_unique<GraphNode>(key);
dependentIter->second->addDependee(node.get());
_nodeMap.emplace(key, std::move(node));
}
}
}

/** Removes a node and all its dependents from the graph. */
void removeDependencyPath (const T &key) {
auto it = _nodeMap.find(key);
if (it != _nodeMap.end()) {
GraphNode *startNode = it->second;
for (GraphNode *node=startNode; node; node=node->dependent)
GraphNode *startNode = it->second.get();
for (GraphNode *node=startNode; node; node=node->dependent) {
node->unlinkDependees();
_nodeMap.erase(node->key);
startNode->deleteDependentsAndSelf();
}
}
}

/** Returns the IDs of all nodes present in the graph. */
std::vector<T> getKeys () const {
std::vector<T> keys;
for (auto &entry : _nodeMap)
keys.push_back(entry.first);
keys.emplace_back(entry.first);
return keys;
}

Expand Down
12 changes: 6 additions & 6 deletions src/SVGTree.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -324,26 +324,26 @@ static inline string extract_id_from_url (const string &url) {
}


/** Removes elements present in the SVH tree that are not required.
/** Removes elements present in the SVG tree that are not required.
* For now, only clipPath elements are removed. */
void SVGTree::removeRedundantElements () {
vector<XMLElementNode*> clipElements;
if (!_defs || !_defs->getDescendants("clipPath", 0, clipElements))
vector<XMLElementNode*> clipPathElements;
if (!_defs || !_defs->getDescendants("clipPath", nullptr, clipPathElements))
return;

// collect dependencies between clipPath elements in the defs section of the SVG tree
DependencyGraph<string> idTree;
for (const XMLElementNode *clip : clipElements) {
for (const XMLElementNode *clip : clipPathElements) {
if (const char *id = clip->getAttributeValue("id")) {
if (const char *url = clip->getAttributeValue("clip-path"))
idTree.insert(extract_id_from_url(url), id);
else
idTree.insert(id);
}
}
// collect elements that reference a clipPath (have a clip-path attribute)
// collect elements that reference a clipPath, i.e. have a clip-path attribute
vector<XMLElementNode*> descendants;
_page->getDescendants(0, "clip-path", descendants);
_page->getDescendants(nullptr, "clip-path", descendants);
// remove referenced IDs and their dependencies from the dependency graph
for (const XMLElementNode *elem : descendants) {
string idref = extract_id_from_url(elem->getAttributeValue("clip-path"));
Expand Down
3 changes: 2 additions & 1 deletion tests/DependencyGraphTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,9 @@ TEST(DependencyGraphTest, getKeys) {
TEST(DependencyGraphTest, insert) {
DependencyGraph<int> graph;
populate(graph);
for (int i=1; i <= 7; i++)
for (int i=1; i <= 7; i++) {
ASSERT_TRUE(graph.contains(i));
}
ASSERT_FALSE(graph.contains(0));
ASSERT_FALSE(graph.contains(8));
}
Expand Down

0 comments on commit 009880e

Please sign in to comment.