Make EventLoopFuture.wait() unavailable from async (#2331)

Motivation:

ELF.wait() waits for a condition variable to become true, which can
frequently lead to extremely long waits. This is a bad thing to call on
a Swift Concurrency thread, especially as we have ELF.get() which is
preferable.

Modifications:

Make ELF.wait() unavailable from async.

Result:

Users are encouraged to use the correct primitive.
This commit is contained in:
Cory Benfield 2022-12-12 14:13:24 +00:00 committed by GitHub
parent abf2b35e6d
commit a58500af68
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 29 additions and 1 deletions

View File

@ -1223,6 +1223,7 @@ extension EventLoopFuture {
// MARK: wait
extension EventLoopFuture {
#if swift(>=5.7)
/// Wait for the resolution of this `EventLoopFuture` by blocking the current thread until it
/// resolves.
///
@ -1232,10 +1233,37 @@ extension EventLoopFuture {
/// threads: it is primarily useful for testing, or for building interfaces between blocking
/// and non-blocking code.
///
/// This is also forbidden in async contexts: prefer ``EventLoopFuture/get``.
///
/// - returns: The value of the `EventLoopFuture` when it completes.
/// - throws: The error value of the `EventLoopFuture` if it errors.
@available(*, noasync, message: "wait() can block indefinitely, prefer get()", renamed: "get()")
@inlinable
public func wait(file: StaticString = #file, line: UInt = #line) throws -> Value {
return try self._wait(file: file, line: line)
}
#else
/// Wait for the resolution of this `EventLoopFuture` by blocking the current thread until it
/// resolves.
///
/// If the `EventLoopFuture` resolves with a value, that value is returned from `wait()`. If
/// the `EventLoopFuture` resolves with an error, that error will be thrown instead.
/// `wait()` will block whatever thread it is called on, so it must not be called on event loop
/// threads: it is primarily useful for testing, or for building interfaces between blocking
/// and non-blocking code.
///
/// This is also forbidden in async contexts: prefer ``EventLoopFuture/get``.
///
/// - returns: The value of the `EventLoopFuture` when it completes.
/// - throws: The error value of the `EventLoopFuture` if it errors.
@inlinable
public func wait(file: StaticString = #fileID, line: UInt = #line) throws -> Value {
public func wait(file: StaticString = #file, line: UInt = #line) throws -> Value {
return try self._wait(file: file, line: line)
}
#endif
@inlinable
func _wait(file: StaticString, line: UInt) throws -> Value {
self.eventLoop._preconditionSafeToWait(file: file, line: line)
let v: UnsafeMutableTransferBox<Result<Value, Error>?> = .init(nil)