From 7b34f1db7f11706242db45fef23b43074b02c6d9 Mon Sep 17 00:00:00 2001 From: Jake Teton-Landis Date: Thu, 29 Dec 2022 23:38:25 -0800 Subject: [PATCH] remove dead code --- Gauss.xcodeproj/project.pbxproj | 12 +- Gauss/GaussKernel.swift | 22 -- .../{JobQueue.swift => ObservableTask.swift} | 297 ++---------------- 3 files changed, 25 insertions(+), 306 deletions(-) rename Gauss/{JobQueue.swift => ObservableTask.swift} (54%) diff --git a/Gauss.xcodeproj/project.pbxproj b/Gauss.xcodeproj/project.pbxproj index 972318f..21cc65f 100644 --- a/Gauss.xcodeproj/project.pbxproj +++ b/Gauss.xcodeproj/project.pbxproj @@ -29,7 +29,7 @@ C161F21B293E6394007F518C /* PromptComposer.swift in Sources */ = {isa = PBXBuildFile; fileRef = C161F21A293E6394007F518C /* PromptComposer.swift */; }; C161F21D293E96A5007F518C /* ResultsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C161F21C293E96A5007F518C /* ResultsView.swift */; }; C161F21F29404AF8007F518C /* DraggableZoomable.swift in Sources */ = {isa = PBXBuildFile; fileRef = C161F21E29404AF8007F518C /* DraggableZoomable.swift */; }; - C161F23C29469628007F518C /* JobQueue.swift in Sources */ = {isa = PBXBuildFile; fileRef = C161F23B29469628007F518C /* JobQueue.swift */; }; + C161F23C29469628007F518C /* ObservableTask.swift in Sources */ = {isa = PBXBuildFile; fileRef = C161F23B29469628007F518C /* ObservableTask.swift */; }; C1825334293BFBFB0038E152 /* StableDiffusion in Frameworks */ = {isa = PBXBuildFile; productRef = C1825333293BFBFB0038E152 /* StableDiffusion */; }; C1825336293BFE1A0038E152 /* ProgressView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1825335293BFE1A0038E152 /* ProgressView.swift */; }; /* End PBXBuildFile section */ @@ -68,8 +68,8 @@ C10A46A8293BB0C9005CEE6D /* PromptView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PromptView.swift; sourceTree = ""; }; C10A46AA293BC512005CEE6D /* ResultView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ResultView.swift; sourceTree = ""; }; C10A46AE293BD460005CEE6D /* GaussKernel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GaussKernel.swift; sourceTree = ""; }; - C146989A295EB57A0025DE55 /* sd1.4 */ = {isa = PBXFileReference; lastKnownFileType = file; name = sd1.4; path = "compiled-models/sd1.4"; sourceTree = SOURCE_ROOT; }; - C146989C295EB5A10025DE55 /* sd1.5 */ = {isa = PBXFileReference; lastKnownFileType = file; name = sd1.5; path = "compiled-models/sd1.5"; sourceTree = SOURCE_ROOT; }; + C146989A295EB57A0025DE55 /* sd1.4 */ = {isa = PBXFileReference; lastKnownFileType = folder; name = sd1.4; path = "compiled-models/sd1.4"; sourceTree = SOURCE_ROOT; }; + C146989C295EB5A10025DE55 /* sd1.5 */ = {isa = PBXFileReference; lastKnownFileType = folder; name = sd1.5; path = "compiled-models/sd1.5"; sourceTree = SOURCE_ROOT; }; C146989E295EB5AA0025DE55 /* sd2 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = sd2; path = "compiled-models/sd2"; sourceTree = SOURCE_ROOT; }; C161F210293C31DF007F518C /* KernelStatusView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KernelStatusView.swift; sourceTree = ""; }; C161F212293C945F007F518C /* AddPromptButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddPromptButton.swift; sourceTree = ""; }; @@ -78,7 +78,7 @@ C161F21A293E6394007F518C /* PromptComposer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PromptComposer.swift; sourceTree = ""; }; C161F21C293E96A5007F518C /* ResultsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ResultsView.swift; sourceTree = ""; }; C161F21E29404AF8007F518C /* DraggableZoomable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DraggableZoomable.swift; sourceTree = ""; }; - C161F23B29469628007F518C /* JobQueue.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JobQueue.swift; sourceTree = ""; }; + C161F23B29469628007F518C /* ObservableTask.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ObservableTask.swift; sourceTree = ""; }; C1825335293BFE1A0038E152 /* ProgressView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProgressView.swift; sourceTree = ""; }; /* End PBXFileReference section */ @@ -136,7 +136,7 @@ C10A467A293B190F005CEE6D /* GaussApp.swift */, C10A467C293B190F005CEE6D /* GaussDocument.swift */, C10A46AE293BD460005CEE6D /* GaussKernel.swift */, - C161F23B29469628007F518C /* JobQueue.swift */, + C161F23B29469628007F518C /* ObservableTask.swift */, C10A467E293B190F005CEE6D /* ContentView.swift */, C161F21A293E6394007F518C /* PromptComposer.swift */, C161F210293C31DF007F518C /* KernelStatusView.swift */, @@ -336,7 +336,7 @@ C161F21D293E96A5007F518C /* ResultsView.swift in Sources */, C10A46A9293BB0C9005CEE6D /* PromptView.swift in Sources */, C161F211293C31DF007F518C /* KernelStatusView.swift in Sources */, - C161F23C29469628007F518C /* JobQueue.swift in Sources */, + C161F23C29469628007F518C /* ObservableTask.swift in Sources */, C10A467D293B190F005CEE6D /* GaussDocument.swift in Sources */, C10A46AB293BC512005CEE6D /* ResultView.swift in Sources */, C10A467B293B190F005CEE6D /* GaussApp.swift in Sources */, diff --git a/Gauss/GaussKernel.swift b/Gauss/GaussKernel.swift index 23ce353..caea349 100644 --- a/Gauss/GaussKernel.swift +++ b/Gauss/GaussKernel.swift @@ -58,36 +58,14 @@ class PreloadModelJob: ObservableTask { } struct GaussKernelResources { - let sourceCodeRoot = "/Users/jitl/src/gauss/compiled-models" - - var sourceCodeURL: URL { - URL(filePath: sourceCodeRoot, directoryHint: .isDirectory) - } - - func fromSourceCode(modelName: String) -> URL { - return sourceCodeURL.appending(components: modelName, "Resources") - } - - var sd2Sources: URL { - return fromSourceCode(modelName: "sd2-base") - } - var sd2Production: URL { return Bundle.main.url(forResource: "sd2", withExtension: nil)! } - var sd14Sources: URL { - return fromSourceCode(modelName: "sd1.4") - } - var sd14Production: URL { return Bundle.main.url(forResource: "sd1.4", withExtension: nil)! } - var sd15Sources: URL { - return fromSourceCode(modelName: "sd1.5") - } - var sd15Production: URL { return Bundle.main.url(forResource: "sd1.5", withExtension: nil)! } diff --git a/Gauss/JobQueue.swift b/Gauss/ObservableTask.swift similarity index 54% rename from Gauss/JobQueue.swift rename to Gauss/ObservableTask.swift index d301ab0..ae5d21d 100644 --- a/Gauss/JobQueue.swift +++ b/Gauss/ObservableTask.swift @@ -8,7 +8,7 @@ import Foundation import SwiftUI -enum QueueJobState { +enum ObservableTaskState { case pending case running case progress(P) @@ -16,7 +16,7 @@ enum QueueJobState { case error(Error) case cancelled(reason: String) - var erased: QueueJobState { + var erased: ObservableTaskState { switch self { case .pending: return .pending case .running: return .running @@ -54,7 +54,7 @@ enum QueueJobState { @MainActor class ObservableTaskTracker: ObservableObject { - @Published var jobs: [UUID: any ObservableTaskProtocol] = [:] + @Published var jobs = ObservableTaskDictionary() func insert(job: any ObservableTaskProtocol) { jobs[job.id] = job @@ -85,7 +85,7 @@ extension ObservableTaskDictionary { } mutating func remove(job: any ObservableTaskProtocol) { - self.removeValue(forKey: job.id) + removeValue(forKey: job.id) } @MainActor @@ -104,50 +104,7 @@ extension ObservableTaskDictionary { } func ofType(_ type: T.Type) -> [UUID: T] { - self.compactMapValues { v in v as? T } - } -} - -class JobQueue: ObservableObject { - @Published var jobs: [UUID: any QueueJobProtocol] = [:] - let dispatchQueue: DispatchQueue - - init(label: String) { - dispatchQueue = DispatchQueue(label: label, qos: .userInitiated) - } - - func insert(job: any QueueJobProtocol) { - job.queue = self - jobs[job.id] = job - } - - func remove(job: any QueueJobProtocol) { - jobs.removeValue(forKey: job.id) - job.queue = nil - } - - func async(job: QueueJob, completionHandler: @escaping (QueueJob) -> Void) { - insert(job: job) - dispatchQueue.async { - job.work { _ in - if case .complete = job.state { - self.remove(job: job) - } - completionHandler(job) - } - } - } - - var pending: [UUID: any QueueJobProtocol] { - self.jobs.filter { _, v in v.pending } - } - - var running: [UUID: any QueueJobProtocol] { - self.jobs.filter { _, v in v.running } - } - - var finalized: [UUID: any QueueJobProtocol] { - self.jobs.filter { _, v in v.finalized } + compactMapValues { v in v as? T } } } @@ -156,50 +113,7 @@ enum QueueJobError: Error { case dependencyCancelled(String) } -protocol QueueJobProtocol: Identifiable, ObservableObject { - var id: UUID { get } - var queue: JobQueue? { get set } - var label: String { get } - var dependsOn: Set { get } - var anyState: QueueJobState { - get - } -} - -extension QueueJobProtocol { - var pending: Bool { - return !running && !finalized - } - - var running: Bool { - switch anyState { - case .progress: return true - case .running: return true - default: return false - } - } - - var finalized: Bool { - switch anyState { - case .cancelled: fallthrough - case .error: fallthrough - case .complete: return true - case .pending: return false - case .running: return false - case .progress: return false - } - } - - var cancelled: Bool { - switch anyState { - case .cancelled: return true - default: return false - } - } -} - -var tokens = [UUID: CheckedContinuation]() - +/// a Task that can be manually fulfilled with a result by external code. class FulfillableTask { typealias Failure = any Error typealias Continuation = CheckedContinuation, Never> @@ -264,22 +178,24 @@ protocol Waitable { extension Task: Waitable { func wait() async { - _ = await self.result + _ = await result } } extension DeferredTask: Waitable { func wait() async { - await self.task.wait() + await task.wait() } } extension FulfillableTask: Waitable { func wait() async { - await self.task.wait() + await task.wait() } } +/// An async Task that only starts to execute once `resume` is called. +/// Callers may wait for the task indefinitely via `deferred.task.value`. struct DeferredTask { public let operation: () async throws -> Success @@ -320,6 +236,8 @@ struct DeferredTask { } } +/// Ensure that only a single enqueued task is running at a time. +/// The intention is to mimic the semantics of DispatchQueue with Swift Concurrency. actor AsyncQueue { var queue = [any ObservableTaskProtocol]() var current: (any ObservableTaskProtocol)? @@ -349,30 +267,18 @@ actor AsyncQueue { } } -actor Protected { - var value: T - - init(value: T) { - self.value = value - } - - func use(_ fn: () async throws -> R) async rethrows -> R { - return try await fn() - } -} - protocol ObservableTaskProtocol: ObservableObject, Identifiable { var id: UUID { get } var createdAt: Date { get } var label: String { get } - @MainActor var anyState: QueueJobState { get } + @MainActor var anyState: ObservableTaskState { get } @discardableResult func resume() -> Self func wait() async func cancel() } extension ObservableTask: ObservableTaskProtocol { - @MainActor var anyState: QueueJobState { + @MainActor var anyState: ObservableTaskState { return state.erased } @@ -381,6 +287,8 @@ extension ObservableTask: ObservableTaskProtocol { } } +/// An ObservableTask is a Task-like abstraction that reports its progress via a published property on the main thread. +/// ObservableTasks are deferred; they begin executing once `observableTask.resume()` is called. class ObservableTask: ObservableObject, Identifiable { typealias Perform = (ObservableTask) async throws -> Success @@ -388,7 +296,7 @@ class ObservableTask: ObservableObject, I let createdAt = Date.now let label: String let fn: Perform - @MainActor @Published var state: QueueJobState = .pending + @MainActor @Published var state: ObservableTaskState = .pending @MainActor @Published var waitingFor = ObservableTaskDictionary() init(_ label: String, _ fn: @escaping Perform) { @@ -446,7 +354,7 @@ class ObservableTask: ObservableObject, I } func cancel() { - self.cancel(reason: "Unknown") + cancel(reason: "Unknown") } func onSuccess(_ handler: @escaping (Success) -> Void) -> Self { @@ -473,170 +381,3 @@ class ObservableTask: ObservableObject, I return self } } - -// actor AsyncJobQueue { -// -// -// func execute(job: ObservableTask, fn: @escaping (ObservableTask) async throws -> R) async { -// let task = Task { -// let currentState = await job.state -// guard case .pending = currentState else { -// throw QueueJobError.invalidState("Expected pending job, but was \(currentState)") -// } -// -// do { -// await MainActor.run { job.state = .running } -// let result = try await fn(job) -// await MainActor.run { job.state = .complete(result) } -// return result -// } catch { -// await MainActor.run { job.state = .error(error) } -// throw error -// } -// } -// -// await MainActor.run { -// job.task = task -// } -// } -// } - -class QueueJob: Identifiable, ObservableObject, QueueJobProtocol { - var anyState: QueueJobState { - switch state { - case .complete(let result): - return .complete(result) - case .progress(let progress): - return .progress(progress) - case .pending: return .pending - case .running: return .running - case .error(let error): return .error(error) - case .cancelled(reason: let reason): return .cancelled(reason: reason) - } - } - - typealias Perform = (_ job: QueueJob) throws -> R - let id = UUID() - let label: String - var queue: JobQueue? - var execute: Perform - @Published var state: QueueJobState - @Published var dependsOn: Set = [] - - init(label: String, state: QueueJobState, execute: @escaping Perform) { - self.label = label - self.state = state - self.execute = execute - Task { print("hi") } - } - - convenience init(_ label: String, _ execute: @escaping Perform) { - self.init(label: label, state: .pending, execute: execute) - } - - func runSubtask(_ job: QueueJob) throws -> R { - if job.finalized { - return try job.unwrap() - } - - onMainAsync { - self.dependsOn.insert(job.id) - if let queue = self.queue { - queue.insert(job: job) - } - } - - job.work { _ in } - - onMainAsync { - self.dependsOn.remove(job.id) - } - - return try job.unwrap() - } - - func reportProgress(_ next: P) { - onMainAsync { - self.state = .progress(next) - } - } - - func cancel(reason: String) { - onMainAsync { - self.state = .cancelled(reason: reason) - } - } - - private func onMainAsync(_ run: @escaping () -> Void) { - if Thread.isMainThread { - run() - } else { - DispatchQueue.main.async { - run() - } - } - } - - func unwrap() throws -> R { - switch state { - case .complete(let result): - return result - case .cancelled(let reason): - throw QueueJobError.dependencyCancelled(reason) - case .error(let error): throw error - default: - throw QueueJobError.invalidState("Job not finalized: \(state)") - } - } - - func work(_ completionHandler: @escaping (QueueJob) -> Void) { - guard !(running || finalized) else { - let currentState = state - onMainAsync { - self.state = .error(QueueJobError.invalidState("Must be .pending to start, but was: \(currentState)")) - } - return - } - - onMainAsync { - self.state = .running - } - - do { - let result = try execute(self) - onMainAsync { - self.state = .complete(result) - completionHandler(self) - } - } catch { - onMainAsync { - self.state = .error(error) - completionHandler(self) - } - } - } -} - -/* - - func generateImage(params) { - var generateJob = Job { job in - let pipeline = job.runSubtask(Job("Get pileline") { getPipelineWorker() }) - let result = pipeline.run(params) { progress in - job.reportProgress(progress) - } - return result - } - generateJob.completionHandler = generateJob - queue.enqueue(generateJob) - return generateJob - } - - func getPipelineWorker() { - if let pipeline = storage.get(pipeline) { - return pipeline - } - return actuallyCreatePipeline() - } - - */