jsdw_ios/Pods/CocoaMQTT/Source/utilities/ConcurrentAtomic.swift

74 lines
2.7 KiB
Swift

import Foundation
/// A thread-safe property wrapper that uses a concurrent dispatch queue for atomic operations.
///
/// This wrapper provides both synchronous and asynchronous access to a wrapped value in a
/// thread-safe manner using `DispatchQueue` with `.concurrent` attributes and `.barrier` writes.
///
/// - Important: Although this wrapper provides atomicity for access, it does not make the wrapped
/// value itself thread-safe if the type is not thread-safe. Avoid wrapping types that manage
/// internal shared state without their own synchronization.
///
/// - Example:
/// ```swift
/// @ConcurrentAtomic var counter: Int = 0
/// counter += 1
/// print(counter)
/// ```
@propertyWrapper
public class ConcurrentAtomic<T> {
private var _value: T
private let queue: DispatchQueue
/// Provides synchronous thread-safe access to the wrapped value.
///
/// - Note: Reads use `queue.sync` and can happen concurrently.
/// - Warning: Writes are done asynchronously with `.barrier`, so a following read may
/// not reflect the new value immediately.
public var wrappedValue: T {
get {
queue.sync { _value }
}
set {
queue.async(flags: .barrier) {
self._value = newValue
}
}
}
/// Returns the property wrapper instance itself for advanced usage, including mutation and transformation APIs.
public var projectedValue: ConcurrentAtomic<T> { self }
/// Initializes the property wrapper with an initial value and a custom queue label.
///
/// - Parameters:
/// - wrappedValue: The initial value to store.
/// - label: A debug label for the underlying `DispatchQueue`. Default is `"ConcurrentAtomic.Queue"`.
public init(wrappedValue: T, label: String = "ConcurrentAtomic.Queue") {
self._value = wrappedValue
self.queue = DispatchQueue(label: label, attributes: .concurrent)
}
/// Synchronously sets a new value in a thread-safe manner.
///
/// This uses `.barrier` to ensure the new value is fully written before continuing.
///
/// - Parameter newValue: The new value to be written.
public func setSync(_ newValue: T) {
queue.sync(flags: .barrier) {
self._value = newValue
}
}
/// Asynchronously mutates the wrapped value using a transform closure.
///
/// The mutation is performed with `.barrier`, ensuring it does not overlap with other reads or writes.
///
/// - Parameter transform: A closure that receives `inout` access to the wrapped value.
public func mutate(_ transform: @escaping (inout T) -> Void) {
queue.async(flags: .barrier) {
transform(&self._value)
}
}
}