13 template<
class Data_,
class Key_ = Id,
template<
class>
class Alloc_ = SmallAllocator>
26 template<
class T>
using Alloc = Alloc_<T>;
29 DepNode(
const Data& data =
Data(),
const Key& key =
Key()) : _data(data), _key(key) {}
32 void setData(
const Data& data) { _data = data; }
33 const Data&
getData()
const {
return _data; }
36 operator const Data&()
const {
return getData(); }
45 void setKey(
const Key& key) { _key = key; }
46 const Key&
getKey()
const {
return _key; }
53 if (key == _key)
return;
58 void remove(
const Key& key) { _deps.erase(key); }
63 const DepMap&
deps()
const {
return _deps; }
81 template<
class DepNode_>
84 typedef DepNode_ DepNode;
88 template<
class T>
using Alloc =
typename DepNode::template Alloc<T>;
95 typedef list<Vertex, Alloc<Vertex>> VertexList;
115 const NodeList&
nodes() {
return nodeList; }
116 const NodeListConst&
nodes()
const {
return reinterpret_cast<const NodeListConst&
>(nodeList); }
118 const KeyList&
keys()
const {
return keyList; }
121 {
return honey::keys(const_cast<const Vertex*>(
this)->linkMaps[static_cast<int>(type)]); }
123 {
return honey::keys(reinterpret_cast<const LinkMapConst&>(linkMaps[static_cast<int>(type)])); }
129 auto& linkMap = this->linkMap(type);
130 auto itMap = linkMap.find(vertex);
131 auto& refCount = (itMap == linkMap.end()) ? linkMap[vertex] = 0 : itMap->second;
136 void remove(DepType type, Vertex*
vertex,
int count = 1)
138 auto& linkMap = this->linkMap(type);
139 auto itMap = linkMap.find(vertex);
140 assert(itMap != linkMap.end(),
sout() <<
"Unable to remove dependency link. Vertex: " << *keyList.begin() <<
141 " ; Link Type: " <<
static_cast<int>(type) <<
" ; Link Key: " << *vertex->keyList.begin());
142 auto& refCount = itMap->second;
144 if (refCount <= 0) linkMap.erase(itMap);
147 const LinkMap& linkMap(DepType type)
const {
return linkMaps[
static_cast<int>(type)]; }
148 LinkMap& linkMap(DepType type) {
return linkMaps[
static_cast<int>(type)]; }
151 bool isPhantom()
const {
return nodeList.empty(); }
153 bool isMerged()
const {
return keyList.size() > 1; }
155 typename VertexList::iterator itAlloc;
158 array<LinkMap, DepNode::depTypeMax> linkMaps;
162 typedef vector<Vertex*, Alloc<Vertex*>> VertexPList;
163 typedef stdutil::unordered_set<Vertex*, Alloc> VertexSet;
167 CondenseData() : preOrd(0) {}
169 typedef stdutil::unordered_map<Vertex*, int, Alloc> PreOrdMap;
171 typedef stdutil::unordered_map<Vertex*, VertexSet, Alloc> MergeMap;
173 typedef stdutil::unordered_map<Vertex*, Vertex*, Alloc> MergeMapR;
179 VertexSet assignedList;
188 typedef
MtMap< Vertex*, k_vertex,
189 const typename Vertex::LinkMap*, k_linkMap,
190 typename Vertex::LinkMap::const_iterator, k_linkIt
193 typedef vector<VertexLink, Alloc<VertexLink>> VertexLinkList;
199 auto& vertex = createVertex(node.getKey());
201 if (!vertex.nodeList.insert(&node).second)
return false;
203 for (
auto& e : node.deps())
206 auto type = e.second;
209 auto& depVertex = createVertex(key);
211 if (&depVertex == &vertex)
continue;
229 bool remove(DepNode& node)
231 auto itMap = _vertexMap.find(node.getKey());
232 if (itMap == _vertexMap.end())
return false;
234 auto& vertex = *itMap->second;
237 auto itNode = vertex.nodeList.find(&node);
238 if (itNode == vertex.nodeList.end())
return false;
239 vertex.nodeList.erase(itNode);
241 for (
auto& e : node.deps())
244 auto type = e.second;
247 auto itMap = _vertexMap.find(key);
248 assert(itMap != _vertexMap.end(),
sout() <<
"Unable to remove dependency. Node: " << node.getKey() <<
249 " ; DepType: " <<
static_cast<int>(type) <<
" ; DepKey: " << key);
250 auto& depVertex = *itMap->second;
252 if (&depVertex == &vertex)
continue;
267 if (depVertex.isPhantom() && depVertex.linkMap(
DepType::in).empty() && depVertex.linkMap(
DepType::out).empty())
268 deleteVertex(depVertex);
273 deleteVertex(vertex);
275 else if (vertex.isMerged())
294 template<
class Vertex_>
308 _graph(nullptr), _vertex(nullptr), _type(DepType::out), _skipEdges(false) {}
311 _graph(&graph) {
reset(start, type); }
315 if (!_vertex)
return *
this;
319 while (!_stack.empty() && _stack.back()[k_vertex()] == _vertex) _stack.pop_back();
323 while (_vertexIt != _graph->_vertexList.end() || !_stack.empty())
334 if (_stack.back()[k_linkIt()] == _stack.back()[k_linkMap()]->end()) { _stack.pop_back();
continue; }
335 _vertex = (_stack.back()[k_linkIt()]++)->first;
337 if (!_vertex || _vertex->isPhantom() || !_visited.insert(_vertex).second)
continue;
340 _stack.push_back(
mtmap( k_vertex() = _vertex,
341 k_linkMap() = &_vertex->linkMap(_type),
342 k_linkIt() = _vertex->linkMap(_type).begin() ));
363 _vertexIt = _graph->_vertexList.end();
370 auto itMap = _graph->_vertexMap.find(*start);
371 _vertex = itMap != _graph->_vertexMap.end() && !itMap->second->isPhantom() ? itMap->second :
nullptr;
376 _vertexIt = _graph->_vertexList.begin();
379 if (!_vertex)
return;
382 _visited.insert(_vertex);
383 _stack.push_back(
mtmap( k_vertex() = _vertex,
384 k_linkMap() = &_vertex->linkMap(_type),
385 k_linkIt() = _vertex->linkMap(_type).begin() ));
395 for (; _vertexIt != _graph->_vertexList.end() && (_vertexIt->isPhantom() || !_vertexIt->linkMap(typeOpp).empty()); ++_vertexIt);
396 _vertex = _vertexIt != _graph->_vertexList.end() ?
const_cast<Vertex*
>(&*_vertexIt) :
nullptr;
403 typename VertexList::const_iterator _vertexIt;
404 VertexLinkList _stack;
416 template<
class Vertex_>
434 if (!_it._vertex)
return *
this;
435 if (++_nodeIt == _it->nodes().end()) { ++_it; initIt(); }
436 else _node = *_nodeIt;
450 { _it.
reset(start, type); initIt(); }
457 void initIt() { _node = _it._vertex ? *(_nodeIt = _it->nodes().begin()) :
nullptr; }
460 typename NodeList::const_iterator _nodeIt;
474 for (
auto it = begin(
range); it != end(
range); ++it)
if (it->keys().count(dependency))
return true;
481 return find(
range, [&](
auto& e) {
return e.nodes().count(&dependency); }) != end(
range);
488 const Vertex*
vertex(
const Key& key)
const
490 auto itMap = _vertexMap.find(key);
491 return itMap != _vertexMap.end() && !itMap->second->isPhantom() ? itMap->second :
nullptr;
495 auto itMap = _vertexMap.find(key);
496 return itMap != _vertexMap.end() && !itMap->second->isPhantom() ? itMap->second :
nullptr;
509 VertexLinkList linkList;
511 for (
auto& vertex :
values(_vertexMap))
513 assert(data.stackS.empty() && data.stackP.empty(),
"Condense algorithm failure");
515 linkList.push_back(
mtmap( k_vertex() = vertex,
521 for (
auto& e : data.mergeMap)
523 auto& mergeVertex = *e.first;
524 auto& oldVertexList = e.second;
529 auto type = DepType(i);
533 for (
auto& e : oldVertexList)
535 auto& oldVertex = *e;
536 for (
auto& e : oldVertex.linkMap(type))
538 auto& vertex = *e.first;
541 if (oldVertexList.count(&vertex))
continue;
545 auto itMerged = data.mergeMapR.find(pVertex);
546 if (itMerged != data.mergeMapR.end()) pVertex = itMerged->second;
549 mergeVertex.add(type, pVertex, e.second);
553 if (pVertex != &vertex)
continue;
556 auto& linkMap = vertex.linkMap(depTypeOpp);
557 auto itOld = linkMap.find(&oldVertex);
558 assert(itOld != linkMap.end(),
"Old link not found, problem with algorithm");
560 vertex.add(depTypeOpp, &mergeVertex, itOld->second);
561 linkMap.erase(itOld);
567 for (
auto& e : mergeVertex.keyList) { _vertexMap[e] = &mergeVertex; }
570 for (
auto& e : oldVertexList)
572 auto& oldVertex = *e;
574 oldVertex.keyList.clear();
575 deleteVertex(oldVertex);
581 Vertex& createVertex()
584 _vertexList.resize(_vertexList.size()+1);
586 _vertexList.back().itAlloc = --_vertexList.end();
587 return _vertexList.back();
591 Vertex& createVertex(
const Key& key)
593 auto itMap = _vertexMap.find(key);
594 if (itMap == _vertexMap.end()) itMap = mapVertex(createVertex(), key);
595 return *itMap->second;
599 typename VertexMap::iterator mapVertex(Vertex& vertex,
const Key& key)
601 vertex.keyList.insert(key);
602 return _vertexMap.insert(make_pair(key, &vertex)).first;
605 void deleteVertex(Vertex& vertex)
608 for (
auto& e : vertex.keyList) { _vertexMap.erase(e); }
610 _vertexList.erase(vertex.itAlloc);
628 void condense(CondenseData& data,
const VertexLinkList& linkList)
630 auto vertex = linkList.back()[k_vertex()];
631 if (!data.preOrdMap.insert(make_pair(vertex, data.preOrd)).second)
return;
633 data.stackS.push_back(vertex);
634 data.stackP.push_back(vertex);
636 VertexLinkList recurseList;
638 for (
auto& e : linkList)
640 auto links =
honey::range(e[k_linkIt()], e[k_linkMap()]->end());
641 for (
auto& linkVertex :
keys(links))
643 auto itPreOrd = data.preOrdMap.find(linkVertex);
644 if (itPreOrd == data.preOrdMap.end())
648 recurseList.push_back(
mtmap(k_vertex() = linkVertex,
650 k_linkIt() = linkVertex->linkMap(
DepType::out).begin() ));
653 else if (!data.assignedList.count(linkVertex))
655 auto linkPreOrd = itPreOrd->second;
656 while (data.preOrdMap.find(data.stackP.back())->second > linkPreOrd)
658 data.stackP.pop_back();
659 assert(!data.stackP.empty(),
"Condense algorithm failure");
665 if (data.stackP.back() ==
vertex)
668 if (data.stackS.back() !=
vertex)
671 auto& mergeVertex = createVertex();
673 Vertex* assignVertex;
676 assignVertex = data.stackS.back();
677 data.stackS.pop_back();
679 data.assignedList.insert(assignVertex);
680 data.mergeMap[&mergeVertex].insert(assignVertex);
681 data.mergeMapR[assignVertex] = &mergeVertex;
686 for (
auto& e : assignVertex->nodeList)
689 assert(!mergeVertex.nodeList.count(e),
sout() <<
"Duplicate reference during condense merge. Node: " << e->getKey());
690 mergeVertex.nodeList.insert(e);
694 for (
auto& e : assignVertex->keyList)
697 assert(!mergeVertex.keyList.count(e),
sout() <<
"Duplicate key during condense merge. Node: " << e);
698 mergeVertex.keyList.insert(e);
701 }
while (assignVertex != vertex);
706 data.assignedList.insert(data.stackS.back());
707 data.stackS.pop_back();
710 data.stackP.pop_back();
715 void decondense(Vertex& mergeVertex)
718 for (
auto& e : mergeVertex.keyList) { _vertexMap.erase(e); }
720 for (
auto& e : mergeVertex.nodeList) {
add(*e); }
725 auto type = DepType(i);
728 for (
auto& e :
keys(mergeVertex.linkMap(type)))
732 vertex.linkMap(depTypeOpp).erase(&mergeVertex);
734 for (
auto& e : vertex.nodeList)
737 for (
auto& e : node.deps())
739 auto type = e.second;
740 if (type != depTypeOpp)
continue;
743 if (!mergeVertex.keyList.count(key))
continue;
746 auto& depVertex = createVertex(key);
766 mergeVertex.keyList.clear();
767 deleteVertex(mergeVertex);
770 VertexList _vertexList;
771 VertexMap _vertexMap;
NodeIter_< const Vertex > NodeConstIter
Definition: Dep.h:464
bool operator!=(const NodeIter_ &rhs) const
Definition: Dep.h:443
Data & operator*()
Definition: Dep.h:40
bool operator!=(const Iter_ &rhs) const
Definition: Dep.h:353
void skipEdges()
Skip the current vertex's edges on next step of this iterator.
Definition: Dep.h:389
this node depends on the target node
void skipEdges()
Skip the current vertex's edges on next step of this iterator.
Definition: Dep.h:452
Vertex_ value_type
Definition: Dep.h:302
Depth-first pre-order iterator over nodes. Iterates over nodes that constitute each vertex in a verte...
Definition: Dep.h:417
static optnull_t optnull
Null optional, use to reset an optional to an uninitialized state or test for initialization.
Definition: Optional.h:12
const NodeList & nodes()
Get all nodes that constitute this vertex.
Definition: Dep.h:115
static DepType depTypeOpp(DepType type)
Get opposite dependency type.
Definition: Dep.h:66
this node is depended on by the target node
stdutil::unordered_map< const Vertex *, int, Alloc > LinkMapConst
Definition: Dep.h:112
Iter_ operator++(int)
Definition: Dep.h:350
reference operator*() const
Definition: Dep.h:355
auto links(DepType type=DepType::out) -> decltype(honey::keys(declval< const LinkMap >()))
Get all vertices along in/out links.
Definition: Dep.h:120
ptrdiff_t sdt
Size difference type, shorthand for ptrdiff_t.
Definition: Core.h:92
Data_ Data
Definition: Dep.h:24
DepNode * pointer
Definition: Dep.h:426
Iter find(Range &&, Seqs &&..., Func &&pred)
Find an element in a series of sequences.
Vertex_ & reference
Definition: Dep.h:305
DepNode value_type
Definition: Dep.h:424
Iter_()
Definition: Dep.h:307
NodeIter_(Iter &&it)
Definition: Dep.h:430
const Data & operator->() const
Definition: Dep.h:41
NodeIter_ & operator++()
Definition: Dep.h:432
bool depends(const Key &vertex, const Key &dependency, DepType type=DepType::out) const
Check if vertex depends on another vertex.
Definition: Dep.h:471
NodeIter_< Vertex > NodeIter
Definition: Dep.h:463
stdutil::unordered_set< DepNode *, Alloc > NodeList
Definition: Dep.h:98
std::unordered_map< Key, Value, std::hash< Key >, std::equal_to< Key >, Alloc< pair< const Key, Value >>> unordered_map
std::unordered_map with custom allocator
Definition: StdUtil.h:83
std::enable_if< mt::isIterator< Iter1 >::value, Range_< Iter1, Iter2 > >::type range(Iter1 &&first, Iter2 &&last)
Range from iterators [first, last)
Definition: Range.h:116
auto mtmap(Pairs &&...pairs) -> decltype(priv::mtmap_(priv::PairSeqGen< Pairs... >(), forward< Pairs >(pairs)...))
Construct a map from (key() = value) pairs.
Definition: MtMap.h:103
Iter_< Vertex_ > Iter
Definition: Dep.h:420
Range_< ConstIter, ConstIter > range(optional< const Key & > start=optnull, DepType type=DepType::out) const
Get a depth-first pre-order range starting from a vertex. If start vertex is null then range is over ...
Definition: Dep.h:411
Vertex_ & vertex() const
Get the current vertex.
Definition: Dep.h:454
Iter_ & operator++()
Definition: Dep.h:313
Range_< NodeIter, NodeIter > rangeNode(optional< const Key & > start=optnull, DepType type=DepType::out)
Definition: Dep.h:468
auto keys(Range &&range) -> Range_< TupleIter< mt_iterOf(range), 0 >, TupleIter< mt_iterOf(range), 0 >>
Create a range over the keys of a map or map iterator range.
Definition: StdUtil.h:23
bool depends(const Key &vertex, const DepNode &dependency, DepType type=DepType::out) const
Check if vertex depends on node.
Definition: Dep.h:478
pointer operator->() const
Definition: Dep.h:356
bool operator==(const Iter_ &rhs) const
Definition: Dep.h:352
ostringstream sout()
Shorthand to create ostringstream.
Definition: Stream.h:15
stdutil::unordered_map< Key, DepType, Alloc > DepMap
Definition: Dep.h:27
Dependency node for insertion into graph.
Definition: Dep.h:14
#define assert(...)
Forwards to assert_#args. See assert_1(), assert_2().
Definition: Debug.h:24
void add(const Key &key, DepType type=DepType::out)
Add a dependency link.
Definition: Dep.h:50
DepType
Definition: Dep.h:17
Range_< NodeConstIter, NodeConstIter > rangeNode(optional< const Key & > start=optnull, DepType type=DepType::out) const
Get a depth-first pre-order range over nodes starting from a vertex. If start vertex is null then ran...
Definition: Dep.h:467
sdt difference_type
Definition: Dep.h:303
Vertex * vertex(const Key &key)
Definition: Dep.h:493
pointer operator->() const
Definition: Dep.h:446
Iter_(const DepGraph &graph, optional< const Key & > start, DepType type)
Definition: Dep.h:310
reference operator*() const
Definition: Dep.h:445
A vertex is initially associated with one key and acts like a multi-map, storing all nodes and graph ...
Definition: Dep.h:107
void reset(optional< const Key & > start=optnull, DepType type=DepType::out)
Reset iterator to begin at vertex in graph.
Definition: Dep.h:359
stdutil::unordered_set< Key, Alloc > KeyList
Definition: Dep.h:100
bool operator==(const NodeIter_ &rhs) const
Definition: Dep.h:442
const Data & operator*() const
Get the data at this node.
Definition: Dep.h:39
Enables any type to be optional so it can exist in an uninitialized null state.
Definition: Optional.h:52
void condense()
Condense directed graph into directed acyclic graph. Useful for finding dependency cycles and optimiz...
Definition: Dep.h:506
auto links(DepType type=DepType::out) const -> decltype(honey::keys(declval< const LinkMapConst >()))
Definition: Dep.h:122
auto values(Range &&range) -> Range_< TupleIter< mt_iterOf(range), 1 >, TupleIter< mt_iterOf(range), 1 >>
Create a range over the values of a map or map iterator range.
Definition: StdUtil.h:30
void clear()
Clear graph of all nodes.
Definition: Dep.h:281
DepNode & reference
Definition: Dep.h:427
const DepMap & deps() const
Get dep links.
Definition: Dep.h:63
Global allocator for small memory blocks. To provide a custom pool define SmallAllocator_createSingle...
Definition: SmallAllocator.h:23
Dependency graph. Collects nodes and builds a searchable directed graph.
Definition: Dep.h:82
void setData(const Data &data)
Set the data that this node contains.
Definition: Dep.h:32
static const int depTypeMax
Definition: Dep.h:22
stdutil::unordered_set< const DepNode *, Alloc > NodeListConst
Definition: Dep.h:99
Iterator range. See range(Iter1&&, Iter2&&) to create.
Definition: Range.h:88
const Data & getData() const
Definition: Dep.h:33
sdt difference_type
Definition: Dep.h:425
std::forward_iterator_tag iterator_category
Definition: Dep.h:301
void reset(optional< const Key & > start=optnull, DepType type=DepType::out)
Reset iterator to begin at vertex in graph.
Definition: Dep.h:449
Key_ Key
Definition: Dep.h:25
Depth-first pre-order iterator over vertices.
Definition: Dep.h:295
stdutil::unordered_map< Vertex *, int, Alloc > LinkMap
Definition: Dep.h:111
const NodeListConst & nodes() const
Definition: Dep.h:116
const Vertex * vertex(const Key &key) const
Get a vertex which contains a list of cyclical (strongly connected) dependency nodes.
Definition: Dep.h:488
Vertex_ * pointer
Definition: Dep.h:304
const Key & getKey() const
Definition: Dep.h:46
void clear()
Remove all dependency links.
Definition: Dep.h:60
const KeyList & keys() const
Get all keys mapped to this vertex.
Definition: Dep.h:118
bool add(DepNode &node)
Add a node to the graph.
Definition: Dep.h:197
Data & operator->()
Definition: Dep.h:42
std::forward_iterator_tag iterator_category
Definition: Dep.h:423
NodeIter_()
Definition: Dep.h:429
std::unordered_set< Key, std::hash< Key >, std::equal_to< Key >, Alloc< Key >> unordered_set
std::unordered_set with custom allocator
Definition: StdUtil.h:89
Data & getData()
Definition: Dep.h:34
std::conditional< std::is_const< Vertex_ >::value, NodeListConst, NodeList >::type NodeList
Definition: Dep.h:421
DepNode(const Data &data=Data(), const Key &key=Key())
Definition: Dep.h:29
void setKey(const Key &key)
Set the key used to identify this node.
Definition: Dep.h:45
Global Honeycomb namespace.
mt::removePtr< typename NodeList::value_type >::type DepNode
Definition: Dep.h:422
Range_< Iter, Iter > range(optional< const Key & > start=optnull, DepType type=DepType::out)
Definition: Dep.h:412
Iter_< const Vertex > ConstIter
Definition: Dep.h:408
Iter_< Vertex > Iter
Definition: Dep.h:407
Key & getKey()
Definition: Dep.h:47
typename priv::MtMap_< Pairs... >::type MtMap
Declare a map type with MtMap
Definition: MtMap.h:46
NodeIter_ operator++(int)
Definition: Dep.h:440