Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(142)

Unified Diff: src/core/SkTTopoSort.h

Issue 1414503003: Add SkTTopoSort (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Fixed comment format Created 5 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « gyp/core.gypi ('k') | tests/TopoSortTest.cpp » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/core/SkTTopoSort.h
diff --git a/src/core/SkTTopoSort.h b/src/core/SkTTopoSort.h
new file mode 100644
index 0000000000000000000000000000000000000000..35b85eeb8147a24744b12cf6c7a30d99ff3f65ed
--- /dev/null
+++ b/src/core/SkTTopoSort.h
@@ -0,0 +1,112 @@
+/*
+ * Copyright 2015 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkTTopoSort_DEFINED
+#define SkTTopoSort_DEFINED
+
+#include "SkTDArray.h"
+
+#ifdef SK_DEBUG
+template <typename T, typename Traits = T>
+void SkTTopoSort_CheckAllUnmarked(const SkTDArray<T*>& graph) {
+ for (int i = 0; i < graph.count(); ++i) {
+ SkASSERT(!Traits::IsTempMarked(graph[i]));
+ SkASSERT(!Traits::WasOutput(graph[i]));
+ }
+}
+
+template <typename T, typename Traits = T>
+void SkTTopoSort_CleanExit(const SkTDArray<T*>& graph) {
+ for (int i = 0; i < graph.count(); ++i) {
+ SkASSERT(!Traits::IsTempMarked(graph[i]));
+ SkASSERT(Traits::WasOutput(graph[i]));
+ }
+}
+#endif
+
+// Recursively visit a node and all the other nodes it depends on.
+// Return false if there is a loop.
+template <typename T, typename Traits = T>
+bool SkTTopoSort_Visit(T* node, SkTDArray<T*>* result) {
+ if (Traits::IsTempMarked(node)) {
+ // There is a loop.
+ return false;
+ }
+
+ // If the node under consideration has been already been output it means it
+ // (and all the nodes it depends on) are already in 'result'.
+ if (!Traits::WasOutput(node)) {
+ // This node hasn't been output yet. Recursively assess all the
+ // nodes it depends on outputing them first.
+ Traits::SetTempMark(node);
+ for (int i = 0; i < Traits::NumDependencies(node); ++i) {
+ if (!SkTTopoSort_Visit<T, Traits>(Traits::Dependency(node, i), result)) {
+ return false;
+ }
+ }
+ Traits::Output(node, result->count()); // mark this node as output
+ Traits::ResetTempMark(node);
+
+ *result->append() = node;
+ }
+
+ return true;
+}
+
+// Topologically sort the nodes in 'graph'. For this sort, when node 'i' depends
+// on node 'j' it means node 'j' must appear in the result before node 'i'.
+// A false return value means there was a loop and the contents of 'graph' will
+// be in some arbitrary state.
+//
+// Traits requires:
+// static void Output(T* t, int index) { ... } // 'index' is 't's position in the result
+// static bool WasOutput(const T* t) { ... }
+//
+// static void SetTempMark(T* t) { ... } // transiently used during toposort
+// static void ResetTempMark(T* t) { ... }
+// static bool IsTempMarked(const T* t) { ... }
+//
+// static int NumDependencies(const T* t) { ... } // 't' will be output after all the other -
+// static T* Dependency(T* t, int index) { ... } // nodes on which it depends
+// We'll look on T for these by default, or you can pass a custom Traits type.
+//
+// TODO: potentially add a version that takes a seed node and just outputs that
+// node and all the nodes on which it depends. This could be used to partially
+// flush a drawTarget DAG.
+template <typename T, typename Traits = T>
+bool SkTTopoSort(SkTDArray<T*>* graph) {
+ SkTDArray<T*> result;
+
+#ifdef SK_DEBUG
+ SkTTopoSort_CheckAllUnmarked<T, Traits>(*graph);
+#endif
+
+ result.setReserve(graph->count());
+
+ for (int i = 0; i < graph->count(); ++i) {
+ if (Traits::WasOutput((*graph)[i])) {
+ // This node was depended on by some earlier node and has already
+ // been output
+ continue;
+ }
+
+ // Output this node after all the nodes it depends on have been output.
+ if (!SkTTopoSort_Visit<T, Traits>((*graph)[i], &result)) {
+ return false;
+ }
+ }
+
+ SkASSERT(graph->count() == result.count());
+ graph->swap(result);
+
+#ifdef SK_DEBUG
+ SkTTopoSort_CleanExit<T, Traits>(*graph);
+#endif
+ return true;
+}
+
+#endif
« no previous file with comments | « gyp/core.gypi ('k') | tests/TopoSortTest.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698