Skip to content

Instantly share code, notes, and snippets.

@robertmryan
Created September 18, 2024 18:37
Show Gist options
  • Save robertmryan/a9c3dc36d9557f9396baefbc876c9b9b to your computer and use it in GitHub Desktop.
Save robertmryan/a9c3dc36d9557f9396baefbc876c9b9b to your computer and use it in GitHub Desktop.
final class ComplexData: @unchecked Sendable {
private let lock = NSLock()
private var _name: String
var name: String {
get { lock.withLock { _name } }
set { lock.withLock { _name = newValue } }
}
init(name: String) {
_name = name
}
}
@robertmryan
Copy link
Author

As an aside, this pattern only works if the properties are not reference types with their own mutable properties. We’re OK with String, but if you add more properties, be wary of this limitation.

@robertmryan
Copy link
Author

By the way, if you're worried about how hairy ComplexData might get with lots and lots of properties, you can abstract this synchronization logic out into a property wrapper:

@propertyWrapper
struct Synchronized<T>: @unchecked Sendable {
    private var _wrappedValue: T
    private let lock = NSLock()

    var wrappedValue: T {
        get { lock.withLock { _wrappedValue } }
        set { lock.withLock { _wrappedValue = newValue } }
    }

    init(wrappedValue: T) {
        _wrappedValue = wrappedValue
    }
}

final class ComplexData: @unchecked Sendable {
    @Synchronized var firstName: String
    @Synchronized var lastName: String

    init(firstName: String, lastName: String) {
        self.firstName = firstName
        self.lastName = lastName
    }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment