Classes

The following classes are available globally.

  • Channel is a non-blocking primitive for communication between a sender and a receiver. Conceptually, a channel is similar to a queue that allows to suspend a coroutine on receive if it is empty or on send if it is full.

    Important

    Always close() or cancel() a channel when you are done to resume all suspended coroutines by the channel.
    let channel = CoChannel<Int>(capacity: 1)
    
    DispatchQueue.global().startCoroutine {
       for i in 0..<100 {
           try channel.awaitSend(i)
       }
       channel.close()
    }
    
    DispatchQueue.global().startCoroutine {
        for i in channel.makeIterator() {
            print("Receive", i)
        }
        print("Done")
    }
    
    See more

    Declaration

    Swift

    public final class CoChannel<Element>
    extension CoChannel: CoCancellable
  • Holder for a result that will be provided later.

    CoFuture and its subclass CoPromise are the implementation of the Future/Promise approach. They allow to launch asynchronous tasks and immediately returnCoFuture with its future results. The available result can be observed by the whenComplete() callback or by await() inside a coroutine without blocking a thread.

    func makeFutureOne(args) -> CoFuture<Response> {
        let promise = CoPromise<Response>()
        someAsyncFuncWithCallback { response in
            . . . do some work . . .
            promise.success(response)
        }
        return promise
    }
    
    func makeFutureTwo(args) -> CoFuture<Response> {
        queue.coroutineFuture {
            let future = makeFutureOne(args)
            . . . do some work . . .
            let response = try future.await()
            . . . create result using response . . .
            return result
        }
     }
    
    func performSomeWork(args) {
        let future = makeFutureTwo(args)
        mainQueue.startCoroutine {
            . . . do some work . . .
            let result = try future.await()
            . . . do some work using result . . .
        }
    }
    

    For coroutine error handling you can use standart do-catch statement or use CoFuture as an alternative.

    //execute coroutine and return CoFuture<Void> that we will use for error handling
    DispatchQueue.main.coroutineFuture {
        let result = try makeSomeFuture().await()
        . . . use result . . .
    }.whenFailure { error in
        . . . handle error . . .
    }
    

    Apple has introduced a new reactive programming framework Combine that makes writing asynchronous code easier and includes a lot of convenient and common functionality. We can use it with coroutines by making CoFuture a subscriber and await its result.

    //create Combine publisher
    let publisher = URLSession.shared.dataTaskPublisher(for: url).map(\.data)
    
    //execute coroutine on the main thread
    DispatchQueue.main.startCoroutine {
        //subscribe CoFuture to publisher
        let future = publisher.subscribeCoFuture()
    
        //await data without blocking the thread
        let data: Data = try future.await()
    }
    
    See more

    Declaration

    Swift

    public class CoFuture<Value>
    extension CoFuture: Hashable
    extension CoFuture: CoCancellable
  • A promise to provide a result later.

    CoPromise is a subclass of CoFuture that allows to deliver the result. You can set the result to CoPromise only once, other attempts will be ignored.

    See more

    Declaration

    Swift

    public final class CoPromise<Value> : CoFuture<Value>
  • The holder of uncompleted CoCancellable and coroutines.

    CoScope helps to manage lifecycle of coroutines and CoCancellable, like CoFuture and CoChannel. It keeps weak references on inner objects and cancels them on cancel() or deinit. All completed objects are automaticaly removed from scope.

    Note

    CoScope keeps weak references.
    let scope = CoScope()
    
    let future = makeSomeFuture().added(to: scope)
    
    queue.startCoroutine(in: scope) {
        . . . some code . . .
        let result = try future.await()
        . . . some code . . .
    }
    
    let future2 = queue.coroutineFuture {
        try Coroutine.delay(.seconds(5)) // imitate some work
        return 5
    }.added(to: scope)
    
    //cancel all added futures and coroutines
    scope.cancel()
    
    See more

    Declaration

    Swift

    public final class CoScope
    extension CoScope: CoCancellable