@@ -393,38 +393,44 @@ producer has been terminated will result in an error thrown from the send method
393393## Detailed design
394394
395395``` swift
396- #if compiler (>= 6.0 )
396+ #if compiler (>= 6.1 )
397397/// An error that is thrown from the various `send` methods of the
398398/// ``MultiProducerSingleConsumerChannel/Source``.
399399///
400400/// This error is thrown when the channel is already finished when
401401/// trying to send new elements to the source.
402402public struct MultiProducerSingleConsumerChannelAlreadyFinishedError : Error { }
403403
404- /// A multi producer single consumer channel.
404+ /// A multi- producer single- consumer channel.
405405///
406406/// The ``MultiProducerSingleConsumerChannel`` provides a ``MultiProducerSingleConsumerChannel/Source`` to
407407/// send values to the channel. The channel supports different back pressure strategies to control the
408408/// buffering and demand. The channel will buffer values until its backpressure strategy decides that the
409409/// producer have to wait.
410410///
411+ /// This channel is also suitable for the single-producer single-consumer use-case
411412///
412413/// ## Using a MultiProducerSingleConsumerChannel
413414///
414- /// To use a ``MultiProducerSingleConsumerChannel`` you have to create a new channel with it's source first by calling
415+ /// To use a ``MultiProducerSingleConsumerChannel`` you have to create a new channel with its source first by calling
415416/// the ``MultiProducerSingleConsumerChannel/makeChannel(of:throwing:BackpressureStrategy:)`` method.
416417/// Afterwards, you can pass the source to the producer and the channel to the consumer.
417418///
418419/// ```
419- /// let (channel, source) = MultiProducerSingleConsumerChannel<Int, Never>.makeChannel(
420+ /// let channelAndSource = MultiProducerSingleConsumerChannel.makeChannel(
421+ /// of: Int.self,
420422/// backpressureStrategy: .watermark(low: 2, high: 4)
421423/// )
424+ ///
425+ /// // The channel and source can be extracted from the returned type
426+ /// let channel = consume channelAndSource.channel
427+ /// let source = consume channelAndSource.source
422428/// ```
423429///
424- /// ### Asynchronous producers
430+ /// ### Asynchronous producing
425431///
426- /// Values can be send to the source from asynchronous contexts using ``MultiProducerSingleConsumerChannel/Source/send(_:)-9b5do ``
427- /// and ``MultiProducerSingleConsumerChannel/Source/send(contentsOf:)-4myrz ``. Backpressure results in calls
432+ /// Values can be send to the source from asynchronous contexts using ``MultiProducerSingleConsumerChannel/Source/send(_:)-8eo96 ``
433+ /// and ``MultiProducerSingleConsumerChannel/Source/send(contentsOf:)``. Backpressure results in calls
428434/// to the `send` methods to be suspended. Once more elements should be produced the `send` methods will be resumed.
429435///
430436/// ```
@@ -441,10 +447,54 @@ public struct MultiProducerSingleConsumerChannelAlreadyFinishedError: Error { }
441447/// }
442448/// ```
443449///
444- /// ### Synchronous producers
450+ /// ### Synchronous produceing
445451///
446452/// Values can also be send to the source from synchronous context. Backpressure is also exposed on the synchronous contexts; however,
447453/// it is up to the caller to decide how to properly translate the backpressure to underlying producer e.g. by blocking the thread.
454+ ///
455+ /// ```swift
456+ /// do {
457+ /// let sendResult = try source.send(contentsOf: sequence)
458+ ///
459+ /// switch sendResult {
460+ /// case .produceMore:
461+ /// // Trigger more production in the underlying system
462+ ///
463+ /// case .enqueueCallback(let callbackToken):
464+ /// // There are enough values in the channel already. We need to enqueue
465+ /// // a callback to get notified when we should produce more.
466+ /// source.enqueueCallback(token: callbackToken, onProduceMore: { result in
467+ /// switch result {
468+ /// case .success:
469+ /// // Trigger more production in the underlying system
470+ /// case .failure(let error):
471+ /// // Terminate the underlying producer
472+ /// }
473+ /// })
474+ /// }
475+ /// } catch {
476+ /// // `send(contentsOf:)` throws if the channel already terminated
477+ /// }
478+ /// ```
479+ ///
480+ /// ### Multiple producers
481+ ///
482+ /// To support multiple producers the source offers a ``Source/copy()`` method to produce a new source.
483+ ///
484+ /// ### Terminating the production of values
485+ ///
486+ /// The consumer can be terminated through multiple ways:
487+ /// - Calling ``Source/finish(throwing:)``.
488+ /// - Deiniting all sources.
489+ ///
490+ /// In both cases, if there are still elements buffered by the channel, then the consumer will receive
491+ /// all buffered elements. Afterwards it will be terminated.
492+ ///
493+ /// ### Observing termination of the consumer
494+ ///
495+ /// When the consumer stops consumption by either deiniting the channel or the task calling ``next(isolation:)``
496+ /// getting cancelled, the source will get notified about the termination if a termination callback has been set
497+ /// before by calling ``Source/setOnTerminationCallback(_:)``.
448498@available (macOS 15.0 , iOS 18.0 , watchOS 11.0 , tvOS 18.0 , visionOS 2.0 , * )
449499public struct MultiProducerSingleConsumerChannel <Element , Failure : Error >: ~ Copyable {
450500 /// A struct containing the initialized channel and source.
@@ -783,6 +833,12 @@ has been offered with the `Continuation` based approach and
783833introduced new factory methods to solve some of the usability ergonomics with
784834the initializer based APIs.
785835
836+ ### Provide the type on older compilers
837+
838+ To achieve maximum performance the implementation is using ` ~Copyable ` extensively.
839+ On Swift versions before 6.1, there is a https://github.com/swiftlang/swift/issues/78048 when using; hence, this type
840+ is only usable with Swift 6.1 and later compilers.
841+
786842## Acknowledgements
787843
788844- [ Johannes Weiss] ( https://github.com/weissi ) - For making me aware how
0 commit comments