Skip to content

Commit

Permalink
- fixed bugs
Browse files Browse the repository at this point in the history
- add tests
  • Loading branch information
Alex Belozierov committed Jan 12, 2020
1 parent 8edf25a commit 03c03da
Show file tree
Hide file tree
Showing 18 changed files with 444 additions and 44 deletions.
4 changes: 2 additions & 2 deletions Sources/SwiftCoroutine/CoFuture/CoFuture+Await.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
// Copyright © 2019 Alex Belozierov. All rights reserved.
//

import Dispatch
import Foundation

extension CoFuture {

Expand All @@ -25,7 +25,7 @@ extension CoFuture {
}

public func await(timeout: DispatchTime) throws -> Output {
let coroutine = try Coroutine.current(), mutex = self.mutex
let coroutine = try Coroutine.current(), mutex = NSLock()
var isTimeOut = false
let timer = DispatchSource.createTimer(timeout: timeout) {
mutex.lock()
Expand Down
6 changes: 0 additions & 6 deletions Sources/SwiftCoroutine/CoFuture/CoFuture+Wait.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,19 +12,13 @@ extension CoFuture {

public func wait(timeout: DispatchTime? = nil) throws -> Output {
assert(!Coroutine.isInsideCoroutine, "Use await inside coroutine")
mutex.lock()
if let result = result {
mutex.unlock()
return try result.get()
}
var result: OutputResult!
let group = DispatchGroup()
group.enter()
addHandler {
result = $0
group.leave()
}
mutex.unlock()
if let timeout = timeout {
if group.wait(timeout: timeout) == .timedOut {
throw CoFutureError.timeout
Expand Down
31 changes: 14 additions & 17 deletions Sources/SwiftCoroutine/CoFuture/CoFuture.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,11 @@ import Foundation

public class CoFuture<Output> {

let mutex: NSRecursiveLock
let mutex: NSLock
@RefBox var resultStorage: OutputResult?
@ArcRefBox var subscriptions: [AnyHashable: OutputHandler]?

init(mutex: NSRecursiveLock = .init(),
resultStorage: RefBox<OutputResult?> = .init(),
init(mutex: NSLock = .init(), resultStorage: RefBox<OutputResult?> = .init(),
subscriptions: ArcRefBox<[AnyHashable: OutputHandler]> = .init(value: [:])) {
self.mutex = mutex
_resultStorage = resultStorage
Expand All @@ -30,21 +29,12 @@ public class CoFuture<Output> {

extension CoFuture {

// MARK: - Result

public var result: OutputResult? {
mutex.lock()
defer { mutex.unlock() }
return resultStorage
}

@inlinable public var isCancelled: Bool {
if case .failure(let error as CoFutureError) = result {
return error == .cancelled
}
return false
}

@usableFromInline func complete(with result: OutputResult) {
mutex.lock()
guard resultStorage == nil
Expand All @@ -56,10 +46,8 @@ extension CoFuture {
handlers?.values.forEach { $0(result) }
}

// MARK: - Identifier

@inlinable public var identifier: Int {
unsafeBitCast(self, to: Int.self)
func newResultStorage(with value: OutputResult?) {
_resultStorage = .init(wrappedValue: value)
}

}
Expand Down Expand Up @@ -87,7 +75,16 @@ extension CoFuture: CoPublisher {

}

extension CoFuture: CoCancellable {}
extension CoFuture: CoCancellable {

@inlinable public var isCancelled: Bool {
if case .failure(let error as CoFutureError) = result {
return error == .cancelled
}
return false
}

}

extension CoFuture: Hashable {

Expand Down
2 changes: 1 addition & 1 deletion Sources/SwiftCoroutine/CoFuture/CoFututre+Operators.swift
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ extension CoFuture {
}

@inlinable @discardableResult
public func onResult(on dispatcher: Dispatcher = .sync, execute completion: @escaping () -> Void) -> CoFuture<Output> {
public func onCompletion(on dispatcher: Dispatcher = .sync, execute completion: @escaping () -> Void) -> CoFuture<Output> {
onResult(on: dispatcher) { _ in completion() }
}

Expand Down
11 changes: 9 additions & 2 deletions Sources/SwiftCoroutine/CoFuture/CoHandleFuture.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,22 @@

final class CoHandleFuture<Output>: CoFuture<Output> {

private let subscribeIdentifier: AnyHashable

@inlinable init(parent: CoFuture<Output>, handler: @escaping OutputHandler) {
subscribeIdentifier = parent.addHandler(handler)
super.init(mutex: parent.mutex,
resultStorage: parent.$resultStorage,
subscriptions: parent.$subscriptions.weak)
subscribe(with: identifier, handler: handler)
}

@inlinable override func cancel() {
unsubscribe(identifier)?(.failure(CoFutureError.cancelled))
mutex.lock()
guard resultStorage == nil else { return mutex.unlock() }
newResultStorage(with: .failure(CoFutureError.cancelled))
let handler = subscriptions?.removeValue(forKey: subscribeIdentifier)
mutex.unlock()
handler?(.failure(CoFutureError.cancelled))
}

}
8 changes: 4 additions & 4 deletions Sources/SwiftCoroutine/CoFuture/CoTransformFuture.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,18 @@
final class CoTransformFuture<Input, Output>: CoFuture<Output> {

typealias Transformer = (Result<Input, Error>) throws -> Output
private let unsubscriber: (AnyHashable) -> Void
private weak var parent: CoFuture<Input>?

@inlinable init(parent: CoFuture<Input>, transformer: @escaping Transformer) {
unsubscriber = { [weak parent] in parent?.unsubscribe($0) }
self.parent = parent
super.init(mutex: parent.mutex)
parent.subscribe(with: identifier) { result in
parent.subscribe(with: self) { [unowned self] result in
self.complete(with: Result { try transformer(result) })
}
}

override func cancel() {
unsubscriber(identifier)
parent?.unsubscribe(self)
super.cancel()
}

Expand Down
4 changes: 2 additions & 2 deletions Sources/SwiftCoroutine/Coroutine/Coroutine.swift
Original file line number Diff line number Diff line change
Expand Up @@ -100,11 +100,11 @@ public class Coroutine {

extension Coroutine: Hashable {

public static func == (lhs: Coroutine, rhs: Coroutine) -> Bool {
@inlinable public static func == (lhs: Coroutine, rhs: Coroutine) -> Bool {
lhs === rhs
}

public func hash(into hasher: inout Hasher) {
@inlinable public func hash(into hasher: inout Hasher) {
ObjectIdentifier(self).hash(into: &hasher)
}

Expand Down
2 changes: 1 addition & 1 deletion Sources/SwiftCoroutine/Helpers/AtomicInt.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ struct AtomicInt {

private var _value: Int

init(value: Int) {
@inlinable init(value: Int) {
_value = value
}

Expand Down
56 changes: 50 additions & 6 deletions SwiftCoroutine.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@
1A6E1ACD23B8EC1300236A47 /* CoroutineContext+Pool.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1A6E1ACB23B8EC1300236A47 /* CoroutineContext+Pool.swift */; };
1A739A6B23AC141500165280 /* Coroutine+Debug.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1A739A6A23AC141500165280 /* Coroutine+Debug.swift */; };
1A739A6C23AC141500165280 /* Coroutine+Debug.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1A739A6A23AC141500165280 /* Coroutine+Debug.swift */; };
1A739A7623ACE66B00165280 /* CoFutureTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1A739A7323ACE63E00165280 /* CoFutureTests.swift */; };
1A739A7723ACE66C00165280 /* CoFutureTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1A739A7323ACE63E00165280 /* CoFutureTests.swift */; };
1A739A7623ACE66B00165280 /* CoFutureTests2.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1A739A7323ACE63E00165280 /* CoFutureTests2.swift */; };
1A739A7723ACE66C00165280 /* CoFutureTests2.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1A739A7323ACE63E00165280 /* CoFutureTests2.swift */; };
1A739A7923ACFAF100165280 /* CoFututre+Operators.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1A739A7823ACFAF100165280 /* CoFututre+Operators.swift */; };
1A739A7A23ACFAF100165280 /* CoFututre+Operators.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1A739A7823ACFAF100165280 /* CoFututre+Operators.swift */; };
1A739ABA23B0B89600165280 /* CoFututeComposite.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1A739AB923B0B89600165280 /* CoFututeComposite.swift */; };
Expand Down Expand Up @@ -84,10 +84,22 @@
1AB8B30E23BA31510052E72F /* CoGenerator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1AB8B30C23BA31510052E72F /* CoGenerator.swift */; };
1AB8B31123BA3A7F0052E72F /* CoPublisher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1AB8B31023BA3A7F0052E72F /* CoPublisher.swift */; };
1AB8B31223BA3A7F0052E72F /* CoPublisher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1AB8B31023BA3A7F0052E72F /* CoPublisher.swift */; };
1AEC382023CA01320000101A /* CoFutureOperatorsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1AEC381F23CA01320000101A /* CoFutureOperatorsTests.swift */; };
1AEC382123CA01320000101A /* CoFutureOperatorsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1AEC381F23CA01320000101A /* CoFutureOperatorsTests.swift */; };
1AEC382323CA02C90000101A /* XCTOrderedExpectation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1AEC382223CA02C90000101A /* XCTOrderedExpectation.swift */; };
1AEC382423CA02C90000101A /* XCTOrderedExpectation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1AEC382223CA02C90000101A /* XCTOrderedExpectation.swift */; };
1AECF5A923BA0E1D002A0493 /* CoFuture+Wait.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1AECF5A823BA0E1D002A0493 /* CoFuture+Wait.swift */; };
1AECF5AA23BA0E1D002A0493 /* CoFuture+Wait.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1AECF5A823BA0E1D002A0493 /* CoFuture+Wait.swift */; };
1AFFF6ED23C8BDEA0079FF73 /* CoFutureError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1AFFF6EC23C8BDEA0079FF73 /* CoFutureError.swift */; };
1AFFF6EE23C8BDEA0079FF73 /* CoFutureError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1AFFF6EC23C8BDEA0079FF73 /* CoFutureError.swift */; };
1AFFF6F123C9002C0079FF73 /* CoFutureTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1AFFF6F023C9002C0079FF73 /* CoFutureTests.swift */; };
1AFFF6F223C9002C0079FF73 /* CoFutureTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1AFFF6F023C9002C0079FF73 /* CoFutureTests.swift */; };
1AFFF6F423C907280079FF73 /* CoPromiseTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1AFFF6F323C907280079FF73 /* CoPromiseTests.swift */; };
1AFFF6F523C907280079FF73 /* CoPromiseTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1AFFF6F323C907280079FF73 /* CoPromiseTests.swift */; };
1AFFF6F723C909C40079FF73 /* CoTransformFutureTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1AFFF6F623C909C40079FF73 /* CoTransformFutureTests.swift */; };
1AFFF6F823C909C40079FF73 /* CoTransformFutureTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1AFFF6F623C909C40079FF73 /* CoTransformFutureTests.swift */; };
1AFFF6FA23C9E74D0079FF73 /* CoHandleFutureTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1AFFF6F923C9E74C0079FF73 /* CoHandleFutureTests.swift */; };
1AFFF6FB23C9E74D0079FF73 /* CoHandleFutureTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1AFFF6F923C9E74C0079FF73 /* CoHandleFutureTests.swift */; };
F8CD258F20199CF700952299 /* SwiftCoroutine.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F8CD258620199CF700952299 /* SwiftCoroutine.framework */; };
F8CD25AB20199D1000952299 /* SwiftCoroutine.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F8CD25A220199D1000952299 /* SwiftCoroutine.framework */; };
F8CD25E92019A01600952299 /* CCoroutine.c in Sources */ = {isa = PBXBuildFile; fileRef = F810EEFF1F8F2E1C00025AD1 /* CCoroutine.c */; };
Expand Down Expand Up @@ -129,7 +141,7 @@
1A65BACD239D9D79004C1716 /* Coroutine.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Coroutine.swift; sourceTree = "<group>"; };
1A6E1ACB23B8EC1300236A47 /* CoroutineContext+Pool.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "CoroutineContext+Pool.swift"; sourceTree = "<group>"; };
1A739A6A23AC141500165280 /* Coroutine+Debug.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Coroutine+Debug.swift"; sourceTree = "<group>"; };
1A739A7323ACE63E00165280 /* CoFutureTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CoFutureTests.swift; sourceTree = "<group>"; };
1A739A7323ACE63E00165280 /* CoFutureTests2.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CoFutureTests2.swift; sourceTree = "<group>"; };
1A739A7823ACFAF100165280 /* CoFututre+Operators.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "CoFututre+Operators.swift"; sourceTree = "<group>"; };
1A739AB923B0B89600165280 /* CoFututeComposite.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CoFututeComposite.swift; sourceTree = "<group>"; };
1A739ABC23B0FF6100165280 /* Dispatcher.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Dispatcher.swift; sourceTree = "<group>"; };
Expand All @@ -155,8 +167,14 @@
1AB2F6932395531400B7B1FD /* Generator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Generator.swift; sourceTree = "<group>"; };
1AB8B30C23BA31510052E72F /* CoGenerator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CoGenerator.swift; sourceTree = "<group>"; };
1AB8B31023BA3A7F0052E72F /* CoPublisher.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CoPublisher.swift; sourceTree = "<group>"; };
1AEC381F23CA01320000101A /* CoFutureOperatorsTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CoFutureOperatorsTests.swift; sourceTree = "<group>"; };
1AEC382223CA02C90000101A /* XCTOrderedExpectation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = XCTOrderedExpectation.swift; sourceTree = "<group>"; };
1AECF5A823BA0E1D002A0493 /* CoFuture+Wait.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "CoFuture+Wait.swift"; sourceTree = "<group>"; };
1AFFF6EC23C8BDEA0079FF73 /* CoFutureError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CoFutureError.swift; sourceTree = "<group>"; };
1AFFF6F023C9002C0079FF73 /* CoFutureTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CoFutureTests.swift; sourceTree = "<group>"; };
1AFFF6F323C907280079FF73 /* CoPromiseTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CoPromiseTests.swift; sourceTree = "<group>"; };
1AFFF6F623C909C40079FF73 /* CoTransformFutureTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CoTransformFutureTests.swift; sourceTree = "<group>"; };
1AFFF6F923C9E74C0079FF73 /* CoHandleFutureTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CoHandleFutureTests.swift; sourceTree = "<group>"; };
F810EEFA1F8F2B3E00025AD1 /* LICENCE */ = {isa = PBXFileReference; lastKnownFileType = text; path = LICENCE; sourceTree = "<group>"; };
F810EEFB1F8F2B4D00025AD1 /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = "<group>"; };
F810EEFF1F8F2E1C00025AD1 /* CCoroutine.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = CCoroutine.c; sourceTree = "<group>"; };
Expand Down Expand Up @@ -256,6 +274,7 @@
1A934FB7239029B700155B71 /* URLSession+Extensions.swift */,
1A934FBA23902A5300155B71 /* URL+Extensions.swift */,
1A934FC3239031C000155B71 /* XCTAssertContains.swift */,
1AEC382223CA02C90000101A /* XCTOrderedExpectation.swift */,
);
path = Extensions;
sourceTree = "<group>";
Expand Down Expand Up @@ -309,6 +328,18 @@
path = Pool;
sourceTree = "<group>";
};
1AFFF6EF23C900120079FF73 /* CoFutureTests */ = {
isa = PBXGroup;
children = (
1AFFF6F023C9002C0079FF73 /* CoFutureTests.swift */,
1AFFF6F323C907280079FF73 /* CoPromiseTests.swift */,
1AFFF6F623C909C40079FF73 /* CoTransformFutureTests.swift */,
1AFFF6F923C9E74C0079FF73 /* CoHandleFutureTests.swift */,
1AEC381F23CA01320000101A /* CoFutureOperatorsTests.swift */,
);
path = CoFutureTests;
sourceTree = "<group>";
};
F810EEFD1F8F2D9000025AD1 /* CCoroutine */ = {
isa = PBXGroup;
children = (
Expand Down Expand Up @@ -336,11 +367,12 @@
F810EF0B1F8F302700025AD1 /* SwiftCoroutineTests */ = {
isa = PBXGroup;
children = (
1AFFF6EF23C900120079FF73 /* CoFutureTests */,
1A934FB6239029A300155B71 /* Extensions */,
F810EF0E1F8F302700025AD1 /* Info.plist */,
F810EF0C1F8F302700025AD1 /* SwiftCoroutineTests.swift */,
1A934FB1239028CA00155B71 /* CombineTests.swift */,
1A739A7323ACE63E00165280 /* CoFutureTests.swift */,
1A739A7323ACE63E00165280 /* CoFutureTests2.swift */,
);
path = SwiftCoroutineTests;
sourceTree = "<group>";
Expand Down Expand Up @@ -623,8 +655,14 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
1AFFF6FA23C9E74D0079FF73 /* CoHandleFutureTests.swift in Sources */,
1A934FC4239031C000155B71 /* XCTAssertContains.swift in Sources */,
1A739A7623ACE66B00165280 /* CoFutureTests.swift in Sources */,
1AFFF6F123C9002C0079FF73 /* CoFutureTests.swift in Sources */,
1A739A7623ACE66B00165280 /* CoFutureTests2.swift in Sources */,
1AFFF6F723C909C40079FF73 /* CoTransformFutureTests.swift in Sources */,
1AEC382023CA01320000101A /* CoFutureOperatorsTests.swift in Sources */,
1AEC382323CA02C90000101A /* XCTOrderedExpectation.swift in Sources */,
1AFFF6F423C907280079FF73 /* CoPromiseTests.swift in Sources */,
F8CD25F92019A19A00952299 /* SwiftCoroutineTests.swift in Sources */,
1A934FBB23902A5300155B71 /* URL+Extensions.swift in Sources */,
1A934FB4239028E900155B71 /* CombineTests.swift in Sources */,
Expand Down Expand Up @@ -679,8 +717,14 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
1AFFF6FB23C9E74D0079FF73 /* CoHandleFutureTests.swift in Sources */,
1A934FC5239031C000155B71 /* XCTAssertContains.swift in Sources */,
1A739A7723ACE66C00165280 /* CoFutureTests.swift in Sources */,
1AFFF6F223C9002C0079FF73 /* CoFutureTests.swift in Sources */,
1A739A7723ACE66C00165280 /* CoFutureTests2.swift in Sources */,
1AFFF6F823C909C40079FF73 /* CoTransformFutureTests.swift in Sources */,
1AEC382123CA01320000101A /* CoFutureOperatorsTests.swift in Sources */,
1AEC382423CA02C90000101A /* XCTOrderedExpectation.swift in Sources */,
1AFFF6F523C907280079FF73 /* CoPromiseTests.swift in Sources */,
1A934FBC23902A5300155B71 /* URL+Extensions.swift in Sources */,
1A94E5C223A3E6A300812AFD /* SwiftCoroutineTests.swift in Sources */,
1A94E5C323A3E6A600812AFD /* CombineTests.swift in Sources */,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Release"
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES"
Expand Down
Loading

0 comments on commit 03c03da

Please sign in to comment.