session-ios/SessionUtilitiesKit/General/Atomic.swift
Morgan Pretty 58184d6d27 Fixed issues found during testing
Fixed an issue where the user config message wouldn't get sent correctly
Fixed an issue where the theme preference migration wasn't working properly
Fixed a crash which could occur in some cases when updating the theme
Fixed a crash which could occur when opening the new conversation screen with a contact with no name
Fixed a minor UI glitch with the 'sessionId' separator border
Fixed a minor UI issue where long author names in quotes could cause the message bubble to stretch incorrectly
Cleaned up some no-contact UI states
Updated the Atomic queue to have a 'userInteractive' priority so it can't be delayed by lower priority queues and block the main thread
2022-10-07 15:35:17 +11:00

52 lines
1.7 KiB
Swift

// Copyright © 2022 Rangeproof Pty Ltd. All rights reserved.
import Foundation
// MARK: - Atomic<Value>
/// The `Atomic<Value>` wrapper is a generic wrapper providing a thread-safe way to get and set a value
///
/// A write-up on the need for this class and it's approach can be found here:
/// https://www.vadimbulavin.com/swift-atomic-properties-with-property-wrappers/
/// there is also another approach which can be taken but it requires separate types for collections and results in
/// a somewhat inconsistent interface between different `Atomic` wrappers
@propertyWrapper
public class Atomic<Value> {
// Note: Using 'userInteractive' to ensure this can't be blockedby higher priority queues
// which could result in the main thread getting blocked
private let queue: DispatchQueue = DispatchQueue(
label: "io.oxen.\(UUID().uuidString)",
qos: .userInteractive
)
private var value: Value
/// In order to change the value you **must** use the `mutate` function
public var wrappedValue: Value {
return queue.sync { return value }
}
/// For more information see https://github.com/apple/swift-evolution/blob/master/proposals/0258-property-wrappers.md#projections
public var projectedValue: Atomic<Value> {
return self
}
// MARK: - Initialization
public init(_ initialValue: Value) {
self.value = initialValue
}
// MARK: - Functions
@discardableResult public func mutate<T>(_ mutation: (inout Value) -> T) -> T {
return queue.sync {
return mutation(&value)
}
}
}
extension Atomic where Value: CustomDebugStringConvertible {
var debugDescription: String {
return value.debugDescription
}
}