Coroutine
public final class Coroutine
Lightweight coroutine.
Launching coroutines and switching between them is extremely fast.
It requires only a few machine instructions.
This makes coroutines a suitable basic flow control mechanism,
like the if
or while
keywords, which have comparable performance.
Coroutines have one big limitation, though: All coroutines run on a single CPU core. If you want to take advantage of multiple cores, you have to launch multiple threads or processes, presumably as many of them as there are CPU cores on your machine.
Coroutines are scheduled cooperatively. What that means is that a coroutine has to
explicitly yield control of the CPU to allow a different coroutine to run.
In a typical scenario, this is done transparently to the user: When a coroutine
invokes a function that would block (such as Coroutine.wakeUp
, FileDescriptor.poll
, channel.send
or channel.receive
),
the CPU is automatically yielded.
However, if a coroutine runs without calling any blocking functions, it may hold
the CPU forever. For these cases, the Coroutine.yield
function can be used to manually relinquish
the CPU to other coroutines manually.
Example:
let coroutine = try Coroutine {
...
}
coroutine.cancel()
-
Launches a coroutine that executes the closure passed as argument. The coroutine is executed concurrently, and its lifetime may exceed the lifetime of the caller.
Example:
let coroutine = try Coroutine { ... } coroutine.cancel()
Throws
The following errors might be thrown:
VeniceError.canceledCoroutine
Thrown when the operation is performed within a canceled coroutine.
VeniceError.outOfMemory
Thrown when the system doesn’t have enough memory to create a new coroutine.
Declaration
Swift
public init(body: @escaping () throws -> Void) throws
Parameters
body
Body of the newly created coroutine.
-
Cancels the coroutine.
Warning
Once a coroutine is canceled any coroutine-blocking operation within the coroutine will throwVeniceError.canceledCoroutine
.Declaration
Swift
public func cancel()
-
Explicitly passes control to other coroutines. By calling this function, you give other coroutines a chance to run.
You should consider using
Coroutiner.yield()
when doing lengthy computations which don’t have natural coroutine switching points.Example:
for _ in 0 ..< 1000000 { expensiveComputation() try Coroutine.yield() // Give other coroutines a chance to run. }
Warning
Once a coroutine is canceled calling
Couroutine.yield
will throwVeniceError.canceledCoroutine
.Throws
The following errors might be thrown:
VeniceError.canceledCoroutine
Thrown when the operation is performed within a canceled coroutine.
Declaration
Swift
public static func yield() throws
-
Wakes up at deadline.
Example:
func execute<R>(_ deadline: Deadline, body: (Void) throws -> R) throws -> R { try Coroutine.wakeUp(deadline) try body() } try execute(1.second.fromNow()) { print("Hey! Ho! Let's go!") }
Warning
Once a coroutine is canceled calling
Couroutine.wakeUp
will throwVeniceError.canceledCoroutine
.Throws
The following errors might be thrown:
VeniceError.canceledCoroutine
Thrown when the operation is performed within a canceled coroutine.
Declaration
Swift
public static func wakeUp(_ deadline: Deadline) throws
-
Coroutine groups are useful for canceling multiple coroutines at the same time.
Example:
See morelet group = Coroutine.Group(minimumCapacity: 2) try group.addCoroutine { ... } try group.addCoroutine { ... } // all coroutines in the group will be canceled group.cancel()
Declaration
Swift
public class Group