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
).
-
Declaration
Swift
associatedtype Output
-
-
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)
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 methodSynchronously 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 methodSynchronously 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 methodDeclaration
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 methodDeclaration
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 methodEnsures 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)
Return Value
AnyFuture<Self.Output>
-
map(_:)
Extension methodTransforms 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
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
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
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
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
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
Return Value
some FutureProtocol<Output == Result<U.FutureType.Output, E.Failure>>
-
peek(_:)
Extension methodCalls the given closure on the output of this future.
let f = Future.ready(42).peek { print($0) } assert(f.wait() == 42)
Declaration
Return Value
some FutureProtocol<Output == Self.Output>
-
replaceNil(with:)
Extension methodReplaces 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
Return Value
some FutureProtocol<Output == T>
-
replaceOutput(with:)
Extension methodReplaces 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 methodIgnores 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
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
Return Value
some FutureProtocol<Output == T>
-
join(_:)
Extension methodCombines 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 methodCombines 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 methodCombines 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 methodWaits 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 methodFlattens 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 methodTransforms 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
Return Value
some FutureProtocol<Output == Result<T, Error>>
-
setFailureType(to:)
Extension methodConverts 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
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
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
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
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 methodChanges 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
Return Value
some FutureProtocol<Output == Result<Self.Output.Success, E>>
-
assertNoError(_:file:line:)
Extension methodRaises 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 methodReplaces 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
Return Value
some FutureProtocol<Output == Self.Output.Success>
-
catchError(_:)
Extension methodHandles 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
Return Value
some FutureProtocol<Output == Self.Output.Success>
-
breakpoint(ready:pending:)
Extension methodRaises 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 theSIGTRAP
signal to stop the process in the debugger.Declaration
Return Value
some FutureProtocol<Output == Self.Output>
-
handleEvents(ready:pending:)
Extension methodPerforms the specified closures when poll events occur.
Declaration
Return Value
some FutureProtocol<Output == Self.Output>
-
print(_:to:)
Extension methodPrints 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 methodRaises a debugger signal upon receiving a failure.
Declaration
Swift
@inlinable public func breakpointOnError() -> Future._Private.Breakpoint<Self>
Return Value
some FutureProtocol<Output == Self.Output>