Implement simple order sort

This commit is contained in:
2025-07-10 22:39:56 +10:00
parent c89a6b92e6
commit 08a05a44eb
2 changed files with 67 additions and 0 deletions

View File

@ -50,6 +50,62 @@ public class ApkPackageGraph {
}
}
extension ApkPackageGraph {
public func orderSort(breakCycles: Bool = true) throws(SortError) -> [ApkPackageGraphNode] {
var stack = [ApkPackageGraphNode]()
var resolving = Set<ApkIndex.Index>()
var visited = Set<ApkIndex.Index>()
var ignoring = Set<ApkIndex.Index>()
for node in self.shallowIsolates {
try orderSort(node, &stack, &resolving, &visited, &ignoring, breakCycles)
}
return stack
}
internal func orderSort(
_ node: ApkPackageGraphNode,
_ stack: inout [ApkPackageGraphNode],
_ resolving: inout Set<ApkIndex.Index>,
_ visited: inout Set<ApkIndex.Index>,
_ ignoring: inout Set<ApkIndex.Index>,
_ breakCycles: Bool
) throws(SortError) {
for dep in node.children {
let depID = dep.packageID
guard !ignoring.contains(depID) else {
continue
}
guard !resolving.contains(depID) else {
throw .cyclicDependency(cycles: "\(node) -> \(dep)")
}
if !visited.contains(depID) {
resolving.insert(depID)
let depNode = self._nodes[depID]
do {
try orderSort(depNode, &stack, &resolving, &visited, &ignoring, breakCycles)
} catch {
guard breakCycles else {
throw error
}
stack.append(depNode)
ignoring.insert(depID)
try orderSort(depNode, &stack, &resolving, &visited, &ignoring, breakCycles)
ignoring.remove(depID)
}
resolving.remove(depID)
visited.insert(depID)
}
}
if !stack.contains(node) {
stack.append(node)
}
}
}
extension ApkPackageGraph {
func findDependencyCycle(node: ApkPackageGraphNode) -> (ApkPackageGraphNode, ApkPackageGraphNode)? {
var resolving = Set<Int>()

View File

@ -30,7 +30,11 @@ struct DpkGraphCommand: AsyncParsableCommand {
try graph.deepIsolates.map { $0.package.nameDescription }.joined(separator: "\n")
.write(to: URL(filePath: "deepIsolates.txt"), atomically: false, encoding: .utf8)
timerStart = DispatchTime.now()
#if false
let sorted = try graph.parallelOrderSort()
print("Parallel sort took \(timerStart.distance(to: .now()).seconds) seconds")
if var out = TextFileWriter(URL(filePath: "sorted.txt")) {
for (i, set) in sorted.enumerated() {
print("\(i):\n", to: &out)
@ -39,6 +43,13 @@ struct DpkGraphCommand: AsyncParsableCommand {
}
}
}
#else
let sorted = try graph.orderSort()
print("Order sort took \(timerStart.distance(to: .now()).seconds) seconds")
try sorted.map(String.init).joined(separator: "\n")
.write(to: URL(filePath: "sorted.txt"), atomically: false, encoding: .utf8)
#endif
} catch {
fatalError(error.localizedDescription)
}