FutureProtocol

public protocol FutureProtocol : FutureConvertible where Self == Self.FutureType

A protocol that defines a container for the result of an asynchronous operation, such as an HTTP request, a timeout, a disk I/O operation, etc.

Futures can be pending, meaning that the result of the operation is not available yet, or completed, meaning that the result is ready. Futures can be combined into larger operations with combinators, such as map(_:), flatMap(_:), etc.

Futures communicate a single value of type Output. Semantically, futures capture only the notion of completion; that is, there is no explicit distinction between a successful or a failed operation. Operations that must communicate success or failure, must do so by encoding that information in the output type, typically using Swift.Result. Futures comes with a number of convenience types and combinators for working with Swift.Result (see ResultFuture).

You typically create futures using the static convenience methods on the Future namespace. You can also create custom futures by adopting this protocol in your types.

Creating futures is always an asynchronous operation. The builtin types guarantee that the operation the future wraps will only be started after the future is submitted to an executor (see ExecutorProtocol). Custom future implementations must also provide the same guarantee.

Memory and Concurrency Management

When a future is submitted to an executor, ownership of the future and its resources is transferred into the executor. You can only affect its fate indirectly from that point on (see Task).

When a future completes, it is effectively dropped and its resources are released on the same execution context (eg. a thread or a Dispatch queue) the future was started and polled in.

This makes both memory and concurrency management predictable and extremely easy to reason about; a future’s lifetime is wholly contained within the executor it was submitted on.

Cancellation

Futures support cancellation implicitly. As discussed above, for a future to make progress, it must be polled by an executor. By simply not polling the future and instead dropping it effectively cancels the underlying operation. To explicitly cancel a submitted future, use Task.

If the operation is allocating resources that must be released manually, you can provide a cancellation token at creation which will automatically invoke a given closure upon deallocation, be it due to completion or cancellation (see Deferred).

  • makeFuture() Extension method

    .

    let f = Future.ready(42).makeFuture()
    assert(f.wait() == 42)
    

    Declaration

    Swift

    public func makeFuture() -> Self

    Return Value

    some FutureProtocol<Output == Self.Output>

  • makeStream() Extension method

    .

    var s = Future.ready(42).makeStream()
    assert(s.next() == 42)
    assert(s.next() == nil)
    

    Declaration

    Swift

    @inlinable
    public func makeStream() -> Future._Private.Stream<Self>

    Return Value

    some StreamProtocol<Output == Self.Output>

  • makeReference() Extension method

    .

    let f1 = Future.ready(4).makeReference()
    let f2 = Future.ready(2).makeReference()
    let f = Future.join(f1, f2)
    assert(f.wait() == (4, 2))
    // assert(f1.wait() == 4) // traps
    // assert(f2.wait() == 2) // traps
    

    Declaration

    Swift

    @inlinable
    public func makeReference() -> Future._Private.Reference<Self>

    Return Value

    some FutureProtocol<Output == Self.Output>

  • wait() Extension method

    Synchronously polls this future on the current thread’s executor until it completes.

    let f = Future.ready(42)
    assert(f.wait() == 42)
    

    Declaration

    Swift

    @inlinable
    public func wait() -> Output

    Return Value

    Self.Output

  • wait(on:) Extension method

    Synchronously polls this future using the provided blocking executor until it completes.

    let executor = ThreadExecutor.current
    let f = Future.ready(42)
    assert(f.wait(on: executor) == 42)
    

    Declaration

    Swift

    @inlinable
    public func wait<E>(on executor: E) -> Output where E : BlockingExecutor

    Return Value

    Self.Output

  • abort(when:) Extension method

    Declaration

    Swift

    @inlinable
    public func abort<U>(when f: U) -> Future._Private.Abort<U, Self> where U : FutureConvertible, U.FutureType.Output == Void

    Return Value

    some FutureProtocol<Output == Self.Output?>

  • abort(when:) Extension method

    Declaration

    Swift

    @inlinable
    public func abort<U>(when f: @escaping () -> U) -> Future._Private.Abort<U, Self>

    Return Value

    some FutureProtocol<Output == Self.Output?>

  • poll(on:) Extension method

    Ensures this future is polled on the given executor.

    The returned future retains the executor for its whole lifetime.

    let f = Future.ready(42)
        .poll(on: QueueExecutor.global)
        .assertNoError()
    assert(f.wait() == 42)
    

    Declaration

    Swift

    @inlinable
    public func poll<E>(on executor: E) -> Future._Private.PollOn<E, Self> where E : ExecutorProtocol

    Return Value

    some FutureProtocol<Output == Result<Self.Output, E.Failure>>

  • eraseToAnyFuture() Extension method

    .

    let f = Future.ready(42).eraseToAnyFuture()
    assert(f.wait() == 42)
    

    Declaration

    Swift

    @inlinable
    public func eraseToAnyFuture() -> AnyFuture<Output>

    Return Value

    AnyFuture<Self.Output>

  • map(_:) Extension method

    Transforms the output from this future with a provided closure.

    let f = Future.ready(4).map {
        String($0) + "2"
    }
    assert(f.wait() == "42")
    

    For a variation of this combinator that accepts an error-throwing closure see tryMap(_:).

    Declaration

    Swift

    @inlinable
    public func map<T>(_ transform: @escaping (Output) -> T) -> Future._Private.Map<T, Self>

    Return Value

    some FutureProtocol<Output == T>

  • map(_:) Extension method

    .

    struct Data {
        let a: Int
    }
    let data = Data(a: 42)
    let f = Future.ready(data).map(\.a)
    assert(f.wait() == 42)
    

    Declaration

    Swift

    @inlinable
    public func map<T>(_ keyPath: KeyPath<Output, T>) -> Future._Private.MapKeyPath<T, Self>

    Return Value

    some FutureProtocol<Output == T>

  • map(_:_:) Extension method

    .

    struct Data {
        let a, b: Int
    }
    let data = Data(a: 4, b: 2)
    let f = Future.ready(data).map(\.a, \.b)
    assert(f.wait() == (4, 2))
    

    Declaration

    Swift

    @inlinable
    public func map<T0, T1>(_ keyPath0: KeyPath<Output, T0>, _ keyPath1: KeyPath<Output, T1>) -> Future._Private.MapKeyPath2<T0, T1, Self>

    Return Value

    some FutureProtocol<Output == (T0, T1)>

  • map(_:_:_:) Extension method

    .

    struct Data {
        let a, b, c: Int
    }
    let data = Data(a: 4, b: 2, c: 5)
    let f = Future.ready(data).map(\.a, \.b, \.c)
    assert(f.wait() == (4, 2, 5))
    

    Declaration

    Swift

    @inlinable
    public func map<T0, T1, T2>(_ keyPath0: KeyPath<Output, T0>, _ keyPath1: KeyPath<Output, T1>, _ keyPath2: KeyPath<Output, T2>) -> Future._Private.MapKeyPath3<T0, T1, T2, Self>

    Return Value

    some FutureProtocol<Output == (T0, T1, T2)>

  • flatMap(_:) Extension method

    .

    let f = Future.ready(4).flatMap {
        Future.ready(String($0) + "2")
    }
    assert(f.wait() == "42")
    

    Declaration

    Swift

    @inlinable
    public func flatMap<U>(_ transform: @escaping (Output) -> U) -> Future._Private.FlatMap<U, Self>

    Return Value

    some FutureProtocol<Output == U.FutureType.Output>

  • then(on:_:) Extension method

    .

    let f = Future.ready(14).then(on: QueueExecutor.global) {
        Future.ready($0 * 3)
    }
    assert(f.wait() == Result.success(42))
    

    Declaration

    Swift

    @inlinable
    public func then<E, U>(on executor: E, _ execute: @escaping (Output) -> U) -> Future._Private.Then<E, U, Self>

    Return Value

    some FutureProtocol<Output == Result<U.FutureType.Output, E.Failure>>

  • peek(_:) Extension method

    Calls the given closure on the output of this future.

    let f = Future.ready(42).peek {
        print($0)
    }
    assert(f.wait() == 42)
    

    Declaration

    Swift

    @inlinable
    public func peek(_ body: @escaping (Output) -> Void) -> Future._Private.Peek<Self>

    Return Value

    some FutureProtocol<Output == Self.Output>

  • replaceNil(with:) Extension method

    Replaces the output from this future with a provided value, if it is nil.

    let f1 = Future.ready(Int?.some(5)).replaceNil(with: 42)
    assert(f1.wait() == 5)
    
    let f2 = Future.ready(Int?.none).replaceNil(with: 42)
    assert(f2.wait() == 42)
    

    Declaration

    Swift

    @inlinable
    public func replaceNil<T>(with output: T) -> Future._Private.Map<T, Self> where Self.Output == T?

    Return Value

    some FutureProtocol<Output == T>

  • replaceOutput(with:) Extension method

    Replaces the output from this future with a provided value.

    let f = Future.ready(5).replaceOutput(with: 42)
    assert(f.wait() == 42)
    

    Declaration

    Swift

    @inlinable
    public func replaceOutput<T>(with output: T) -> Future._Private.ReplaceOutput<T, Self>

    Return Value

    some FutureProtocol<Output == T>

  • ignoreOutput() Extension method

    Ignores the output from this future.

    let f = Future.ready(42).ignoreOutput()
    assert(f.wait() == ())
    

    Declaration

    Swift

    @inlinable
    public func ignoreOutput() -> Future._Private.IgnoreOutput<Self>

    Return Value

    some FutureProtocol<Output == Void>

  • match(some:none:) Extension method

    .

    let f1 = Future.ready(Int?.some(42)).match(
        some: String.init,
        none: { "NaN" }
    )
    assert(f1.wait() == "42")
    
    let f2 = Future.ready(Int?.none).match(
        some: String.init,
        none: { "NaN" }
    )
    assert(f2.wait() == "NaN")
    

    Declaration

    Swift

    @inlinable
    public func match<T>(
        some: @escaping (Output.WrappedType) -> T,
        none: @escaping () -> T
    ) -> Future._Private.MatchOptional<T, Self>

    Return Value

    some FutureProtocol<Output == T>

  • match(left:right:) Extension method

    .

    func transform(_ value: Int) -> Either<Int, Float> {
        if value == 42 {
            return .left(value)
        } else {
            return .right(.init(value))
        }
    }
    
    let f1 = Future.ready(42).map(transform).match(
        left: String.init,
        right: String.init(describing:)
    )
    assert(f1.wait() == "42")
    
    let f2 = Future.ready(5).map(transform).match(
        left: String.init,
        right: String.init(describing:)
    )
    assert(f2.wait() == "5.0")
    

    Declaration

    Swift

    @inlinable
    public func match<T>(
        left: @escaping (Output.Left) -> T,
        right: @escaping (Output.Right) -> T
    ) -> Future._Private.MatchEither<T, Self>

    Return Value

    some FutureProtocol<Output == T>

  • join(_:) Extension method

    Combines the output from this future with that from another future by waiting until both futures complete and then completing with the output from each future together as a tuple.

    let a = Future.ready(1)
    let b = Future.ready("A")
    let f = a.join(b)
    assert(f.wait() == (1, "A"))
    

    Declaration

    Swift

    @inlinable
    public func join<F>(_ other: F) -> Future._Private.Join<Self, F> where F : FutureProtocol

    Return Value

    some FutureProtocol<Output == (Self.Output, S.Output)>

  • join(_:_:) Extension method

    Combines the output from this future with that from two other futures by waiting until all futures complete and then completing with the output from each future together as a tuple.

    let a = Future.ready(1)
    let b = Future.ready("A")
    let c = Future.ready("X")
    let f = a.join(b, c)
    assert(f.wait() == (1, "A", "X"))
    

    Declaration

    Swift

    @inlinable
    public func join<B, C>(_ b: B, _ c: C) -> Future._Private.Join3<Self, B, C> where B : FutureProtocol, C : FutureProtocol

    Return Value

    some FutureProtocol<Output == (Self.Output, B.Output, C.Output)>

  • join(_:_:_:) Extension method

    Combines the output from this future with that from three other futures by waiting until all futures complete and then completing with the output from each future together as a tuple.

    let a = Future.ready(1)
    let b = Future.ready("A")
    let c = Future.ready("X")
    let d = Future.ready(5)
    let f = a.join(b, c, d)
    assert(f.wait() == (1, "A", "X", 5))
    

    Declaration

    Swift

    @inlinable
    public func join<B, C, D>(_ b: B, _ c: C, _ d: D) -> Future._Private.Join4<Self, B, C, D> where B : FutureProtocol, C : FutureProtocol, D : FutureProtocol

    Return Value

    some FutureProtocol<Output == (Self.Output, B.Output, C.Output, D.Output)>

  • select(_:) Extension method

    Waits until either this future or the given one complete, and completes with the output from that future.

    let a = Future.ready(1)
    let b = Future.ready("A")
    let f = a.select(b)
    assert(f.wait() == .left(1))
    

    Declaration

    Swift

    @inlinable
    public func select<B>(_ other: B) -> Future._Private.Select<Self, B> where B : FutureProtocol

    Return Value

    some FutureProtocol<Output == Either<Self.Output, B.Output>>

  • flatten() Extension method

    Flattens the output from this future by waiting for the output of the future produced by this future.

    let a = Future.ready(4).map {
        Future.ready(String($0) + "2")
    }
    let f = a.flatten()
    assert(f.wait() == "42")
    

    Declaration

    Swift

    @inlinable
    public func flatten() -> Future._Private.Flatten<Self>

    Return Value

    some FutureProtocol<Output == Self.Output.FutureType.Output>

  • tryMap(_:) Extension method

    Transforms the output from this future with a provided error-throwing closure.

    enum UltimateQuestionError: Error {
        case wrongAnswer
    }
    
    func validateAnswer(_ answer: Int) throws -> Int {
        guard answer == 42 else {
            throw UltimateQuestionError.wrongAnswer
        }
        return answer
    }
    
    let f1 = Future.ready(42).tryMap(validateAnswer)
    assert(try! f1.wait().get() == 42)
    
    let f2 = Future.ready(5).tryMap(validateAnswer)
    assert(try? f2.wait().get() == nil)
    

    Declaration

    Swift

    @inlinable
    public func tryMap<T>(_ catching: @escaping (Output) throws -> T) -> Future._Private.TryMap<T, Self>

    Return Value

    some FutureProtocol<Output == Result<T, Error>>

  • setFailureType(to:) Extension method

    Converts this future to a failable one with the specified failure type.

    You typically use this combinator to match the error types of two mismatched failable futures.

    enum UltimateQuestionError: Error {
        case wrongAnswer
    }
    
    let f = Future.ready(42).setFailureType(to: UltimateQuestionError.self)
    assert(try! f.wait().get() == 42)
    

    Declaration

    Swift

    @inlinable
    public func setFailureType<E>(to _: E.Type) -> Future._Private.SetFailureType<Output, E, Self> where E : Error

    Return Value

    some FutureProtocol<Output == Result<Self.Output, E>>

  • match(success:failure:) Extension method

    .

    enum UltimateQuestionError: Error {
        case wrongAnswer
    }
    
    func validateAnswer(_ answer: Int) throws -> Int {
        guard answer == 42 else {
            throw UltimateQuestionError.wrongAnswer
        }
        return answer
    }
    
    let a1 = Future.ready(5).tryMap(validateAnswer)
    let f1 = a1.match(
        success: String.init,
        failure: String.init(describing:)
    )
    assert(f1.wait() == "wrongAnswer")
    
    let a2 = Future.ready(42).tryMap(validateAnswer)
    let f2 = a2.match(
        success: String.init,
        failure: String.init(describing:)
    )
    assert(f2.wait() == "42")
    

    Declaration

    Swift

    @inlinable
    public func match<T>(
        success: @escaping (Output.Success) -> T,
        failure: @escaping (Output.Failure) -> T
    ) -> Future._Private.MatchResult<T, Self>

    Return Value

    some FutureProtocol<Output == T>

  • mapValue(_:) Extension method

    .

    enum UltimateQuestionError: Error {
        case wrongAnswer
    }
    
    func validateAnswer(_ answer: Int) throws -> Int {
        guard answer == 42 else {
            throw UltimateQuestionError.wrongAnswer
        }
        return answer
    }
    
    let f1 = Future.ready(5).tryMap(validateAnswer).mapValue {
        $0 + 1
    }
    assert(try? f1.wait().get() == nil)
    
    let f2 = Future.ready(42).tryMap(validateAnswer).mapValue {
        $0 + 1
    }
    assert(try? f2.wait().get() == 43)
    

    Declaration

    Swift

    @inlinable
    public func mapValue<T>(_ transform: @escaping (Output.Success) -> T) -> Future._Private.MapResult<T, Output.Failure, Self>

    Return Value

    some FutureProtocol<Output == Result<T, Self.Output.Failure>>

  • mapError(_:) Extension method

    .

    enum UltimateQuestionError: Error {
        case wrongAnswer
    }
    
    func validateAnswer(_ answer: Int) throws -> Int {
        guard answer == 42 else {
            throw UltimateQuestionError.wrongAnswer
        }
        return answer
    }
    
    struct WrappedError: Error {
        let error: Error
    }
    
    let f1 = Future.ready(5).tryMap(validateAnswer).mapError {
        WrappedError(error: $0)
    }
    assert(try? f1.wait().get() == nil)
    
    let f2 = Future.ready(42).tryMap(validateAnswer).mapError {
        WrappedError(error: $0)
    }
    assert(try? f2.wait().get() == 42)
    

    Declaration

    Swift

    @inlinable
    public func mapError<E>(_ transform: @escaping (Output.Failure) -> E) -> Future._Private.MapResult<Output.Success, E, Self>

    Return Value

    some FutureProtocol<Output == Result<Self.Output.Success, E>>

  • flattenResult() Extension method

    .

    enum UltimateQuestionError: Error {
        case wrongAnswer
    }
    
    func validateAnswer(_ answer: Int) throws -> Int {
        guard answer == 42 else {
            throw UltimateQuestionError.wrongAnswer
        }
        return answer
    }
    
    let a1 = Future.ready(5)
        .tryMap(validateAnswer)
        .mapValue(Result<Int, Error>.success)
    let f1 = a1.flattenResult()
    assert(try? f1.wait().get() == nil)
    
    let a2 = Future.ready(42)
        .tryMap(validateAnswer)
        .mapValue(Result<Int, Error>.success)
    let f2 = a2.flattenResult()
    assert(try? f2.wait().get() == 42)
    

    Declaration

    Swift

    @inlinable
    public func flattenResult() -> Future._Private.FlattenResult<Self>

    Return Value

    some FutureProtocol<Output == Result<Self.Output.Success.Success, Self.Output.Failure>>

  • setFailureType(to:) Extension method

    Changes the failure type declared by this future.

    You typically use this combinator to match the error types of two mismatched result futures.

    enum UltimateQuestionError: Error {
        case wrongAnswer
    }
    
    let a = Future.ready(42).map(Result<Int, Never>.success)
    let f = a.setFailureType(to: UltimateQuestionError.self)
    
    assert(try! f.wait().get() == 42)
    

    Declaration

    Swift

    @inlinable
    public func setFailureType<E>(to _: E.Type) -> Future._Private.SetFailureType<Output.Success, E, Self> where E : Error

    Return Value

    some FutureProtocol<Output == Result<Self.Output.Success, E>>

  • assertNoError(_:file:line:) Extension method

    Raises a fatal error when this future fails.

    Declaration

    Swift

    @inlinable
    public func assertNoError(_ prefix: String = "", file: StaticString = #file, line: UInt = #line) -> Future._Private.AssertNoError<Self>

    Return Value

    some FutureProtocol<Output == Self.Output.Success>

  • replaceError(with:) Extension method

    Replaces failure with the provided element.

    enum UltimateQuestionError: Error {
        case wrongAnswer
    }
    
    func validateAnswer(_ answer: Int) throws -> Int {
        guard answer == 42 else {
            throw UltimateQuestionError.wrongAnswer
        }
        return answer
    }
    
    let a = Future.ready(5).tryMap(validateAnswer)
    let f = a.replaceError(with: 42)
    
    assert(f.wait() == 42)
    

    Declaration

    Swift

    @inlinable
    public func replaceError(with output: Output.Success) -> Future._Private.ReplaceError<Self>

    Return Value

    some FutureProtocol<Output == Self.Output.Success>

  • catchError(_:) Extension method

    Handles errors from this future by replacing it with another future on failure.

    enum UltimateQuestionError: Error {
        case wrongAnswer
    }
    
    func validateAnswer(_ answer: Int) throws -> Int {
        guard answer == 42 else {
            throw UltimateQuestionError.wrongAnswer
        }
        return answer
    }
    
    let f = Future.ready(5).tryMap(validateAnswer).catchError {
        _ in Future.ready(42)
    }
    
    assert(f.wait() == 42)
    

    Declaration

    Swift

    @inlinable
    public func catchError<U>(_ errorHandler: @escaping (Output.Failure) -> U) -> Future._Private.CatchError<U, Self>

    Return Value

    some FutureProtocol<Output == Self.Output.Success>

  • breakpoint(ready:pending:) Extension method

    Raises a debugger signal when a provided closure needs to stop the process in the debugger.

    When any of the provided closures returns true, this future raises the SIGTRAP signal to stop the process in the debugger.

    Declaration

    Swift

    @inlinable
    public func breakpoint(
        ready: @escaping (Output) -> Bool = { _ in false },
        pending: @escaping () -> Bool = { false }
    ) -> Future._Private.Breakpoint<Self>

    Return Value

    some FutureProtocol<Output == Self.Output>

  • handleEvents(ready:pending:) Extension method

    Performs the specified closures when poll events occur.

    Declaration

    Swift

    @inlinable
    public func handleEvents(
        ready: @escaping (Output) -> Void = { _ in },
        pending: @escaping () -> Void = {}
    ) -> Future._Private.HandleEvents<Self>

    Return Value

    some FutureProtocol<Output == Self.Output>

  • print(_:to:) Extension method

    Prints log messages for all poll events.

    Declaration

    Swift

    @inlinable
    public func print(_ prefix: String = "", to stream: TextOutputStream? = nil) -> Future._Private.Print<Self>

    Return Value

    some FutureProtocol<Output == Self.Output>

  • breakpointOnError() Extension method

    Raises a debugger signal upon receiving a failure.

    Declaration

    Swift

    @inlinable
    public func breakpointOnError() -> Future._Private.Breakpoint<Self>

    Return Value

    some FutureProtocol<Output == Self.Output>