Skip to content

Commit

Permalink
- remove CoFutre map() and flatMap()
Browse files Browse the repository at this point in the history
  • Loading branch information
Alex Belozierov committed Mar 31, 2020
1 parent 0697fb2 commit 2bc9a0f
Show file tree
Hide file tree
Showing 54 changed files with 157 additions and 1,686 deletions.
1 change: 0 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,6 @@ Futures and promises are represented by the corresponding `CoFuture` class and i

#### Main features
- **Best performance**. It is much faster than most of other futures and promises implementations.
- **Build chains**. With `flatMap()` and `map()`, you can create data dependencies via `CoFuture` chains.
- **Cancellable**. You can cancel the whole chain as well as handle it and complete the related actions.
- **Awaitable**. You can await the result inside the coroutine.
- **Combine-ready**. You can create `Publisher` from `CoFuture`, and vice versa make `CoFuture` a subscriber.
Expand Down
115 changes: 19 additions & 96 deletions Sources/SwiftCoroutine/CoFuture/Core/CoFuture.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,6 @@
// Copyright © 2020 Alex Belozierov. All rights reserved.
//

protocol _CoFutureCancellable: class {

func cancel()

}

///
///Holder for a result that will be provided later.
///
Expand Down Expand Up @@ -61,28 +55,6 @@ protocol _CoFutureCancellable: class {
///Тести для `CoFuture` та Combine `Future` ви можете знайти в файлі `CoFuturePerformanceTests`.
///Тест проводився на MacBook Pro (13-inch, 2017, Two Thunderbolt 3 ports) у release mode.
///
///### **Build chains**
///За допомогою `flatMap()` ви можете створювати chain of `CoFuture`, that allows you to do
///more asynchronous processing. Або ви можете використати `map()` для синхронного трансформування.
///В кінці ви можете використати `whenSuccess()` or `whenFailure()` для observing callback with the result or error.
///
///```
/////some future that will return URLRequest
///let requestFuture: CoFuture<URLRequest>
///
///requestFuture.flatMap { request in
/// URLSession.shared.dataTaskFuture(for: request)
///}.flatMap { data, response in
/// CoFuture(on: .global) {
/// //do some work on global queue that return some result
/// }
///}.map {
/// transformData($0)
///}.whenComplete { result in
/// //result handler
///}
///```
///
///### **Cancellable**
///За допомогою `cancel()` ви можете завершити весь upstream chain of CoFutures.
///Також ви можете handle cancelling і завершити пов’язані таски.
Expand Down Expand Up @@ -135,8 +107,7 @@ protocol _CoFutureCancellable: class {
///
public class CoFuture<Value> {

private let mutex: PsxLock?
private var parent: UnownedCancellable?
internal let mutex: PsxLock?
private var callbacks: ContiguousArray<Child>?
final private(set) var _result: Optional<Result<Value, Error>>

Expand Down Expand Up @@ -172,37 +143,25 @@ extension CoFuture {
self.init(result: .failure(error))
}

// MARK: - Mutex

internal func lock() {
mutex?.lock()
}

internal func unlock() {
mutex?.unlock()
}

// MARK: - result

/// Returns completed result or nil if this future has not completed yet.
public var result: Result<Value, Error>? {
lock()
defer { unlock() }
mutex?.lock()
defer { mutex?.unlock() }
return _result
}

@usableFromInline internal func setResult(_ result: Result<Value, Error>) {
lock()
if _result != nil { return unlock() }
lockedComplete(with: result)
}

private func lockedComplete(with result: Result<Value, Error>) {
_result = result
unlock()
callbacks?.forEach { $0.callback(result) }
callbacks = nil
parent = nil
mutex?.lock()
if _result != nil {
mutex?.unlock()
} else {
_result = result
mutex?.unlock()
callbacks?.forEach { $0.callback(result) }
callbacks = nil
}
}

// MARK: - Callback
Expand All @@ -211,20 +170,11 @@ extension CoFuture {
private struct Child { let callback: Callback }

internal func append(callback: @escaping Callback) {
callbacks.append(.init(callback: callback))
}

internal func addChild<T>(future: CoFuture<T>, callback: @escaping Callback) {
future.parent = .init(cancellable: self)
append(callback: callback)
}

}

extension CoFuture: _CoFutureCancellable {

private struct UnownedCancellable {
unowned(unsafe) let cancellable: _CoFutureCancellable
if callbacks == nil {
callbacks = [.init(callback: callback)]
} else {
callbacks?.append(.init(callback: callback))
}
}

// MARK: - cancel
Expand All @@ -238,35 +188,8 @@ extension CoFuture: _CoFutureCancellable {
}

/// Cancel цей та всі пов'язані future, засетавши всім результат з CoFutureError.canceled.
public func cancel() {
lock()
if _result != nil { return unlock() }
if let parent = parent {
unlock()
parent.cancellable.cancel()
} else {
lockedComplete(with: .failure(CoFutureError.canceled))
}
}

}

extension CoPromise {

@inlinable public convenience init() {
self.init(mutex: .init(), result: nil)
}

}

extension Optional {

fileprivate mutating func append<T>(_ element: T) where Wrapped == ContiguousArray<T> {
if self == nil {
self = [element]
} else {
self!.append(element)
}
@inlinable public func cancel() {
setResult(.failure(CoFutureError.canceled))
}

}
12 changes: 4 additions & 8 deletions Sources/SwiftCoroutine/CoFuture/Core/CoPromise.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ public final class CoPromise<Value>: CoFuture<Value> {}

extension CoPromise {

@inlinable public convenience init() {
self.init(mutex: .init(), result: nil)
}

@inlinable public func complete(with result: Result<Value, Error>) {
setResult(result)
}
Expand All @@ -31,11 +35,3 @@ extension CoPromise {
}

}

extension CoPromise where Value == Void {

@inlinable public func success() {
setResult(.success(()))
}

}
63 changes: 0 additions & 63 deletions Sources/SwiftCoroutine/CoFuture/Operators/CoFuture1+flatMap.swift

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -8,28 +8,18 @@

extension CoFuture {

// MARK: - always

/// Adds an observer callback that is called when the `CoFuture` has any result.
/// - Parameter callback: The callback that is called when the `CoFuture` is fulfilled.
/// - returns: The current `CoFuture`.
@inlinable public func always(_ callback: @escaping (Result<Value, Error>) -> Void) -> CoFuture {
whenComplete(callback)
return self
}

// MARK: - whenComplete

/// Adds an observer callback that is called when the `CoFuture` has any result.
/// - Parameter callback: The callback that is called when the `CoFuture` is fulfilled.
public func whenComplete(_ callback: @escaping (Result<Value, Error>) -> Void) {
lock()
mutex?.lock()
if let result = _result {
unlock()
mutex?.unlock()
callback(result)
} else {
append(callback: callback)
unlock()
mutex?.unlock()
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,15 @@ extension CoFuture {
// MARK: - await

public func await() throws -> Value {
lock()
mutex?.lock()
if let result = _result {
unlock()
mutex?.unlock()
return try result.get()
}
return try Coroutine.current()
.await { (callback: @escaping (Result<Value, Error>) -> Void) in
self.append(callback: callback)
self.unlock()
self.mutex?.unlock()
}.get()
}

Expand Down
50 changes: 0 additions & 50 deletions Sources/SwiftCoroutine/CoFuture/Operators/CoFuture2+map.swift

This file was deleted.

33 changes: 0 additions & 33 deletions Sources/SwiftCoroutine/CoFuture/Operators/CoFuture5+wait.swift

This file was deleted.

Loading

0 comments on commit 2bc9a0f

Please sign in to comment.