Repository: apple/swift-nio
File: Sources/NIOPosix/PendingWritesManager.swift (Swift)

Code before:
                    "We are in .closed state but we still have pending writes. This should never happen."
                )
            }

        }

        return closeResult
    }

    /// Signal that the `Channel` is closed.
    func closeComplete(_ error: Error? = nil) {
        assert(self.isOpen)
        assert(self.isEmpty)

        switch self.outboundCloseState {
        case .readyForClose(let closePromise):
            self.outboundCloseState = .closed
            if let error {
                closePromise?.fail(error)
            } else {
                closePromise?.succeed(())
            }
        case .closed:
            ()  // nothing to do
        case .open, .pending:
            preconditionFailure("close complete called on channel in unexpected state: \(self.outboundCloseState)")
        }
    }

    /// Initialize with a pre-allocated array of IO vectors and storage references. We pass in these pre-allocated
    /// objects to save allocations. They can be safely be re-used for all `Channel`s on a given `EventLoop` as an
    /// `EventLoop` always runs on one and the same thread. That means that there can't be any writes of more than
    /// one `Channel` on the same `EventLoop` at the same time.
    ///
    /// - Parameters:
    ///   - bufferPool: Pool of buffers to be used for iovecs and storage references
    init(bufferPool: Pool<PooledBuffer>) {
        self.bufferPool = bufferPool
    }
}

internal enum CloseState {
    case open
    case pending(EventLoopPromise<Void>?)
    case readyForClose(EventLoopPromise<Void>?)
    case closed
}

internal enum CloseResult: Equatable {
    case open
    case pending

Review comment (bug):
Can we make this a thrown error instead of a crash?

Code after:
    }

    /// Signal the intention to close. Takes a promise which will be returned for completing when pending writes are dealt with
    ///
    /// - Parameters:
    ///   - promise: Optionally an `EventLoopPromise` which is stored and is returned to be completed by the caller once
    ///              all outstanding writes have been dealt with or an error condition is encountered.
    func closeOutbound(_ promise: EventLoopPromise<Void>?) -> CloseOutboundResult {
        assert(self.isOpen)

        // Update our internal state
        switch self.outboundCloseState {
        case .open:
            if self.isEmpty {
                self.outboundCloseState = .readyForClose(promise)
            } else {
                self.outboundCloseState = .pending(promise)
            }
        case .readyForClose(var closePromise):
            closePromise.setOrCascade(to: promise)
            self.outboundCloseState = .readyForClose(closePromise)
        case .pending(var closePromise):
            closePromise.setOrCascade(to: promise)
            if self.isEmpty {
                self.outboundCloseState = .readyForClose(closePromise)
            } else {
                self.outboundCloseState = .pending(closePromise)
            }
        case .closed:
            ()
        }

        // Decide on the result
        let result = CloseOutboundResult(self.outboundCloseState, self.isEmpty, promise)

        return result
    }

    /// Initialize with a pre-allocated array of IO vectors and storage references. We pass in these pre-allocated
    /// objects to save allocations. They can be safely be re-used for all `Channel`s on a given `EventLoop` as an
    /// `EventLoop` always runs on one and the same thread. That means that there can't be any writes of more than
    /// one `Channel` on the same `EventLoop` at the same time.
    ///
    /// - Parameters:
    ///   - bufferPool: Pool of buffers to be used for iovecs and storage references
    init(bufferPool: Pool<PooledBuffer>) {
        self.bufferPool = bufferPool
    }
}

internal enum WriteMechanism {