Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import Foundation
- //
- // Pool.swift
- //
- open class Pool<T> {
- // MARK: Initialization
- /**
- - parameter maxElementCount: Specifies the maximum number of element that the pool can manage.
- - parameter factory: Closure used to create new items for the pool.
- */
- public init(maxElementCount: Int, factory: @escaping () throws -> T) {
- self.factory = factory
- self.maxElementCount = maxElementCount
- self.semaphore = DispatchSemaphore(value: maxElementCount)
- }
- // MARK: Setting and Getting Attributes
- /// The maximum number of element that the pool can manage.
- public let maxElementCount: Int
- /// Closure used to create new items for the pool.
- public let factory: () throws -> T
- // MARK: Storage
- var elements = [T]()
- var elementCount = 0
- // MARK: Concurrency Management
- private let queue = DispatchQueue(label: Bundle.main.bundleIdentifier! + ".Pool")
- private let semaphore: DispatchSemaphore
- // MARK: Accessing Elements
- public func dequeue() throws -> T {
- // when count reaches zero, calls to the semaphore will block
- guard self.semaphore.wait(timeout: .distantFuture) == .success else {
- throw PoolError.drawTimeOut
- }
- return try self.queue.sync {
- guard self.elements.isEmpty, self.elementCount < self.maxElementCount else {
- // Use an existing element
- return self.elements.removeFirst()
- }
- // Create a new element
- do {
- let element = try self.factory()
- self.elementCount += 1
- return element
- } catch {
- self.semaphore.signal()
- throw PoolError.factoryError(error)
- }
- }
- }
- public func enqueue(_ element: T, completion: (() -> Void)? = nil) {
- self.queue.async {
- self.elements.append(element)
- self.semaphore.signal()
- completion?()
- }
- }
- deinit {
- for _ in 0..<self.elementCount {
- self.semaphore.signal()
- }
- }
- }
- public enum PoolError: Swift.Error {
- case drawTimeOut
- case factoryError(Swift.Error)
- }
Add Comment
Please, Sign In to add comment