From e1b87288d03e152214e224c5b9b099a83a0b97e9 Mon Sep 17 00:00:00 2001 From: James J Kalafus Date: Sun, 4 Feb 2024 18:14:22 -0500 Subject: [PATCH] array thread safety wrapper to fix racing condition causing `Fatal error: UnsafeMutablePointer.moveUpdate(from:) with negative count` at `self?.streamingSessions.removeAll(where: { $0 == object })` --- Sources/OpenAI/OpenAI.swift | 2 +- .../Utilities/ArrayWithThreadSafety.swift | 26 +++++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) create mode 100644 Sources/OpenAI/Public/Utilities/ArrayWithThreadSafety.swift diff --git a/Sources/OpenAI/OpenAI.swift b/Sources/OpenAI/OpenAI.swift index cfb1e9d1..182fced1 100644 --- a/Sources/OpenAI/OpenAI.swift +++ b/Sources/OpenAI/OpenAI.swift @@ -35,7 +35,7 @@ final public class OpenAI: OpenAIProtocol { } private let session: URLSessionProtocol - private var streamingSessions: [NSObject] = [] + private var streamingSessions = ArrayWithThreadSafety() public let configuration: Configuration diff --git a/Sources/OpenAI/Public/Utilities/ArrayWithThreadSafety.swift b/Sources/OpenAI/Public/Utilities/ArrayWithThreadSafety.swift new file mode 100644 index 00000000..a0c4db64 --- /dev/null +++ b/Sources/OpenAI/Public/Utilities/ArrayWithThreadSafety.swift @@ -0,0 +1,26 @@ +// +// ArrayWithThreadSafety.swift +// +// +// Created by James J Kalafus on 2024-02-01. +// + +import Foundation + +internal class ArrayWithThreadSafety { + private var array = [Element]() + private let queue = DispatchQueue(label: "us.kalaf.OpenAI.threadSafeArray", attributes: .concurrent) + + @inlinable public func append(_ element: Element) { + queue.async(flags: .barrier) { + self.array.append(element) + } + } + + @inlinable public func removeAll(where shouldBeRemoved: @escaping (Element) throws -> Bool) rethrows { + try queue.sync(flags: .barrier) { + try self.array.removeAll(where: shouldBeRemoved) + } + } +} +