mirror of
				https://github.com/GayPizzaSpecifications/darwin-apk.git
				synced 2025-11-04 07:59:38 +00:00 
			
		
		
		
	Port index changes to parallel sort
This commit is contained in:
		@ -6,61 +6,46 @@
 | 
				
			|||||||
import Foundation
 | 
					import Foundation
 | 
				
			||||||
 | 
					
 | 
				
			||||||
public class ApkPackageGraph {
 | 
					public class ApkPackageGraph {
 | 
				
			||||||
  public let pkgIndex: ApkIndex
 | 
					  public var pkgIndex: ApkIndex
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  private var _nodes = [ApkPackageGraphNode]()
 | 
					  private var _nodes = [ApkPackageGraphNode]()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  public var nodes: [ApkPackageGraphNode] { self._nodes }
 | 
					  public var nodes: [ApkPackageGraphNode] { self._nodes }
 | 
				
			||||||
  public var shallowIsolates: [ApkPackageGraphNode] { self._nodes.filter(\.parents.isEmpty) }
 | 
					  public var shallowIsolates: [ApkPackageGraphNode] { self._nodes.filter(\.isShallow) }
 | 
				
			||||||
  public var deepIsolates: [ApkPackageGraphNode] { self._nodes.filter(\.children.isEmpty) }
 | 
					  public var deepIsolates: [ApkPackageGraphNode] { self._nodes.filter(\.isDeep) }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  public init(index: ApkIndex) {
 | 
					  public init(index: ApkIndex) {
 | 
				
			||||||
    self.pkgIndex = index
 | 
					    self.pkgIndex = index
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  public func buildGraphNode() {
 | 
					  public func buildGraphNode() {
 | 
				
			||||||
    var provides = [String: Int]()
 | 
					    for (packageID, package) in pkgIndex.packages.enumerated() {
 | 
				
			||||||
 | 
					      let children: [ApkPackageGraphNode.ChildRef] = package.dependencies.compactMap { dependency in
 | 
				
			||||||
    for (idx, package) in self.pkgIndex.packages.enumerated() {
 | 
					        guard let providerID = pkgIndex.resolveIndex(requirement: dependency.requirement) else {
 | 
				
			||||||
      provides[package.name] = idx
 | 
					 | 
				
			||||||
      for provision in package.provides {
 | 
					 | 
				
			||||||
        if !provides.keys.contains(provision.name) {
 | 
					 | 
				
			||||||
          provides[provision.name] = idx
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    for (id, package) in pkgIndex.packages.enumerated() {
 | 
					 | 
				
			||||||
      let children: [ApkIndexRequirementRef] = package.dependencies.compactMap { dependency in
 | 
					 | 
				
			||||||
        guard !dependency.requirement.versionSpec.conflict,
 | 
					 | 
				
			||||||
            let id = provides[dependency.requirement.name] else {
 | 
					 | 
				
			||||||
          return nil
 | 
					          return nil
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        return .init(self, id: id, constraint: .dep(version: dependency.requirement.versionSpec))
 | 
					        return .init(constraint: .dependency, packageID: providerID, versionSpec: dependency.requirement.versionSpec)
 | 
				
			||||||
      } + package.installIf.compactMap { installIf in
 | 
					      } + package.installIf.compactMap { installIf in
 | 
				
			||||||
        guard let id = provides[installIf.requirement.name] else {
 | 
					        guard let prvID = pkgIndex.resolveIndex(requirement: installIf.requirement) else {
 | 
				
			||||||
          return nil
 | 
					          return nil
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        return .init(self, id: id, constraint: .installIf(version: installIf.requirement.versionSpec ))
 | 
					        return .init(constraint: .installIf, packageID: prvID, versionSpec: installIf.requirement.versionSpec)
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      self._nodes.append(.init(self,
 | 
					      self._nodes.append(.init(self,
 | 
				
			||||||
        id: id,
 | 
					        id: packageID,
 | 
				
			||||||
        children: children
 | 
					        children: children
 | 
				
			||||||
      ))
 | 
					      ))
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    var reverseDependencies = [ApkIndexRequirementRef: [ApkIndexRequirementRef]]()
 | 
					    var reverseDependencies = [ApkIndex.Index: [ApkIndex.Index]]()
 | 
				
			||||||
 | 
					 | 
				
			||||||
    for (index, node) in self._nodes.enumerated() {
 | 
					    for (index, node) in self._nodes.enumerated() {
 | 
				
			||||||
      for child in node.children {
 | 
					      for child in node.children {
 | 
				
			||||||
        reverseDependencies[child, default: []].append(
 | 
					        reverseDependencies[child.packageID, default: []].append(index)
 | 
				
			||||||
          .init(self, id: index, constraint: child.constraint)
 | 
					 | 
				
			||||||
        )
 | 
					 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for (ref, parents) in reverseDependencies {
 | 
					    for (ref, parents) in reverseDependencies {
 | 
				
			||||||
      self._nodes[ref.packageID].parents = parents
 | 
					      self._nodes[ref].parentIDs = parents
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -74,8 +59,8 @@ extension ApkPackageGraph {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  func findDependencyCycle(
 | 
					  func findDependencyCycle(
 | 
				
			||||||
    node: ApkPackageGraphNode,
 | 
					    node: ApkPackageGraphNode,
 | 
				
			||||||
    _ resolving: inout Set<Int>,
 | 
					    _ resolving: inout Set<ApkIndex.Index>,
 | 
				
			||||||
    _ visited: inout Set<Int>
 | 
					    _ visited: inout Set<ApkIndex.Index>
 | 
				
			||||||
  ) -> (ApkPackageGraphNode, ApkPackageGraphNode)? {
 | 
					  ) -> (ApkPackageGraphNode, ApkPackageGraphNode)? {
 | 
				
			||||||
    for dependency in node.children {
 | 
					    for dependency in node.children {
 | 
				
			||||||
      let depNode = self._nodes[dependency.packageID]
 | 
					      let depNode = self._nodes[dependency.packageID]
 | 
				
			||||||
@ -103,8 +88,8 @@ extension ApkPackageGraph {
 | 
				
			|||||||
    // Map all nodes to all of their children, remove any self dependencies
 | 
					    // Map all nodes to all of their children, remove any self dependencies
 | 
				
			||||||
    var working = self._nodes.reduce(into: [ApkPackageGraphNode: Set<ApkPackageGraphNode>]()) { d, node in
 | 
					    var working = self._nodes.reduce(into: [ApkPackageGraphNode: Set<ApkPackageGraphNode>]()) { d, node in
 | 
				
			||||||
      d[node] = Set(node.children.filter { child in
 | 
					      d[node] = Set(node.children.filter { child in
 | 
				
			||||||
        if case .dep(let version) = child.constraint {
 | 
					        if case .dependency = child.constraint {
 | 
				
			||||||
          !version.conflict && child.packageID != node.packageID
 | 
					          !child.versionSpec.isConflict && child.packageID != node.packageID
 | 
				
			||||||
        } else { false }
 | 
					        } else { false }
 | 
				
			||||||
      }.map { self._nodes[$0.packageID] })
 | 
					      }.map { self._nodes[$0.packageID] })
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -118,7 +103,7 @@ extension ApkPackageGraph {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    // Put all extra nodes into the working map, with an empty set
 | 
					    // Put all extra nodes into the working map, with an empty set
 | 
				
			||||||
    extras.forEach {
 | 
					    extras.forEach {
 | 
				
			||||||
      working[$0] = .init()
 | 
					      working[$0] = []
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    while !working.isEmpty {
 | 
					    while !working.isEmpty {
 | 
				
			||||||
 | 
				
			|||||||
@ -1,24 +1,31 @@
 | 
				
			|||||||
/*
 | 
					/*
 | 
				
			||||||
 * darwin-apk © 2024 Gay Pizza Specifications
 | 
					 * darwin-apk © 2024, 2025 Gay Pizza Specifications
 | 
				
			||||||
 * SPDX-License-Identifier: Apache-2.0
 | 
					 * SPDX-License-Identifier: Apache-2.0
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import Foundation
 | 
					import Foundation
 | 
				
			||||||
 | 
					
 | 
				
			||||||
public class ApkPackageGraphNode {
 | 
					public class ApkPackageGraphNode {
 | 
				
			||||||
 | 
					  public let packageID: ApkIndex.Index
 | 
				
			||||||
 | 
					  public var parentIDs = [ApkIndex.Index]()
 | 
				
			||||||
 | 
					  public var children: [ChildRef]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  private weak var _graph: ApkPackageGraph?
 | 
					  private weak var _graph: ApkPackageGraph?
 | 
				
			||||||
  let packageID: Int
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  //private var _parents = NSHashTable<ApkPackageGraphNode>.weakObjects()
 | 
					  public var package: ApkIndexPackage {
 | 
				
			||||||
  //private var _children = NSHashTable<ApkPackageGraphNode>.weakObjects()
 | 
					 | 
				
			||||||
  var parents = [ApkIndexRequirementRef]()
 | 
					 | 
				
			||||||
  var children: [ApkIndexRequirementRef]
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  var package: ApkIndexPackage {
 | 
					 | 
				
			||||||
    self._graph!.pkgIndex.packages[self.packageID]
 | 
					    self._graph!.pkgIndex.packages[self.packageID]
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					  public var parents: [ApkIndexPackage] {
 | 
				
			||||||
 | 
					    self.parentIDs.map { index in self._graph!.pkgIndex.packages[index] }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  public var childPackages: [ApkIndexPackage] {
 | 
				
			||||||
 | 
					    self.children.map { child in self._graph!.pkgIndex.packages[child.packageID] }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  internal init(_ graph: ApkPackageGraph, id: Int, children: [ApkIndexRequirementRef]) {
 | 
					  @inlinable public var isShallow: Bool { self.parentIDs.isEmpty }
 | 
				
			||||||
 | 
					  @inlinable public var isDeep: Bool { self.children.isEmpty }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  internal init(_ graph: ApkPackageGraph, id: Int, children: [ChildRef]) {
 | 
				
			||||||
    self._graph = graph
 | 
					    self._graph = graph
 | 
				
			||||||
    self.packageID = id
 | 
					    self.packageID = id
 | 
				
			||||||
    self.children = children
 | 
					    self.children = children
 | 
				
			||||||
@ -35,15 +42,42 @@ extension ApkPackageGraphNode: Equatable, Hashable {
 | 
				
			|||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extension ApkPackageGraphNode {
 | 
				
			||||||
 | 
					  public struct ChildRef {
 | 
				
			||||||
 | 
					    let constraint: Constraint
 | 
				
			||||||
 | 
					    let packageID: Int
 | 
				
			||||||
 | 
					    let versionSpec: ApkVersionSpecification
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  public enum Constraint {
 | 
				
			||||||
 | 
					    case dependency, installIf
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
extension ApkPackageGraphNode: CustomStringConvertible {
 | 
					extension ApkPackageGraphNode: CustomStringConvertible {
 | 
				
			||||||
  public var description: String {
 | 
					  public var description: String {
 | 
				
			||||||
    var result = "node[\(self.package.name)]"
 | 
					    let package = self.package
 | 
				
			||||||
    if !self.parents.isEmpty {
 | 
					    var result = "  \(package.nameDescription):\n"
 | 
				
			||||||
      result += ", parents[\(self.parents.lazy.map(\.description).joined(separator: ", "))]"
 | 
					    if !self.parentIDs.isEmpty {
 | 
				
			||||||
 | 
					      result += "    parents:\n"
 | 
				
			||||||
 | 
					      for parent in self.parents {
 | 
				
			||||||
 | 
					        result += "      \(parent.nameDescription)\n"
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    if !self.children.isEmpty {
 | 
					    if !self.children.isEmpty {
 | 
				
			||||||
      result += ", children[\(self.children.lazy.map(\.description).joined(separator: ", "))]"
 | 
					      result += "    children:\n"
 | 
				
			||||||
      
 | 
					      for child in self.children {
 | 
				
			||||||
 | 
					        let childPackage = self._graph!.pkgIndex.packages[child.packageID]
 | 
				
			||||||
 | 
					        result += "      "
 | 
				
			||||||
 | 
					        switch child.constraint {
 | 
				
			||||||
 | 
					        case .dependency: result += "dep="
 | 
				
			||||||
 | 
					        case .installIf: result += "installIf="
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        result += childPackage.nameDescription
 | 
				
			||||||
 | 
					        result += ", "
 | 
				
			||||||
 | 
					        result += child.versionSpec.description
 | 
				
			||||||
 | 
					        result += "\n"
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    return result
 | 
					    return result
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
				
			|||||||
@ -1,64 +0,0 @@
 | 
				
			|||||||
/*
 | 
					 | 
				
			||||||
 * darwin-apk © 2024 Gay Pizza Specifications
 | 
					 | 
				
			||||||
 * SPDX-License-Identifier: Apache-2.0
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
struct ApkIndexRequirementRef {
 | 
					 | 
				
			||||||
  private weak var _graph: ApkPackageGraph?
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  let packageID: Int
 | 
					 | 
				
			||||||
  let constraint: Constraint
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  init(_ graph: ApkPackageGraph, id: Int, constraint: Constraint) {
 | 
					 | 
				
			||||||
    self._graph = graph
 | 
					 | 
				
			||||||
    self.packageID = id
 | 
					 | 
				
			||||||
    self.constraint = constraint
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  var package: ApkIndexPackage {
 | 
					 | 
				
			||||||
    self._graph!.pkgIndex.packages[self.packageID]
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  func satisfied(by other: ApkVersionRequirement) -> Bool {
 | 
					 | 
				
			||||||
    true
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  
 | 
					 | 
				
			||||||
  func normalize() -> ApkIndexRequirementRef {
 | 
					 | 
				
			||||||
    .init(self._graph!, id: self.packageID, constraint: .dep(version: .any()))
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
extension ApkIndexRequirementRef: Equatable, Hashable {
 | 
					 | 
				
			||||||
  static func == (lhs: Self, rhs: Self) -> Bool {
 | 
					 | 
				
			||||||
    lhs.packageID == rhs.packageID && lhs.constraint == rhs.constraint
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  func hash(into hasher: inout Hasher) {
 | 
					 | 
				
			||||||
    self.packageID.hash(into: &hasher)
 | 
					 | 
				
			||||||
    self.constraint.hash(into: &hasher)
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
extension ApkIndexRequirementRef {
 | 
					 | 
				
			||||||
  enum Constraint: Hashable {
 | 
					 | 
				
			||||||
    case dep(version: ApkVersionSpecification)
 | 
					 | 
				
			||||||
    case provision
 | 
					 | 
				
			||||||
    case installIf(version: ApkVersionSpecification)
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
extension ApkIndexRequirementRef: CustomStringConvertible {
 | 
					 | 
				
			||||||
  var description: String {
 | 
					 | 
				
			||||||
    guard let package = self._graph?.pkgIndex.packages[self.packageID] else {
 | 
					 | 
				
			||||||
      return String()
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    return switch self.constraint {
 | 
					 | 
				
			||||||
    case .dep(let version):
 | 
					 | 
				
			||||||
      "dep=\(ApkVersionRequirement(name: package.name, spec: version))"
 | 
					 | 
				
			||||||
    case .provision:
 | 
					 | 
				
			||||||
      "provides=\(package.name)"
 | 
					 | 
				
			||||||
    case .installIf(let version):
 | 
					 | 
				
			||||||
      "installIf=\(ApkVersionRequirement(name: package.name, spec: version))"
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@ -1,5 +1,5 @@
 | 
				
			|||||||
/*
 | 
					/*
 | 
				
			||||||
 * darwin-apk © 2024 Gay Pizza Specifications
 | 
					 * darwin-apk © 2024, 2025 Gay Pizza Specifications
 | 
				
			||||||
 * SPDX-License-Identifier: Apache-2.0
 | 
					 * SPDX-License-Identifier: Apache-2.0
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -92,3 +92,14 @@ extension ApkVersionSpecification.Operator: CustomStringConvertible {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extension ApkVersionSpecification: CustomStringConvertible {
 | 
				
			||||||
 | 
					  var description: String {
 | 
				
			||||||
 | 
					    switch self {
 | 
				
			||||||
 | 
					      case .any(invert: false): "depend=any"
 | 
				
			||||||
 | 
					      case .any(invert: true): "conflict=any"
 | 
				
			||||||
 | 
					      case .constraint(invert: false, let op, let version): "depend\(op)\(version)"
 | 
				
			||||||
 | 
					      case .constraint(invert: true, let op, let version): "conflict\(op)\(version)"
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -1,5 +1,5 @@
 | 
				
			|||||||
/*
 | 
					/*
 | 
				
			||||||
 * darwin-apk © 2024 Gay Pizza Specifications
 | 
					 * darwin-apk © 2024, 2025 Gay Pizza Specifications
 | 
				
			||||||
 * SPDX-License-Identifier: Apache-2.0
 | 
					 * SPDX-License-Identifier: Apache-2.0
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -14,28 +14,47 @@ struct DpkGraphCommand: AsyncParsableCommand {
 | 
				
			|||||||
    let graph: ApkPackageGraph
 | 
					    let graph: ApkPackageGraph
 | 
				
			||||||
    do {
 | 
					    do {
 | 
				
			||||||
      let localRepositories = try await ApkRepositoriesConfig()
 | 
					      let localRepositories = try await ApkRepositoriesConfig()
 | 
				
			||||||
      graph = ApkPackageGraph(index: try await ApkIndexReader.resolve(localRepositories.repositories, fetch: .lazy))
 | 
					 | 
				
			||||||
      graph.buildGraphNode()
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      var timerStart = DispatchTime.now()
 | 
				
			||||||
 | 
					      graph = ApkPackageGraph(index:
 | 
				
			||||||
 | 
					        try await ApkIndexReader.resolve(localRepositories.repositories, fetch: .lazy))
 | 
				
			||||||
 | 
					      print("Index build took \(timerStart.distance(to: .now()).seconds) seconds")
 | 
				
			||||||
      try graph.pkgIndex.description.write(to: URL(filePath: "packages.txt"), atomically: false, encoding: .utf8)
 | 
					      try graph.pkgIndex.description.write(to: URL(filePath: "packages.txt"), atomically: false, encoding: .utf8)
 | 
				
			||||||
    } catch {
 | 
					 | 
				
			||||||
      fatalError(error.localizedDescription)
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
#if false
 | 
					      timerStart = DispatchTime.now()
 | 
				
			||||||
    if var out = TextFileWriter(URL(filePath: "shallowIsolates.txt")) {
 | 
					      graph.buildGraphNode()
 | 
				
			||||||
      for node in graph.shallowIsolates { print(node, to: &out) }
 | 
					      print("Graph build took \(timerStart.distance(to: .now()).seconds) seconds")
 | 
				
			||||||
    }
 | 
					
 | 
				
			||||||
    if var out = TextFileWriter(URL(filePath: "deepIsolates.txt")) {
 | 
					      try graph.shallowIsolates.map { $0.package.nameDescription }.joined(separator: "\n")
 | 
				
			||||||
      for node in graph.deepIsolates { print(node, to: &out) }
 | 
					        .write(to: URL(filePath: "shallowIsolates.txt"), atomically: false, encoding: .utf8)
 | 
				
			||||||
    }
 | 
					      try graph.deepIsolates.map { $0.package.nameDescription }.joined(separator: "\n")
 | 
				
			||||||
#else
 | 
					        .write(to: URL(filePath: "deepIsolates.txt"), atomically: false, encoding: .utf8)
 | 
				
			||||||
    do {
 | 
					
 | 
				
			||||||
      let sorted = try graph.parallelOrderSort()
 | 
					      let sorted = try graph.parallelOrderSort()
 | 
				
			||||||
      print(sorted)
 | 
					      if var out = TextFileWriter(URL(filePath: "sorted.txt")) {
 | 
				
			||||||
 | 
					        for (i, set) in sorted.enumerated() {
 | 
				
			||||||
 | 
					          print("\(i):\n", to: &out)
 | 
				
			||||||
 | 
					          for item in set {
 | 
				
			||||||
 | 
					            print("\(item.description)", to: &out)
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
    } catch {
 | 
					    } catch {
 | 
				
			||||||
      fatalError(error.localizedDescription)
 | 
					      fatalError(error.localizedDescription)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
#endif
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					fileprivate extension DispatchTimeInterval {
 | 
				
			||||||
 | 
					  var seconds: Double {
 | 
				
			||||||
 | 
					    switch self {
 | 
				
			||||||
 | 
					    case .seconds(let value):      Double(value)
 | 
				
			||||||
 | 
					    case .milliseconds(let value): Double(value) / 1_000
 | 
				
			||||||
 | 
					    case .microseconds(let value): Double(value) / 1_000_000
 | 
				
			||||||
 | 
					    case .nanoseconds(let value):  Double(value) / 1_000_000_000
 | 
				
			||||||
 | 
					    case .never: .infinity
 | 
				
			||||||
 | 
					    @unknown default:
 | 
				
			||||||
 | 
					    fatalError("Unsupported")
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user