From a29a889961d816c7ff7750c743024cc7b6ca5cbe Mon Sep 17 00:00:00 2001 From: Vanderlei Martinelli Date: Sun, 6 May 2018 20:39:20 -0300 Subject: [PATCH 01/13] Minor comment change to TaskCondition --- .../Conditions and Dependencies/TaskCondition.swift | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/Source/AlecrimAsyncKit/Conditions and Dependencies/TaskCondition.swift b/Source/AlecrimAsyncKit/Conditions and Dependencies/TaskCondition.swift index e269b36..213738d 100644 --- a/Source/AlecrimAsyncKit/Conditions and Dependencies/TaskCondition.swift +++ b/Source/AlecrimAsyncKit/Conditions and Dependencies/TaskCondition.swift @@ -14,18 +14,14 @@ import Foundation // example: // // extension Reachability: TaskCondition { -// func evaluate() -> Task { -// return conditionAsync { conditionTask in -// self.whenReachable { -// conditionTask.finish(with: true) -// } -// } +// public func evaluate() -> Task { +// return conditionAsync { self.connection != .none } // } // } // // ... // -// async(condition: Reachability()) { ... } +// async(condition: self.reachability) { ... } // public protocol TaskCondition { From c962e293ab314ca45379448b6580d56adb9f2898 Mon Sep 17 00:00:00 2001 From: Vanderlei Martinelli Date: Sun, 6 May 2018 20:40:00 -0300 Subject: [PATCH 02/13] Changed the max concurrent operation count for operation queues --- Source/AlecrimAsyncKit/Core/Queue.swift | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/Source/AlecrimAsyncKit/Core/Queue.swift b/Source/AlecrimAsyncKit/Core/Queue.swift index 906a413..c583220 100644 --- a/Source/AlecrimAsyncKit/Core/Queue.swift +++ b/Source/AlecrimAsyncKit/Core/Queue.swift @@ -10,11 +10,14 @@ import Foundation internal /* namespace */ enum Queue { + //private static let defaultMaxConcurrentOperationCount = ProcessInfo().activeProcessorCount * 2 + private static let defaultMaxConcurrentOperationCount = OperationQueue.defaultMaxConcurrentOperationCount + internal static let defaultOperationQueue: OperationQueue = { let queue = OperationQueue() queue.name = "com.alecrim.AlecrimAsyncKit.Task" queue.qualityOfService = .utility - queue.maxConcurrentOperationCount = ProcessInfo().activeProcessorCount * 2 + queue.maxConcurrentOperationCount = Queue.defaultMaxConcurrentOperationCount return queue }() @@ -23,14 +26,14 @@ internal /* namespace */ enum Queue { let queue = OperationQueue() queue.name = "com.alecrim.AlecrimAsyncKit.TaskAwaiter" queue.qualityOfService = .utility - queue.maxConcurrentOperationCount = ProcessInfo().activeProcessorCount * 2 + queue.maxConcurrentOperationCount = Queue.defaultMaxConcurrentOperationCount return queue }() internal static func operationQueue(for dispatchQueue: DispatchQueue) -> OperationQueue { let operationQueue = OperationQueue() - operationQueue.maxConcurrentOperationCount = ProcessInfo().activeProcessorCount * 2 + operationQueue.maxConcurrentOperationCount = Queue.defaultMaxConcurrentOperationCount operationQueue.underlyingQueue = dispatchQueue return operationQueue @@ -42,7 +45,7 @@ internal /* namespace */ enum Queue { let queue = OperationQueue() queue.name = "com.alecrim.AlecrimAsyncKit.TaskCondition" queue.qualityOfService = .utility - queue.maxConcurrentOperationCount = ProcessInfo().activeProcessorCount * 2 + queue.maxConcurrentOperationCount = Queue.defaultMaxConcurrentOperationCount return queue }() From ef54308160422a9f705685d4eca5ceca3545ca73 Mon Sep 17 00:00:00 2001 From: Vanderlei Martinelli Date: Sun, 6 May 2018 20:40:31 -0300 Subject: [PATCH 03/13] Removed commented code --- Source/AlecrimAsyncKit/Core/Queue.swift | 1 - 1 file changed, 1 deletion(-) diff --git a/Source/AlecrimAsyncKit/Core/Queue.swift b/Source/AlecrimAsyncKit/Core/Queue.swift index c583220..38b7ac3 100644 --- a/Source/AlecrimAsyncKit/Core/Queue.swift +++ b/Source/AlecrimAsyncKit/Core/Queue.swift @@ -10,7 +10,6 @@ import Foundation internal /* namespace */ enum Queue { - //private static let defaultMaxConcurrentOperationCount = ProcessInfo().activeProcessorCount * 2 private static let defaultMaxConcurrentOperationCount = OperationQueue.defaultMaxConcurrentOperationCount internal static let defaultOperationQueue: OperationQueue = { From 352631c36805e68d26aa11e296bcc289a6fa84fd Mon Sep 17 00:00:00 2001 From: Vanderlei Martinelli Date: Mon, 7 May 2018 01:36:44 -0300 Subject: [PATCH 04/13] Added simple mapping capability --- .../AlecrimAsyncKit.xcodeproj/project.pbxproj | 4 ++ .../AlecrimAsyncKit/Convenience/Mapping.swift | 68 +++++++++++++++++++ 2 files changed, 72 insertions(+) create mode 100644 Source/AlecrimAsyncKit/Convenience/Mapping.swift diff --git a/Source/AlecrimAsyncKit.xcodeproj/project.pbxproj b/Source/AlecrimAsyncKit.xcodeproj/project.pbxproj index f4128b4..79f9695 100644 --- a/Source/AlecrimAsyncKit.xcodeproj/project.pbxproj +++ b/Source/AlecrimAsyncKit.xcodeproj/project.pbxproj @@ -22,6 +22,7 @@ 1466506C205B178F006C70AA /* Sequence+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1466506B205B178F006C70AA /* Sequence+Extensions.swift */; }; 1466506E205B1905006C70AA /* OtherConveniences.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1466506D205B1905006C70AA /* OtherConveniences.swift */; }; 14A391242053A03300AD8249 /* Cancellation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 14A391232053A03300AD8249 /* Cancellation.swift */; }; + 14E8AD3B209FF6F20035DFA2 /* Mapping.swift in Sources */ = {isa = PBXBuildFile; fileRef = 14E8AD3A209FF6F20035DFA2 /* Mapping.swift */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ @@ -42,6 +43,7 @@ 1466506B205B178F006C70AA /* Sequence+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Sequence+Extensions.swift"; sourceTree = ""; }; 1466506D205B1905006C70AA /* OtherConveniences.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OtherConveniences.swift; sourceTree = ""; }; 14A391232053A03300AD8249 /* Cancellation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Cancellation.swift; sourceTree = ""; }; + 14E8AD3A209FF6F20035DFA2 /* Mapping.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Mapping.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -121,6 +123,7 @@ 14665067205B1727006C70AA /* DispatchQueue+Extensions.swift */, 14665065205B1708006C70AA /* OperationQueue+Extensions.swift */, 1466506D205B1905006C70AA /* OtherConveniences.swift */, + 14E8AD3A209FF6F20035DFA2 /* Mapping.swift */, 1466506B205B178F006C70AA /* Sequence+Extensions.swift */, ); path = Convenience; @@ -215,6 +218,7 @@ 14665068205B1727006C70AA /* DispatchQueue+Extensions.swift in Sources */, 14665066205B1708006C70AA /* OperationQueue+Extensions.swift in Sources */, 143E712520531FBC002F7222 /* Async.swift in Sources */, + 14E8AD3B209FF6F20035DFA2 /* Mapping.swift in Sources */, 143E712320531F9B002F7222 /* Errors.swift in Sources */, 1444522A209E09200016D444 /* TaskDependency.swift in Sources */, 1466506A205B1763006C70AA /* Availability.swift in Sources */, diff --git a/Source/AlecrimAsyncKit/Convenience/Mapping.swift b/Source/AlecrimAsyncKit/Convenience/Mapping.swift new file mode 100644 index 0000000..06bc5dd --- /dev/null +++ b/Source/AlecrimAsyncKit/Convenience/Mapping.swift @@ -0,0 +1,68 @@ +// +// Mapping.swift +// AlecrimAsyncKit +// +// Created by Vanderlei Martinelli on 06/05/18. +// Copyright © 2018 Alecrim. All rights reserved. +// + +import Foundation + +// MARK: - + +extension Task { + + public func map(in queue: OperationQueue? = nil, closure: @escaping (Value) throws -> U) -> Task { + return async(in: queue) { + let value = try self.await() + let mappedValue = try closure(value) + + return mappedValue + } + } + + public func map(in queue: OperationQueue? = nil, closure: @escaping (Value) -> U) -> Task { + return async(in: queue) { + let value = try self.await() + let mappedValue = closure(value) + + return mappedValue + } + } + +} + +extension Task { + + public func asNonFailable(in queue: OperationQueue? = nil) -> NonFailableTask { + return async(in: queue) { + return try! self.await() + } + } + +} + +// MARK: - + +extension NonFailableTask { + + public func map(in queue: OperationQueue? = nil, closure: @escaping (Value) -> U) -> NonFailableTask { + return async(in: queue) { + let value = try! self.await() + let mappedValue = closure(value) + + return mappedValue + } + } + +} + +extension NonFailableTask { + + public func asFailable(in queue: OperationQueue? = nil) -> Task { + return async(in: queue) { + return try self.await() + } + } + +} From 816cbe47b14352a65bf5cadd85a3ad6c91a7e8fe Mon Sep 17 00:00:00 2001 From: Vanderlei Martinelli Date: Mon, 7 May 2018 01:37:55 -0300 Subject: [PATCH 05/13] Changed `TaskCondition to be not necessarily dependent on another asynchronous task --- .../TaskCondition.swift | 68 ++++++++----------- Source/AlecrimAsyncKit/Core/Task.swift | 18 ++--- 2 files changed, 36 insertions(+), 50 deletions(-) diff --git a/Source/AlecrimAsyncKit/Conditions and Dependencies/TaskCondition.swift b/Source/AlecrimAsyncKit/Conditions and Dependencies/TaskCondition.swift index 213738d..f0b57f9 100644 --- a/Source/AlecrimAsyncKit/Conditions and Dependencies/TaskCondition.swift +++ b/Source/AlecrimAsyncKit/Conditions and Dependencies/TaskCondition.swift @@ -14,8 +14,8 @@ import Foundation // example: // // extension Reachability: TaskCondition { -// public func evaluate() -> Task { -// return conditionAsync { self.connection != .none } +// public func evaluate() -> Bool { +// return self.connection != .none // } // } // @@ -25,17 +25,8 @@ import Foundation // public protocol TaskCondition { - func evaluate() -> Task -} - -// MARK: - - -public func conditionAsync(execute closure: @escaping AsyncTaskClosure) -> Task { - return async(in: Queue.taskConditionOperationQueue, execute: closure) -} - -public func conditionAsync(execute taskClosure: @escaping AsyncTaskFullClosure) -> Task { - return async(in: Queue.taskConditionOperationQueue, execute: taskClosure) + // this will always be executed on a background thread, so the result does not need to me immediately computed + func evaluate() -> Bool } // MARK: - @@ -43,10 +34,13 @@ public func conditionAsync(execute taskClosure: @escaping AsyncTaskFullClosure Task { - return conditionAsync { + public func evaluate() -> Bool { + do { return try self.await() } + catch { + return false + } } } @@ -100,35 +94,33 @@ public final class CompoundTaskCondition: TaskCondition { self.subconditions = subconditions } - public func evaluate() -> Task { - return conditionAsync { - switch self.compoundTaskConditionType { - case .and: - var all = true - for subcondition in self.subconditions { - if !(try await(subcondition.evaluate())) { - all = false - break - } + public func evaluate() -> Bool { + switch self.compoundTaskConditionType { + case .and: + var all = true + for subcondition in self.subconditions { + if !subcondition.evaluate() { + all = false + break } + } - return all + return all - case .or: - var any = false - for subcondition in self.subconditions { - if (try await(subcondition.evaluate())) { - any = true - break - } + case .or: + var any = false + for subcondition in self.subconditions { + if subcondition.evaluate() { + any = true + break } + } - return any + return any - case .not: - let subcondition = self.subconditions.first! - return !(try await(subcondition.evaluate())) - } + case .not: + let subcondition = self.subconditions.first! + return !subcondition.evaluate() } } diff --git a/Source/AlecrimAsyncKit/Core/Task.swift b/Source/AlecrimAsyncKit/Core/Task.swift index b4a5ad0..a6cf706 100644 --- a/Source/AlecrimAsyncKit/Core/Task.swift +++ b/Source/AlecrimAsyncKit/Core/Task.swift @@ -60,13 +60,7 @@ public class BaseTask { private func _start() { if let condition = self.condition { - var result = false - do { - result = try AlecrimAsyncKit.await(condition.evaluate()) - } - catch {} - - if result { + if condition.evaluate() { self.__start() } else { @@ -93,13 +87,13 @@ public class BaseTask { internal final func await() throws -> Value { self.wait() - guard let value = self.value else { - guard let error = self.error else { - fatalError("Unexpected: error cannot be nil") - } - + if let error = self.error { throw error } + + guard let value = self.value else { + fatalError("Unexpected: error cannot be nil") + } return value } From 26805d2c38972ea18e654361eb0c60a1e1e0cd45 Mon Sep 17 00:00:00 2001 From: Vanderlei Martinelli Date: Mon, 7 May 2018 02:20:09 -0300 Subject: [PATCH 06/13] Ensuring task `value` and `error` consistence --- Source/AlecrimAsyncKit/Core/Task.swift | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Source/AlecrimAsyncKit/Core/Task.swift b/Source/AlecrimAsyncKit/Core/Task.swift index a6cf706..ac97518 100644 --- a/Source/AlecrimAsyncKit/Core/Task.swift +++ b/Source/AlecrimAsyncKit/Core/Task.swift @@ -88,11 +88,12 @@ public class BaseTask { self.wait() if let error = self.error { + self.value = nil // to be sure throw error } guard let value = self.value else { - fatalError("Unexpected: error cannot be nil") + fatalError("Unexpected: value cannot be nil") } return value From f28545f28f616e07568b52a52a99425a8e3c3934 Mon Sep 17 00:00:00 2001 From: Vanderlei Martinelli Date: Mon, 7 May 2018 02:22:19 -0300 Subject: [PATCH 07/13] Greater security to access value or error at the end --- Source/AlecrimAsyncKit/Core/Task.swift | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/Source/AlecrimAsyncKit/Core/Task.swift b/Source/AlecrimAsyncKit/Core/Task.swift index ac97518..5229151 100644 --- a/Source/AlecrimAsyncKit/Core/Task.swift +++ b/Source/AlecrimAsyncKit/Core/Task.swift @@ -87,16 +87,20 @@ public class BaseTask { internal final func await() throws -> Value { self.wait() - if let error = self.error { - self.value = nil // to be sure - throw error - } + do { + self.lock(); defer { self.unlock() } + + if let error = self.error { + self.value = nil // to be sure + throw error + } - guard let value = self.value else { - fatalError("Unexpected: value cannot be nil") + guard let value = self.value else { + fatalError("Unexpected: value cannot be nil") + } + + return value } - - return value } // From d267bfaa7f2ec177ae6c6e1303ff596a3c03d661 Mon Sep 17 00:00:00 2001 From: Vanderlei Martinelli Date: Wed, 9 May 2018 05:25:37 -0300 Subject: [PATCH 08/13] Minor changes --- Source/AlecrimAsyncKit/Core/Cancellation.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/AlecrimAsyncKit/Core/Cancellation.swift b/Source/AlecrimAsyncKit/Core/Cancellation.swift index bf42069..2953ae5 100644 --- a/Source/AlecrimAsyncKit/Core/Cancellation.swift +++ b/Source/AlecrimAsyncKit/Core/Cancellation.swift @@ -1,5 +1,5 @@ // -// File.swift +// Cancellation.swift // AlecrimAsyncKit // // Created by Vanderlei Martinelli on 10/03/18. @@ -14,7 +14,7 @@ public typealias CancellationHandler = () -> Void // -public protocol CancellableTask: class { +public protocol CancellableTask: AnyObject { var cancellation: Cancellation { get } var isCancelled: Bool { get } From 89a9c6b731f682f987a14234b4ef6d11b9760f3e Mon Sep 17 00:00:00 2001 From: Vanderlei Martinelli Date: Sun, 20 May 2018 20:46:37 -0300 Subject: [PATCH 09/13] Changed preposition "in" to "on" in parameter names --- .../Convenience/Availability.swift | 12 ++-- .../DispatchQueue+Extensions.swift | 8 +-- .../AlecrimAsyncKit/Convenience/Mapping.swift | 20 +++---- .../OperationQueue+Extensions.swift | 8 +-- .../Convenience/OtherConveniences.swift | 56 +++++++++---------- Source/AlecrimAsyncKit/Core/Async.swift | 28 +++++----- Source/AlecrimAsyncKit/Core/TaskAwaiter.swift | 12 ++-- 7 files changed, 72 insertions(+), 72 deletions(-) diff --git a/Source/AlecrimAsyncKit/Convenience/Availability.swift b/Source/AlecrimAsyncKit/Convenience/Availability.swift index 0b56bdd..e0cced7 100644 --- a/Source/AlecrimAsyncKit/Convenience/Availability.swift +++ b/Source/AlecrimAsyncKit/Convenience/Availability.swift @@ -10,31 +10,31 @@ import Foundation @available(*, deprecated, renamed: "async(in:execute:)") public func asyncEx(in queue: OperationQueue? = nil, execute closure: @escaping AsyncTaskFullClosure) -> Task { - return async(in: queue, execute: closure) + return async(on: queue, execute: closure) } @available(*, deprecated, renamed: "async(value:)") public func asyncValue(in queue: OperationQueue? = nil, _ value: Value) -> Task { - return async(in: queue, value: value) + return async(on: queue, value: value) } @available(*, deprecated, renamed: "async(error:)") public func asyncError(in queue: OperationQueue? = nil, _ error: Error) -> Task { - return async(in: queue, error: error) + return async(on: queue, error: error) } @available(*, deprecated, renamed: "async(in:delay:)") public func asyncDelay(in queue: OperationQueue? = nil, timeInterval: TimeInterval) -> NonFailableTask { - return async(in: queue, delay: timeInterval) + return async(on: queue, delay: timeInterval) } @available(*, deprecated, renamed: "async(in:sleepForTimeInterval:)") public func asyncSleep(in queue: OperationQueue? = nil, forTimeInterval timeInterval: TimeInterval) -> NonFailableTask { - return async(in: queue, sleepForTimeInterval: timeInterval) + return async(on: queue, sleepForTimeInterval: timeInterval) } @available(*, deprecated, renamed: "async(in:sleepUntil:)") public func asyncSleep(in queue: OperationQueue? = nil, until date: Date) -> NonFailableTask { - return async(in: queue, sleepUntil: date) + return async(on: queue, sleepUntil: date) } diff --git a/Source/AlecrimAsyncKit/Convenience/DispatchQueue+Extensions.swift b/Source/AlecrimAsyncKit/Convenience/DispatchQueue+Extensions.swift index dee0f54..2ee4833 100644 --- a/Source/AlecrimAsyncKit/Convenience/DispatchQueue+Extensions.swift +++ b/Source/AlecrimAsyncKit/Convenience/DispatchQueue+Extensions.swift @@ -11,19 +11,19 @@ import Foundation extension DispatchQueue { public func async(execute closure: @escaping AsyncTaskClosure) -> Task { - return AlecrimAsyncKit.async(in: Queue.operationQueue(for: self), execute: closure) + return AlecrimAsyncKit.async(on: Queue.operationQueue(for: self), execute: closure) } public func async(execute closure: @escaping AsyncNonFailableTaskClosure) -> NonFailableTask { - return AlecrimAsyncKit.async(in: Queue.operationQueue(for: self), execute: closure) + return AlecrimAsyncKit.async(on: Queue.operationQueue(for: self), execute: closure) } public func async(execute taskClosure: @escaping AsyncTaskFullClosure) -> Task { - return AlecrimAsyncKit.async(in: Queue.operationQueue(for: self), execute: taskClosure) + return AlecrimAsyncKit.async(on: Queue.operationQueue(for: self), execute: taskClosure) } public func async(execute taskClosure: @escaping AsyncTaskFullClosure) -> NonFailableTask { - return AlecrimAsyncKit.async(in: Queue.operationQueue(for: self), execute: taskClosure) + return AlecrimAsyncKit.async(on: Queue.operationQueue(for: self), execute: taskClosure) } } diff --git a/Source/AlecrimAsyncKit/Convenience/Mapping.swift b/Source/AlecrimAsyncKit/Convenience/Mapping.swift index 06bc5dd..f9ee588 100644 --- a/Source/AlecrimAsyncKit/Convenience/Mapping.swift +++ b/Source/AlecrimAsyncKit/Convenience/Mapping.swift @@ -12,8 +12,8 @@ import Foundation extension Task { - public func map(in queue: OperationQueue? = nil, closure: @escaping (Value) throws -> U) -> Task { - return async(in: queue) { + public func map(on queue: OperationQueue? = nil, closure: @escaping (Value) throws -> U) -> Task { + return async(on: queue) { let value = try self.await() let mappedValue = try closure(value) @@ -21,8 +21,8 @@ extension Task { } } - public func map(in queue: OperationQueue? = nil, closure: @escaping (Value) -> U) -> Task { - return async(in: queue) { + public func map(on queue: OperationQueue? = nil, closure: @escaping (Value) -> U) -> Task { + return async(on: queue) { let value = try self.await() let mappedValue = closure(value) @@ -34,8 +34,8 @@ extension Task { extension Task { - public func asNonFailable(in queue: OperationQueue? = nil) -> NonFailableTask { - return async(in: queue) { + public func asNonFailable(on queue: OperationQueue? = nil) -> NonFailableTask { + return async(on: queue) { return try! self.await() } } @@ -46,8 +46,8 @@ extension Task { extension NonFailableTask { - public func map(in queue: OperationQueue? = nil, closure: @escaping (Value) -> U) -> NonFailableTask { - return async(in: queue) { + public func map(on queue: OperationQueue? = nil, closure: @escaping (Value) -> U) -> NonFailableTask { + return async(on: queue) { let value = try! self.await() let mappedValue = closure(value) @@ -59,8 +59,8 @@ extension NonFailableTask { extension NonFailableTask { - public func asFailable(in queue: OperationQueue? = nil) -> Task { - return async(in: queue) { + public func asFailable(on queue: OperationQueue? = nil) -> Task { + return async(on: queue) { return try self.await() } } diff --git a/Source/AlecrimAsyncKit/Convenience/OperationQueue+Extensions.swift b/Source/AlecrimAsyncKit/Convenience/OperationQueue+Extensions.swift index 98323c5..36e92ed 100644 --- a/Source/AlecrimAsyncKit/Convenience/OperationQueue+Extensions.swift +++ b/Source/AlecrimAsyncKit/Convenience/OperationQueue+Extensions.swift @@ -11,19 +11,19 @@ import Foundation extension OperationQueue { public func addOperation(_ closure: @escaping AsyncTaskClosure) -> Task { - return AlecrimAsyncKit.async(in: self, execute: closure) + return AlecrimAsyncKit.async(on: self, execute: closure) } public func addOperation(_ closure: @escaping AsyncNonFailableTaskClosure) -> NonFailableTask { - return AlecrimAsyncKit.async(in: self, execute: closure) + return AlecrimAsyncKit.async(on: self, execute: closure) } public func addOperation(_ taskClosure: @escaping AsyncTaskFullClosure) -> Task { - return AlecrimAsyncKit.async(in: self, execute: taskClosure) + return AlecrimAsyncKit.async(on: self, execute: taskClosure) } public func addOperation(_ taskClosure: @escaping AsyncTaskFullClosure) -> NonFailableTask { - return AlecrimAsyncKit.async(in: self, execute: taskClosure) + return AlecrimAsyncKit.async(on: self, execute: taskClosure) } } diff --git a/Source/AlecrimAsyncKit/Convenience/OtherConveniences.swift b/Source/AlecrimAsyncKit/Convenience/OtherConveniences.swift index ef577c1..25cb424 100644 --- a/Source/AlecrimAsyncKit/Convenience/OtherConveniences.swift +++ b/Source/AlecrimAsyncKit/Convenience/OtherConveniences.swift @@ -13,87 +13,87 @@ import Foundation // MARK: - externally controlled tasks /// The task must be retained and the `finish` method shall be called externally when done. -public func manualTask(in queue: OperationQueue? = nil, dependency: TaskDependency? = nil, condition: TaskCondition? = nil) -> Task { - return async(in: queue, dependency: dependency, condition: condition) { _ in } +public func manualTask(on queue: OperationQueue? = nil, dependency: TaskDependency? = nil, condition: TaskCondition? = nil) -> Task { + return async(on: queue, dependency: dependency, condition: condition) { _ in } } /// The task must be retained and the `finish` method shall be called externally when done. -public func manualTask(in queue: OperationQueue? = nil, dependency: TaskDependency? = nil, condition: TaskCondition? = nil) -> NonFailableTask { - return async(in: queue, dependency: dependency, condition: condition) { _ in } +public func manualTask(on queue: OperationQueue? = nil, dependency: TaskDependency? = nil, condition: TaskCondition? = nil) -> NonFailableTask { + return async(on: queue, dependency: dependency, condition: condition) { _ in } } // MARK: - // stubs for Void tasks -public func async(in queue: OperationQueue? = nil, dependency: TaskDependency? = nil, condition: TaskCondition? = nil) -> Task { - return async(in: queue, dependency: dependency, condition: condition) { return () } +public func async(on queue: OperationQueue? = nil, dependency: TaskDependency? = nil, condition: TaskCondition? = nil) -> Task { + return async(on: queue, dependency: dependency, condition: condition) { return () } } -public func async(in queue: OperationQueue? = nil, dependency: TaskDependency? = nil, condition: TaskCondition? = nil) -> NonFailableTask { - return async(in: queue, dependency: dependency, condition: condition) { return () } +public func async(on queue: OperationQueue? = nil, dependency: TaskDependency? = nil, condition: TaskCondition? = nil) -> NonFailableTask { + return async(on: queue, dependency: dependency, condition: condition) { return () } } // shortcuts to simply return a value or throw an error -public func async(in queue: OperationQueue? = nil, dependency: TaskDependency? = nil, condition: TaskCondition? = nil, value: Value) -> Task { - return async(in: queue, dependency: dependency, condition: condition) { return value } +public func async(on queue: OperationQueue? = nil, dependency: TaskDependency? = nil, condition: TaskCondition? = nil, value: Value) -> Task { + return async(on: queue, dependency: dependency, condition: condition) { return value } } -public func async(in queue: OperationQueue? = nil, dependency: TaskDependency? = nil, condition: TaskCondition? = nil, value: Value) -> NonFailableTask { - return async(in: queue, dependency: dependency, condition: condition) { return value } +public func async(on queue: OperationQueue? = nil, dependency: TaskDependency? = nil, condition: TaskCondition? = nil, value: Value) -> NonFailableTask { + return async(on: queue, dependency: dependency, condition: condition) { return value } } -public func async(in queue: OperationQueue? = nil, dependency: TaskDependency? = nil, condition: TaskCondition? = nil, error: Error) -> Task { - return async(in: queue, dependency: dependency, condition: condition) { throw error } +public func async(on queue: OperationQueue? = nil, dependency: TaskDependency? = nil, condition: TaskCondition? = nil, error: Error) -> Task { + return async(on: queue, dependency: dependency, condition: condition) { throw error } } // delay / sleep -public func async(in queue: OperationQueue? = nil, dependency: TaskDependency? = nil, condition: TaskCondition? = nil, delay timeInterval: TimeInterval) -> Task { - return async(in: queue, dependency: dependency, condition: condition, sleepForTimeInterval: timeInterval) +public func async(on queue: OperationQueue? = nil, dependency: TaskDependency? = nil, condition: TaskCondition? = nil, delay timeInterval: TimeInterval) -> Task { + return async(on: queue, dependency: dependency, condition: condition, sleepForTimeInterval: timeInterval) } -public func async(in queue: OperationQueue? = nil, dependency: TaskDependency? = nil, condition: TaskCondition? = nil, delay timeInterval: TimeInterval) -> NonFailableTask { - return async(in: queue, dependency: dependency, condition: condition, sleepForTimeInterval: timeInterval) +public func async(on queue: OperationQueue? = nil, dependency: TaskDependency? = nil, condition: TaskCondition? = nil, delay timeInterval: TimeInterval) -> NonFailableTask { + return async(on: queue, dependency: dependency, condition: condition, sleepForTimeInterval: timeInterval) } -public func async(in queue: OperationQueue? = nil, dependency: TaskDependency? = nil, condition: TaskCondition? = nil, sleepForTimeInterval timeInterval: TimeInterval) -> Task { - return async(in: queue, dependency: dependency, condition: condition) { task in +public func async(on queue: OperationQueue? = nil, dependency: TaskDependency? = nil, condition: TaskCondition? = nil, sleepForTimeInterval timeInterval: TimeInterval) -> Task { + return async(on: queue, dependency: dependency, condition: condition) { task in Queue.delayDispatchQueue.asyncAfter(deadline: .now() + timeInterval) { task.finish() } } } -public func async(in queue: OperationQueue? = nil, dependency: TaskDependency? = nil, condition: TaskCondition? = nil, sleepForTimeInterval timeInterval: TimeInterval) -> NonFailableTask { - return async(in: queue, dependency: dependency, condition: condition) { task in +public func async(on queue: OperationQueue? = nil, dependency: TaskDependency? = nil, condition: TaskCondition? = nil, sleepForTimeInterval timeInterval: TimeInterval) -> NonFailableTask { + return async(on: queue, dependency: dependency, condition: condition) { task in Queue.delayDispatchQueue.asyncAfter(deadline: .now() + timeInterval) { task.finish() } } } -public func async(in queue: OperationQueue? = nil, dependency: TaskDependency? = nil, condition: TaskCondition? = nil, sleepUntil date: Date) -> Task { +public func async(on queue: OperationQueue? = nil, dependency: TaskDependency? = nil, condition: TaskCondition? = nil, sleepUntil date: Date) -> Task { let now = Date() if date > now { let timeInterval = date.timeIntervalSince(now) - return async(in: queue, dependency: dependency, condition: condition, sleepForTimeInterval: timeInterval) + return async(on: queue, dependency: dependency, condition: condition, sleepForTimeInterval: timeInterval) } else { - return async(in: queue, dependency: dependency, condition: condition) {} + return async(on: queue, dependency: dependency, condition: condition) {} } } -public func async(in queue: OperationQueue? = nil, dependency: TaskDependency? = nil, condition: TaskCondition? = nil, sleepUntil date: Date) -> NonFailableTask { +public func async(on queue: OperationQueue? = nil, dependency: TaskDependency? = nil, condition: TaskCondition? = nil, sleepUntil date: Date) -> NonFailableTask { let now = Date() if date > now { let timeInterval = date.timeIntervalSince(now) - return async(in: queue, dependency: dependency, condition: condition, sleepForTimeInterval: timeInterval) + return async(on: queue, dependency: dependency, condition: condition, sleepForTimeInterval: timeInterval) } else { - return async(in: queue, dependency: dependency, condition: condition) {} + return async(on: queue, dependency: dependency, condition: condition) {} } } diff --git a/Source/AlecrimAsyncKit/Core/Async.swift b/Source/AlecrimAsyncKit/Core/Async.swift index 6fe188a..ce4908c 100644 --- a/Source/AlecrimAsyncKit/Core/Async.swift +++ b/Source/AlecrimAsyncKit/Core/Async.swift @@ -17,15 +17,15 @@ public typealias AsyncTaskFullClosure = (BaseTask) -> Void // MARK: - -public func async(in queue: OperationQueue? = nil, dependency: TaskDependency? = nil, condition: TaskCondition? = nil, execute closure: @escaping AsyncTaskClosure) -> Task { - return enqueue(in: queue, dependency: dependency, condition: condition, closure: closure) +public func async(on queue: OperationQueue? = nil, dependency: TaskDependency? = nil, condition: TaskCondition? = nil, execute closure: @escaping AsyncTaskClosure) -> Task { + return enqueue(on: queue, dependency: dependency, condition: condition, closure: closure) } -public func async(in queue: OperationQueue? = nil, dependency: TaskDependency? = nil, condition: TaskCondition? = nil, execute closure: @escaping AsyncNonFailableTaskClosure) -> NonFailableTask { - return enqueue(in: queue, dependency: dependency, condition: condition, closure: closure) +public func async(on queue: OperationQueue? = nil, dependency: TaskDependency? = nil, condition: TaskCondition? = nil, execute closure: @escaping AsyncNonFailableTaskClosure) -> NonFailableTask { + return enqueue(on: queue, dependency: dependency, condition: condition, closure: closure) } -fileprivate func enqueue(in queue: OperationQueue?, dependency: TaskDependency?, condition: TaskCondition?, closure: @escaping AsyncTaskClosure) -> Task { +fileprivate func enqueue(on queue: OperationQueue?, dependency: TaskDependency?, condition: TaskCondition?, closure: @escaping AsyncTaskClosure) -> Task { // let taskClosure: AsyncTaskFullClosure = { do { @@ -38,31 +38,31 @@ fileprivate func enqueue(in queue: OperationQueue?, dependency: TaskDepen } // - return enqueue(in: queue, dependency: dependency, condition: condition, closure: taskClosure) + return enqueue(on: queue, dependency: dependency, condition: condition, closure: taskClosure) } -fileprivate func enqueue(in queue: OperationQueue?, dependency: TaskDependency?, condition: TaskCondition?, closure: @escaping AsyncNonFailableTaskClosure) -> NonFailableTask { +fileprivate func enqueue(on queue: OperationQueue?, dependency: TaskDependency?, condition: TaskCondition?, closure: @escaping AsyncNonFailableTaskClosure) -> NonFailableTask { // let taskClosure: AsyncTaskFullClosure = { $0.finish(with: closure()) } // - return enqueue(in: queue, dependency: dependency, condition: condition, closure: taskClosure) + return enqueue(on: queue, dependency: dependency, condition: condition, closure: taskClosure) } // -public func async(in queue: OperationQueue? = nil, dependency: TaskDependency? = nil, condition: TaskCondition? = nil, execute taskClosure: @escaping AsyncTaskFullClosure) -> Task { - return enqueue(in: queue, dependency: dependency, condition: condition, closure: taskClosure) +public func async(on queue: OperationQueue? = nil, dependency: TaskDependency? = nil, condition: TaskCondition? = nil, execute taskClosure: @escaping AsyncTaskFullClosure) -> Task { + return enqueue(on: queue, dependency: dependency, condition: condition, closure: taskClosure) } -public func async(in queue: OperationQueue? = nil, dependency: TaskDependency? = nil, condition: TaskCondition? = nil, execute taskClosure: @escaping AsyncTaskFullClosure) -> NonFailableTask { - return enqueue(in: queue, dependency: dependency, condition: condition, closure: taskClosure) +public func async(on queue: OperationQueue? = nil, dependency: TaskDependency? = nil, condition: TaskCondition? = nil, execute taskClosure: @escaping AsyncTaskFullClosure) -> NonFailableTask { + return enqueue(on: queue, dependency: dependency, condition: condition, closure: taskClosure) } -fileprivate func enqueue(in queue: OperationQueue?, dependency: TaskDependency?, condition: TaskCondition?, closure taskClosure: @escaping AsyncTaskFullClosure) -> Task { +fileprivate func enqueue(on queue: OperationQueue?, dependency: TaskDependency?, condition: TaskCondition?, closure taskClosure: @escaping AsyncTaskFullClosure) -> Task { // let queue = queue ?? Queue.defaultOperationQueue precondition(queue.maxConcurrentOperationCount > 1 || queue.maxConcurrentOperationCount == OperationQueue.defaultMaxConcurrentOperationCount) @@ -94,7 +94,7 @@ fileprivate func enqueue(in queue: OperationQueue?, dependency: TaskDepen return task } -fileprivate func enqueue(in queue: OperationQueue?, dependency: TaskDependency?, condition: TaskCondition?, closure taskClosure: @escaping AsyncTaskFullClosure) -> NonFailableTask { +fileprivate func enqueue(on queue: OperationQueue?, dependency: TaskDependency?, condition: TaskCondition?, closure taskClosure: @escaping AsyncTaskFullClosure) -> NonFailableTask { // let queue = queue ?? Queue.defaultOperationQueue precondition(queue.maxConcurrentOperationCount > 1 || queue.maxConcurrentOperationCount == OperationQueue.defaultMaxConcurrentOperationCount) diff --git a/Source/AlecrimAsyncKit/Core/TaskAwaiter.swift b/Source/AlecrimAsyncKit/Core/TaskAwaiter.swift index fc35286..43df890 100644 --- a/Source/AlecrimAsyncKit/Core/TaskAwaiter.swift +++ b/Source/AlecrimAsyncKit/Core/TaskAwaiter.swift @@ -95,22 +95,22 @@ public final class TaskAwaiter { extension Task { @discardableResult - public func then(in queue: OperationQueue? = nil, callbackQueue: OperationQueue? = nil, closure: @escaping (Value) -> Void) -> TaskAwaiter { + public func then(on queue: OperationQueue? = nil, callbackQueue: OperationQueue? = nil, closure: @escaping (Value) -> Void) -> TaskAwaiter { return TaskAwaiter(queue: queue ?? Queue.taskAwaiterDefaultOperationQueue, callbackQueue: callbackQueue ?? OperationQueue.main, task: self).then(closure) } @discardableResult - public func `catch`(in queue: OperationQueue? = nil, callbackQueue: OperationQueue? = nil, closure: @escaping (Error) -> Void) -> TaskAwaiter { + public func `catch`(on queue: OperationQueue? = nil, callbackQueue: OperationQueue? = nil, closure: @escaping (Error) -> Void) -> TaskAwaiter { return TaskAwaiter(queue: queue ?? Queue.taskAwaiterDefaultOperationQueue, callbackQueue: callbackQueue ?? OperationQueue.main, task: self).catch(closure) } @discardableResult - public func cancelled(in queue: OperationQueue? = nil, callbackQueue: OperationQueue? = nil, closure: @escaping () -> Void) -> TaskAwaiter { + public func cancelled(on queue: OperationQueue? = nil, callbackQueue: OperationQueue? = nil, closure: @escaping () -> Void) -> TaskAwaiter { return TaskAwaiter(queue: queue ?? Queue.taskAwaiterDefaultOperationQueue, callbackQueue: callbackQueue ?? OperationQueue.main, task: self).cancelled(closure) } @discardableResult - public func finally(in queue: OperationQueue? = nil, callbackQueue: OperationQueue? = nil, closure: @escaping () -> Void) -> TaskAwaiter { + public func finally(on queue: OperationQueue? = nil, callbackQueue: OperationQueue? = nil, closure: @escaping () -> Void) -> TaskAwaiter { return TaskAwaiter(queue: queue ?? Queue.taskAwaiterDefaultOperationQueue, callbackQueue: callbackQueue ?? OperationQueue.main, task: self).finally(closure) } @@ -168,12 +168,12 @@ public final class NonFailableTaskAwaiter { extension NonFailableTask { @discardableResult - public func then(in queue: OperationQueue? = nil, callbackQueue: OperationQueue? = nil, closure: @escaping (Value) -> Void) -> NonFailableTaskAwaiter { + public func then(on queue: OperationQueue? = nil, callbackQueue: OperationQueue? = nil, closure: @escaping (Value) -> Void) -> NonFailableTaskAwaiter { return NonFailableTaskAwaiter(queue: queue ?? Queue.taskAwaiterDefaultOperationQueue, callbackQueue: callbackQueue ?? OperationQueue.main, task: self).then(closure) } @discardableResult - public func finally(in queue: OperationQueue? = nil, callbackQueue: OperationQueue? = nil, closure: @escaping () -> Void) -> NonFailableTaskAwaiter { + public func finally(on queue: OperationQueue? = nil, callbackQueue: OperationQueue? = nil, closure: @escaping () -> Void) -> NonFailableTaskAwaiter { return NonFailableTaskAwaiter(queue: queue ?? Queue.taskAwaiterDefaultOperationQueue, callbackQueue: callbackQueue ?? OperationQueue.main, task: self).finally(closure) } From ac786c00962e50df022b569239509adc481fc6ed Mon Sep 17 00:00:00 2001 From: Vanderlei Martinelli Date: Sun, 20 May 2018 20:47:50 -0300 Subject: [PATCH 10/13] Updated availability hints --- Source/AlecrimAsyncKit/Convenience/Availability.swift | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Source/AlecrimAsyncKit/Convenience/Availability.swift b/Source/AlecrimAsyncKit/Convenience/Availability.swift index e0cced7..4d8510c 100644 --- a/Source/AlecrimAsyncKit/Convenience/Availability.swift +++ b/Source/AlecrimAsyncKit/Convenience/Availability.swift @@ -8,7 +8,7 @@ import Foundation -@available(*, deprecated, renamed: "async(in:execute:)") +@available(*, deprecated, renamed: "async(on:execute:)") public func asyncEx(in queue: OperationQueue? = nil, execute closure: @escaping AsyncTaskFullClosure) -> Task { return async(on: queue, execute: closure) } @@ -23,17 +23,17 @@ public func asyncError(in queue: OperationQueue? = nil, _ error: Error) - return async(on: queue, error: error) } -@available(*, deprecated, renamed: "async(in:delay:)") +@available(*, deprecated, renamed: "async(on:delay:)") public func asyncDelay(in queue: OperationQueue? = nil, timeInterval: TimeInterval) -> NonFailableTask { return async(on: queue, delay: timeInterval) } -@available(*, deprecated, renamed: "async(in:sleepForTimeInterval:)") +@available(*, deprecated, renamed: "async(on:sleepForTimeInterval:)") public func asyncSleep(in queue: OperationQueue? = nil, forTimeInterval timeInterval: TimeInterval) -> NonFailableTask { return async(on: queue, sleepForTimeInterval: timeInterval) } -@available(*, deprecated, renamed: "async(in:sleepUntil:)") +@available(*, deprecated, renamed: "async(on:sleepUntil:)") public func asyncSleep(in queue: OperationQueue? = nil, until date: Date) -> NonFailableTask { return async(on: queue, sleepUntil: date) } From 5486524f4624975a2167e9feedd8c6bf5d350c33 Mon Sep 17 00:00:00 2001 From: Vanderlei Martinelli Date: Sun, 20 May 2018 20:52:20 -0300 Subject: [PATCH 11/13] Added "Package.swift" --- Package.swift | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 Package.swift diff --git a/Package.swift b/Package.swift new file mode 100644 index 0000000..b648f58 --- /dev/null +++ b/Package.swift @@ -0,0 +1,3 @@ +import PackageDescription + +let package = Package(name: "AlecrimAsyncKit") From 5714aa7817bb2289f520ec5ca60ec79d049082f7 Mon Sep 17 00:00:00 2001 From: Vanderlei Martinelli Date: Sun, 20 May 2018 20:52:40 -0300 Subject: [PATCH 12/13] Bumped version and build numbers --- AlecrimAsyncKit.podspec | 2 +- Source/AlecrimAsyncKit.xcodeproj/project.pbxproj | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/AlecrimAsyncKit.podspec b/AlecrimAsyncKit.podspec index 0627958..24d6e93 100644 --- a/AlecrimAsyncKit.podspec +++ b/AlecrimAsyncKit.podspec @@ -1,7 +1,7 @@ Pod::Spec.new do |s| s.name = "AlecrimAsyncKit" - s.version = "4.0-beta.5" + s.version = "4.0" s.summary = "async and await for Swift." s.homepage = "https://www.alecrim.com/AlecrimAsyncKit" diff --git a/Source/AlecrimAsyncKit.xcodeproj/project.pbxproj b/Source/AlecrimAsyncKit.xcodeproj/project.pbxproj index 79f9695..08dd125 100644 --- a/Source/AlecrimAsyncKit.xcodeproj/project.pbxproj +++ b/Source/AlecrimAsyncKit.xcodeproj/project.pbxproj @@ -364,7 +364,7 @@ CODE_SIGN_IDENTITY = ""; CODE_SIGN_STYLE = Manual; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 356; + CURRENT_PROJECT_VERSION = 370; DEFINES_MODULE = YES; DEVELOPMENT_TEAM = ""; DYLIB_COMPATIBILITY_VERSION = 1; @@ -396,7 +396,7 @@ CODE_SIGN_IDENTITY = ""; CODE_SIGN_STYLE = Manual; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 356; + CURRENT_PROJECT_VERSION = 370; DEFINES_MODULE = YES; DEVELOPMENT_TEAM = ""; DYLIB_COMPATIBILITY_VERSION = 1; From 7dcfc0d29ea72bfc65dc40dd448dcfad8fef37cd Mon Sep 17 00:00:00 2001 From: Vanderlei Martinelli Date: Sun, 20 May 2018 21:06:09 -0300 Subject: [PATCH 13/13] Updated README --- README.md | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index acd3dc7..541b16e 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ async and await for Swift. ## Usage ### Awaiting the results -I know I am putting the cart before the horse, but... For the three functions in the next section you can await the returning value in the same way: +Maybe I am putting the cart before the horses, but... For all the functions in the next section you can await the returning value in the same way: ```swift func someFuncRunningInBackground() throws { @@ -161,21 +161,19 @@ func someFuncRunningInTheMainThread() { } ``` -All methods (`then`, `catch`, `cancelled` and `finally`) are optional. If specified, the closure related to the `finally` method will always be called regardless whether the task was cancelled or not, whether there was an error or not. +All methods (`then`, `catch`, `cancelled` and `finally`) are optional. When specified, the closure related to the `finally` method will always be called regardless whether the task was cancelled or not, whether there was an error or not. ## Non failable tasks If you read the framework's code you will find the `NonFailableTask` class. This kind of task cannot fail (sort of). In fact it may fail, but it should not. -The main difference from the failable task class is that you do not have to use the `try` keyword when awaiting for non failable task results. A non failable task cannot be cancelled either. +The main difference from the failable task class is that you do not have to `try` when awaiting for non failable task results. A non failable task cannot be cancelled either. -Please only use this type of task when you are sure that it can not fail. If it do, your program will crash. +Please only use this type of task when you are sure that it cannot fail. If it do and the task fail your program will crash. -## Observers and conditions -The previous version had observers and conditions based on Session 226 of WWDC 2015 (“Advanced NSOperations”). This turned the framework unnecessarily complex. +## Dependencies, conditions and observers +The previous version had observers and conditions based on Session 226 of WWDC 2015 (“Advanced NSOperations”). This turned the framework unnecessarily complex. If you need this functionality right now you can use version 3.x of **AlecrimAsyncKit**. -If you need this functionality right now you can use version 3.x of **AlecrimAsyncKit**. - -Observers and conditions may be reimplemented in a future release or as a separated framework. No guarantees, though. +In version 4.0 the framework has the notion of "dependencies" and a new kind of "conditions" was implemented. Observers may reappear in a future release. No guarantees, though. ## Contribute If you have any problems or need more information, please open an issue using the provided GitHub link.