aboutsummaryrefslogtreecommitdiff
path: root/toolsrc/include
diff options
context:
space:
mode:
authorAlexander Karatarakis <alkarata@microsoft.com>2017-04-11 19:37:38 -0700
committerAlexander Karatarakis <alkarata@microsoft.com>2017-04-12 22:05:03 -0700
commit58f46ab6527b79fcef59cf828133aa9092cba3eb (patch)
tree48d3db322e88043db476429cee9359758981dc0b /toolsrc/include
parent24ba9f94ea346e3ce79441a4752a4f635d410088 (diff)
downloadvcpkg-58f46ab6527b79fcef59cf828133aa9092cba3eb.tar.gz
vcpkg-58f46ab6527b79fcef59cf828133aa9092cba3eb.zip
Rework toposort and create_install_plan
Diffstat (limited to 'toolsrc/include')
-rw-r--r--toolsrc/include/vcpkg_Dependencies.h12
-rw-r--r--toolsrc/include/vcpkg_Graphs.h90
2 files changed, 67 insertions, 35 deletions
diff --git a/toolsrc/include/vcpkg_Dependencies.h b/toolsrc/include/vcpkg_Dependencies.h
index 0e629ffef..36dd3cb2d 100644
--- a/toolsrc/include/vcpkg_Dependencies.h
+++ b/toolsrc/include/vcpkg_Dependencies.h
@@ -4,9 +4,20 @@
#include "StatusParagraphs.h"
#include "VcpkgPaths.h"
#include "vcpkg_optional.h"
+#include "Paragraphs.h"
namespace vcpkg::Dependencies
{
+ struct AnyParagraph
+ {
+ std::vector<PackageSpec> edges() const;
+
+ PackageSpec spec;
+ Optional<StatusParagraph> status_paragraph;
+ Optional<BinaryParagraph> binary_paragraph;
+ Optional<SourceParagraph> source_paragraph;
+ };
+
enum class RequestType
{
UNKNOWN,
@@ -27,6 +38,7 @@ namespace vcpkg::Dependencies
struct InstallPlanAction
{
InstallPlanAction();
+ explicit InstallPlanAction(const AnyParagraph& any_paragraph, const RequestType& request_type);
InstallPlanAction(const InstallPlanType& plan_type, const RequestType& request_type, Optional<BinaryParagraph> binary_pgh, Optional<SourceParagraph> source_pgh);
InstallPlanAction(const InstallPlanAction&) = delete;
InstallPlanAction(InstallPlanAction&&) = default;
diff --git a/toolsrc/include/vcpkg_Graphs.h b/toolsrc/include/vcpkg_Graphs.h
index 3ba26c017..8af2ad053 100644
--- a/toolsrc/include/vcpkg_Graphs.h
+++ b/toolsrc/include/vcpkg_Graphs.h
@@ -17,52 +17,77 @@ namespace vcpkg::Graphs
FULLY_EXPLORED
};
- template <class V, class Func>
- static void topological_sort_internal(const V& vertex,
- ExplorationStatus& status,
- const Func adjacency_list_provider,
- std::unordered_map<V, ExplorationStatus>& exploration_status,
- std::vector<V>& sorted)
+ template <class V, class U>
+ __interface AdjacencyProvider
{
- status = ExplorationStatus::PARTIALLY_EXPLORED;
+ std::vector<V> adjacency_list(const U& vertex) const;
- auto neighbours = adjacency_list_provider(vertex);
+ U load_vertex_data(const V& vertex) const;
+ };
- for (V neighbour : neighbours)
+ template <class V, class U>
+ static void topological_sort_internal(const V& vertex,
+ const AdjacencyProvider<V, U>& f,
+ std::unordered_map<V, ExplorationStatus>& exploration_status,
+ std::vector<U>& sorted)
+ {
+ ExplorationStatus& status = exploration_status[vertex];
+ switch (status)
{
- ExplorationStatus& neighbour_status = exploration_status[neighbour];
- if (neighbour_status == ExplorationStatus::NOT_EXPLORED)
- {
- topological_sort_internal(neighbour, neighbour_status, adjacency_list_provider, exploration_status, sorted);
- }
- else if (neighbour_status == ExplorationStatus::PARTIALLY_EXPLORED)
- {
- throw std::runtime_error("cycle in graph");
- }
+ case ExplorationStatus::FULLY_EXPLORED:
+ return;
+ case ExplorationStatus::PARTIALLY_EXPLORED:
+ Checks::exit_with_message(VCPKG_LINE_INFO, "cycle in graph");
+ case ExplorationStatus::NOT_EXPLORED:
+ {
+ status = ExplorationStatus::PARTIALLY_EXPLORED;
+ const U& vertex_data = f.load_vertex_data(vertex);
+ for (const V& neighbour : f.adjacency_list(vertex_data))
+ topological_sort_internal(neighbour, f, exploration_status, sorted);
+
+ sorted.push_back(std::move(vertex_data));
+ status = ExplorationStatus::FULLY_EXPLORED;
+ return;
+ }
+ default:
+ Checks::unreachable(VCPKG_LINE_INFO);
}
- status = ExplorationStatus::FULLY_EXPLORED;
- sorted.push_back(vertex);
}
- template <class V, class Func>
- std::vector<V> topological_sort(const std::vector<V>& starting_vertices, const Func adjacency_list_provider)
+ template <class V, class U>
+ std::vector<U> topological_sort(const std::vector<V>& starting_vertices, const AdjacencyProvider<V, U>& f)
{
- std::vector<V> sorted;
+ std::vector<U> sorted;
std::unordered_map<V, ExplorationStatus> exploration_status;
for (auto& vertex : starting_vertices)
{
- ExplorationStatus& status = exploration_status[vertex];
- if (status == ExplorationStatus::NOT_EXPLORED)
- {
- topological_sort_internal(vertex, status, adjacency_list_provider, exploration_status, sorted);
- }
+ topological_sort_internal(vertex, f, exploration_status, sorted);
}
return sorted;
}
template <class V>
+ struct GraphAdjacencyProvider final : AdjacencyProvider<V, V>
+ {
+ const std::unordered_map<V, std::unordered_set<V>>& vertices;
+
+ GraphAdjacencyProvider(const std::unordered_map<V, std::unordered_set<V>>& vertices) : vertices(vertices) {}
+
+ std::vector<V> adjacency_list(const V& vertex) const override
+ {
+ const std::unordered_set<V>& as_set = this->vertices.at(vertex);
+ return std::vector<V>(as_set.cbegin(), as_set.cend()); // TODO: Avoid redundant copy
+ }
+
+ V load_vertex_data(const V& vertex) const override
+ {
+ return vertex;
+ }
+ };
+
+ template <class V>
class Graph
{
public:
@@ -88,6 +113,7 @@ namespace vcpkg::Graphs
std::vector<V> topological_sort() const
{
+ GraphAdjacencyProvider<V> adjacency_provider{ this->vertices };
std::unordered_map<V, int> indegrees = count_indegrees();
std::vector<V> sorted;
@@ -101,13 +127,7 @@ namespace vcpkg::Graphs
if (pair.second == 0) // Starting from vertices with indegree == 0. Not required.
{
V vertex = pair.first;
- ExplorationStatus& status = exploration_status[vertex];
- if (status == ExplorationStatus::NOT_EXPLORED)
- {
- topological_sort_internal(vertex, status,
- [this](const V& v) { return this->vertices.at(v); },
- exploration_status, sorted);
- }
+ topological_sort_internal(vertex, adjacency_provider, exploration_status, sorted);
}
}