Last active
July 1, 2025 14:57
-
-
Save levibostian/5cd7e93e17bcc863820503d73c0d649a to your computer and use it in GitHub Desktop.
Swift Atomic property wrapper using DispatchQueue
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Foundation | |
/** | |
Guarantee the wrapped value is only ever accessed from one thread at a time. | |
Inspired from: https://github.com/RougeWare/Swift-Atomic/blob/master/Sources/Atomic/Atomic.swift | |
*/ | |
@propertyWrapper | |
public struct Atomic<DataType: Any> { | |
fileprivate let exclusiveAccessQueue = DispatchQueue(label: "Atomic \(UUID())", qos: .userInteractive) | |
fileprivate var unsafeValue: DataType | |
/// Safely accesses the unsafe value from within the context of its exclusive-access queue | |
public var wrappedValue: DataType { | |
get { exclusiveAccessQueue.sync { unsafeValue } } | |
set { exclusiveAccessQueue.sync { unsafeValue = newValue } } | |
} | |
/// Safely access the unsafe value and keep a lock on it to perform operations on it before letting go. | |
public mutating func lock(_ block: (inout DataType) -> Void) { | |
exclusiveAccessQueue.sync { | |
// Create reference to we can modify the data | |
var existingValue = unsafeValue | |
// By passing the existingValue into the block with `inout`, it can be modified in that block. | |
block(&existingValue) | |
// Set the new value to the modified version. | |
self.unsafeValue = existingValue | |
} | |
} | |
/** | |
Initializer that satisfies @propertyWrapper's requirements. | |
With this initializer created, you can assign default values to our wrapped properties, | |
like this: `@Atomic var foo = Foo()` | |
*/ | |
public init(wrappedValue: DataType) { | |
self.unsafeValue = wrappedValue | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment