Skip to content
This repository has been archived by the owner on Feb 28, 2020. It is now read-only.

Commit

Permalink
Merge branch 'release/4.0-beta.5'
Browse files Browse the repository at this point in the history
  • Loading branch information
vmartinelli committed May 6, 2018
2 parents fd0f582 + 3194985 commit 425388a
Show file tree
Hide file tree
Showing 7 changed files with 123 additions and 46 deletions.
2 changes: 1 addition & 1 deletion AlecrimAsyncKit.podspec
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
Pod::Spec.new do |s|

s.name = "AlecrimAsyncKit"
s.version = "4.0-beta.4"
s.version = "4.0-beta.5"
s.summary = "async and await for Swift."
s.homepage = "https://www.alecrim.com/AlecrimAsyncKit"

Expand Down
36 changes: 18 additions & 18 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,12 @@ async and await for Swift.

## Usage
### Awaiting the results
I know I am puttting the cart before the horse, but... For the three functions in the next section you can await the returning value in the same way:
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:

```swift
func someFuncRunningInBackground() throws {
let value = try await { self.someLongRunningAsynchronousFunc() }

// do something with the returned value...
}
```
Expand All @@ -27,12 +27,12 @@ You can also use the result only when needed:
func someFuncRunningInBackground() throws {
// the task starts immediately
let task = self.someLongRunningAsynchronousFunc()

// do other things, the task is running...

// continue doing other things...
// the task can be still running or maybe it is already finished, who knows?

//
let value = try await(task)

Expand All @@ -47,9 +47,9 @@ You can simply return the desired value inside the `async` closure.
func someLongRunningAsynchronousFunc -> Task<SomeValuableValue> {
return async {
let value = self.createSomeValuableValue()

// some long running code here...

return value
}
}
Expand Down Expand Up @@ -86,25 +86,25 @@ func calculate() -> Double {
// using DispatchQueue
let someCalculatedValue = await(DispatchQueue.global(qos: .background).async {
var value: Double = 0

// do some long running calculation here

return value
} as NonFailableTask<Double>)

// using OperationQueue
let operationQueue = OperationQueue()
operationQueue.qualityOfService = .background

let operationTask = operationQueue.addOperation {
var value: Double = 0

// do some long running calculation here

return value
} as NonFailableTask<Double>


// using the results
return someCalculatedValue * await(operationTask)
}
Expand All @@ -113,7 +113,7 @@ func calculate() -> Double {
### Cancellation
You can cancel a task after it was enqueued using its `cancel()` method. When it will be actually cancelled depends on the implementation of its content, however.

Cancelling a task in **AlecrimAsyncKit** is pretty the same as finishig it with an `NSError` with `NSCocoaErrorDomain` and `NSUserCancelledError` as parameters. But if you use `cancel()` cancellation actions can be fired using provided blocks.
Cancelling a task in **AlecrimAsyncKit** is pretty the same as finishing it with an `NSError` with `NSCocoaErrorDomain` and `NSUserCancelledError` as parameters. But if you use `cancel()` cancellation actions can be fired using provided blocks.

You can add cancellation blocks to be executed when a task is cancelled this way:

Expand All @@ -123,7 +123,7 @@ func someLongRunningAsynchronousFunc -> Task<SomeValuableValue> {
let token = self.getSomeValuableValue(completionHandler: { value, error in
task.finish(with: value, or: error)
})

// add a closure to be executed when and if the task is cancelled
task.cancellation += {
token.invalidate()
Expand Down Expand Up @@ -180,7 +180,7 @@ Observers and conditions may be reimplemented in a future release or as a separa
## Contribute
If you have any problems or need more information, please open an issue using the provided GitHub link.

You can also contribute by fixing errors or creating new features. When doing this, please submit your pull requests to this repository as I do not have much time to "hunt" forks for not submited patches.
You can also contribute by fixing errors or creating new features. When doing this, please submit your pull requests to this repository as I do not have much time to "hunt" forks for not submitted patches.

- master - The production branch. Clone or fork this repository for the latest copy.
- develop - The active development branch. [Pull requests](https://help.github.com/articles/creating-a-pull-request) should be directed to this branch.
Expand Down
4 changes: 2 additions & 2 deletions Source/AlecrimAsyncKit.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -360,7 +360,7 @@
CODE_SIGN_IDENTITY = "";
CODE_SIGN_STYLE = Manual;
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 351;
CURRENT_PROJECT_VERSION = 356;
DEFINES_MODULE = YES;
DEVELOPMENT_TEAM = "";
DYLIB_COMPATIBILITY_VERSION = 1;
Expand Down Expand Up @@ -392,7 +392,7 @@
CODE_SIGN_IDENTITY = "";
CODE_SIGN_STYLE = Manual;
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 351;
CURRENT_PROJECT_VERSION = 356;
DEFINES_MODULE = YES;
DEVELOPMENT_TEAM = "";
DYLIB_COMPATIBILITY_VERSION = 1;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,24 @@ import Foundation

// MARK: -

//
// example:
//
// extension Reachability: TaskCondition {
// func evaluate() -> Task<Bool> {
// return conditionAsync { conditionTask in
// self.whenReachable {
// conditionTask.finish(with: true)
// }
// }
// }
// }
//
// ...
//
// async(condition: Reachability()) { ... }
//

public protocol TaskCondition {
func evaluate() -> Task<Bool>
}
Expand All @@ -24,6 +42,35 @@ public func conditionAsync(execute taskClosure: @escaping AsyncTaskFullClosure<B
return async(in: Queue.taskConditionOperationQueue, execute: taskClosure)
}

// MARK: -

// boolean tasks can be used as conditions too

extension BaseTask: TaskCondition where Value == Bool {
public func evaluate() -> Task<Bool> {
return conditionAsync {
return try self.await()
}
}
}

// MARK: -

// ex: let mtc = ManualTaskCondition(); ...; ...; ...; mtc.result = true

public final class ManualTaskCondition: BaseTask<Bool> {
public init() {
super.init(dependency: nil, condition: nil, closure: { _ in })
}

public var result = false {
didSet {
self.finish(with: self.result)
}
}
}


// MARK: -

public final class CompoundTaskCondition: TaskCondition {
Expand Down Expand Up @@ -89,28 +136,18 @@ public final class CompoundTaskCondition: TaskCondition {
}
}


}

// MARK: -

public final class ManualTaskCondition: BaseTask<Bool>, TaskCondition {

public init() {
super.init(dependency: nil, condition: nil, closure: { _ in })
}
// So we can use: async(condition: (condition1 || condition2) && condition3 && !condition4) { ... }

public func evaluate() -> Task<Bool> {
return conditionAsync {
let result = try self.await()
return result
}
}
public func &&(left: TaskCondition, right: TaskCondition) -> TaskCondition {
return CompoundTaskCondition(type: .and, subconditions: [left, right])
}

public var result = false {
didSet {
self.finish(with: self.result)
}
}
public func ||(left: TaskCondition, right: TaskCondition) -> TaskCondition {
return CompoundTaskCondition(type: .or, subconditions: [left, right])
}

prefix public func !(left: TaskCondition) -> TaskCondition {
return CompoundTaskCondition(type: .not, subconditions: [left])
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,47 @@ extension BaseTask: TaskDependency {

// MARK: -

// So we can use: async(dependency: [dependency1, dependency2]) { ... }

extension Array: TaskDependency where Element: TaskDependency {
public func notify(execute work: @escaping @convention(block) () -> Void) {
return self.dependency().notify(execute: work)
}
}

extension Array where Element: TaskDependency {
fileprivate func dependency() -> TaskDependency {
return ArrayTaskDependency(array: self)
}
}

public final class ArrayTaskDependency: TaskDependency {
private let array: [TaskDependency]

fileprivate init(array: [TaskDependency]) {
self.array = array
}

public func notify(execute work: @escaping @convention(block) () -> Void) {
let dispatchGroup = DispatchGroup()

array.forEach {
dispatchGroup.enter()
$0.notify { dispatchGroup.leave() }
}

dispatchGroup.notify(execute: work)
}
}

// So we can use: async(dependency: dependency1 && dependency2) { ... }

public func &&(left: TaskDependency, right: TaskDependency) -> TaskDependency {
return ArrayTaskDependency(array: [left, right])
}

// MARK: -

// `BaseTask` has special knowledge of `TaskSemaphoreDependency`

internal protocol TaskSemaphoreDependency: TaskDependency {
Expand All @@ -51,6 +92,8 @@ extension TaskSemaphoreDependency {
}
}

// limit the number of concurrent tasks running with the same dependency to n

public class ConcurrencyTaskDependency: TaskSemaphoreDependency, TaskDependency {
private let rawValue: DispatchSemaphore

Expand All @@ -59,16 +102,17 @@ public class ConcurrencyTaskDependency: TaskSemaphoreDependency, TaskDependency
self.rawValue = DispatchSemaphore(value: maxConcurrentTaskCount)
}

public func wait() {
internal func wait() {
self.rawValue.wait()
}

@discardableResult
public func signal() -> Int {
internal func signal() -> Int {
return self.rawValue.signal()
}
}

// limit the number of concurrent tasks running with the same dependency to 1

public final class MutuallyExclusiveTaskDependency: ConcurrencyTaskDependency {
public init() {
Expand Down
1 change: 0 additions & 1 deletion Source/AlecrimAsyncKit/Core/Await.swift
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ public func await<Value>(_ task: NonFailableTask<Value>) -> Value {
return try! task.await()
}


@discardableResult
public func await<Value>(_ closure: () -> Task<Value>) throws -> Value {
let task = closure()
Expand Down
3 changes: 0 additions & 3 deletions Source/AlecrimAsyncKit/Core/Errors.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,10 @@ import Foundation
// MARK:

extension NSError {

internal static let userCancelled = NSError(domain: NSCocoaErrorDomain, code: NSUserCancelledError, userInfo: nil)

}

extension Error {

internal var isUserCancelled: Bool {
let error = self as NSError
return error.domain == NSCocoaErrorDomain && error.code == NSUserCancelledError
Expand Down

0 comments on commit 425388a

Please sign in to comment.