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

Code before:
//===----------------------------------------------------------------------===//
//
// This source file is part of the SwiftNIO open source project
//
// Copyright (c) 2023 Apple Inc. and the SwiftNIO project authors
// Licensed under Apache License v2.0
//
// See LICENSE.txt for license information
// See CONTRIBUTORS.txt for the list of SwiftNIO project authors
//
// SPDX-License-Identifier: Apache-2.0
//
//===----------------------------------------------------------------------===//

protocol PoolElement {
    init()
    func evictedFromPool()
}

class Pool<Element: PoolElement> {
    private let maxSize: Int
    private var elements: [Element]

    init(maxSize: Int) {
        self.maxSize = maxSize
        self.elements = [Element]()
    }

    deinit {
        for e in elements {
            e.evictedFromPool()
        }
    }

    func get() -> Element {
        if elements.isEmpty {
            return Element()
        }
        else {
            return elements.removeLast()
        }
    }

    func put(_ e: Element) {
        if (elements.count == maxSize) {
            e.evictedFromPool()
        }
        else {
            elements.append(e)
        }
    }
}


Review comment (suggestion):
For reviewers: this function isn't in use right now, but I added it because it's a necessary component for io_uring support, where the buffer will need to outlive the closure-scoped usage site.

Code after:
        self.validateSentinel()
    }

    func withUnsafePointers<ReturnValue>(
        _ body: (UnsafeMutableBufferPointer<IOVector>, UnsafeMutableBufferPointer<Unmanaged<AnyObject>>) throws -> ReturnValue
    ) rethrows -> ReturnValue {
        defer {
            self.validateSentinel()
        }
        return try self.storage.withUnsafeMutableTypedPointers { iovecPointer, ownerPointer, _ in
            try body(iovecPointer, ownerPointer)
        }
    }

    /// Yields buffer pointers containing this ``PooledBuffer``'s readable bytes. You may hold a pointer to those bytes
    /// even after the closure has returned iff you model the lifetime of those bytes correctly using the `Unmanaged`
    /// instance. If you don't require the pointer after the closure returns, use ``withUnsafePointers``.
    ///
    /// If you escape the pointer from the closure, you _must_ call `storageManagement.retain()` to get ownership to
    /// the bytes and you also must call `storageManagement.release()` if you no longer require those bytes. Calls to
    /// `retain` and `release` must be balanced.
    ///
    /// - parameters:
    ///     - body: The closure that will accept the yielded pointers and the `storageManagement`.
    /// - returns: The value returned by `body`.
    func withUnsafePointersWithStorageManagement<ReturnValue>(
            _ body: (UnsafeMutableBufferPointer<IOVector>, UnsafeMutableBufferPointer<Unmanaged<AnyObject>>, Unmanaged<AnyObject>) throws -> ReturnValue
    ) rethrows -> ReturnValue {
        let storageRef: Unmanaged<AnyObject> = Unmanaged.passUnretained(self.storage)
        return try self.storage.withUnsafeMutableTypedPointers { iovecPointer, ownerPointer, _ in
            try body(iovecPointer, ownerPointer, storageRef)
        }
    }

    private func configureSentinel() {
        self.storage.withUnsafeMutableTypedPointers { _, _, sentinelPointer in
            sentinelPointer.pointee = Self.sentinelValue
        }
    }

    private func validateSentinel() {
        self.storage.withUnsafeMutableTypedPointers { _, _, sentinelPointer in
            precondition(sentinelPointer.pointee == Self.sentinelValue, "Detected memory handling error!")
        }
    }
}

extension PooledBuffer {
    fileprivate typealias MemorySentinel = UInt32

    fileprivate struct PooledBufferHead {