Skip to content

Instantly share code, notes, and snippets.

@swhitty
Last active October 14, 2025 15:20
Show Gist options
  • Save swhitty/571deb25d84c1954a7a01aafa661496e to your computer and use it in GitHub Desktop.
Save swhitty/571deb25d84c1954a7a01aafa661496e to your computer and use it in GitHub Desktop.

Revisions

  1. swhitty revised this gist Jun 3, 2025. 1 changed file with 2 additions and 2 deletions.
    4 changes: 2 additions & 2 deletions Mutex.swift
    Original file line number Diff line number Diff line change
    @@ -23,9 +23,9 @@ public struct Mutex<Value: ~Copyable>: @unchecked Sendable, ~Copyable {
    return try body(&storage.value)
    }

    public borrowing func withLockIfAvailable<Result, E>(
    public borrowing func withLockIfAvailable<Result, E: Error>(
    _ body: (inout sending Value) throws(E) -> sending Result
    ) throws(E) -> sending Result? where E: Error {
    ) throws(E) -> sending Result? {
    guard lock.lockIfAvailable() else { return nil }
    defer { lock.unlock() }
    return try body(&storage.value)
  2. swhitty revised this gist Jun 3, 2025. 1 changed file with 2 additions and 2 deletions.
    4 changes: 2 additions & 2 deletions Mutex.swift
    Original file line number Diff line number Diff line change
    @@ -5,8 +5,8 @@
    import struct os.OSAllocatedUnfairLock

    // Backports the Swift 6.0 Mutex API
    @available(iOS, introduced: 16.0, deprecated: 18.0, message: "use Mutex from Synchronization module included with Swift 6")
    @available(macOS, introduced: 13.0, deprecated: 15.0, message: "use Mutex from Synchronization module included with Swift 6")
    @available(iOS, introduced: 16.0, deprecated: 18.0, message: "use Mutex from Synchronization module")
    @available(macOS, introduced: 13.0, deprecated: 15.0, message: "use Mutex from Synchronization module")
    public struct Mutex<Value: ~Copyable>: @unchecked Sendable, ~Copyable {
    private let lock = OSAllocatedUnfairLock()
    private let storage: Storage
  3. swhitty revised this gist Jun 3, 2025. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion Mutex.swift
    Original file line number Diff line number Diff line change
    @@ -31,7 +31,7 @@ public struct Mutex<Value: ~Copyable>: @unchecked Sendable, ~Copyable {
    return try body(&storage.value)
    }

    final class Storage {
    private final class Storage {
    var value: Value

    init(_ initialValue: consuming Value) {
  4. swhitty revised this gist Jun 3, 2025. 1 changed file with 17 additions and 31 deletions.
    48 changes: 17 additions & 31 deletions Mutex.swift
    Original file line number Diff line number Diff line change
    @@ -1,55 +1,41 @@
    // Backports the Swift 6 type Mutex<Value> to all Darwin platforms via OSAllocatedUnfairLock.
    // Lightweight version of https://github.com/swhitty/swift-mutex
    // Feel free to use any part of this gist.
    // Note: Value: ~Copyable are not supported

    import struct os.OSAllocatedUnfairLock

    // Backports the Swift 6.0 Mutex API
    @available(iOS, introduced: 16.0, deprecated: 18.0, message: "use Mutex from Synchronization module included with Swift 6")
    @available(macOS, introduced: 13.0, deprecated: 15.0, message: "use Mutex from Synchronization module included with Swift 6")
    public struct Mutex<Value>: @unchecked Sendable, ~Copyable {
    let lock: OSAllocatedUnfairLock<Value>
    public struct Mutex<Value: ~Copyable>: @unchecked Sendable, ~Copyable {
    private let lock = OSAllocatedUnfairLock()
    private let storage: Storage

    public init(_ initialValue: consuming sending Value) {
    self.lock = OSAllocatedUnfairLock(uncheckedState: initialValue)
    self.storage = Storage(initialValue)
    }

    public borrowing func withLock<Result, E: Error>(
    _ body: (inout sending Value) throws(E) -> sending Result
    ) throws(E) -> sending Result {
    do {
    return try lock.withLockUnchecked { value in
    nonisolated(unsafe) var copy = value
    defer { value = copy }
    return try Transferring(body(&copy))
    }.value
    } catch let error as E {
    throw error
    } catch {
    preconditionFailure("cannot occur")
    }
    lock.lock()
    defer { lock.unlock() }
    return try body(&storage.value)
    }

    public borrowing func withLockIfAvailable<Result, E>(
    _ body: (inout sending Value) throws(E) -> sending Result
    ) throws(E) -> sending Result? where E: Error {
    do {
    return try lock.withLockIfAvailableUnchecked { value in
    nonisolated(unsafe) var copy = value
    defer { value = copy }
    return try Transferring(body(&copy))
    }?.value
    } catch let error as E {
    throw error
    } catch {
    preconditionFailure("cannot occur")
    }
    guard lock.lockIfAvailable() else { return nil }
    defer { lock.unlock() }
    return try body(&storage.value)
    }
    }

    private struct Transferring<T> {
    nonisolated(unsafe) var value: T
    init(_ value: T) {
    self.value = value
    final class Storage {
    var value: Value

    init(_ initialValue: consuming Value) {
    self.value = initialValue
    }
    }
    }
  5. swhitty revised this gist Jun 3, 2025. 1 changed file with 5 additions and 34 deletions.
    39 changes: 5 additions & 34 deletions Mutex.swift
    Original file line number Diff line number Diff line change
    @@ -1,13 +1,13 @@
    // Backports the Swift 6 type Mutex<Value> to Swift 5 and all Darwin platforms via OSAllocatedUnfairLock.
    // Backports the Swift 6 type Mutex<Value> to all Darwin platforms via OSAllocatedUnfairLock.
    // Lightweight version of https://github.com/swhitty/swift-mutex
    // Feel free to use any part of this gist.
    // Note: ~Copyable are not supported
    // Note: Value: ~Copyable are not supported

    #if compiler(>=6)
    import struct os.OSAllocatedUnfairLock

    @available(iOS, introduced: 16.0, deprecated: 18.0, message: "use Mutex from Synchronization module included with Swift 6")
    @available(macOS, introduced: 13.0, deprecated: 15.0, message: "use Mutex from Synchronization module included with Swift 6")
    public struct Mutex<Value>: @unchecked Sendable {
    public struct Mutex<Value>: @unchecked Sendable, ~Copyable {
    let lock: OSAllocatedUnfairLock<Value>

    public init(_ initialValue: consuming sending Value) {
    @@ -52,33 +52,4 @@ private struct Transferring<T> {
    init(_ value: T) {
    self.value = value
    }
    }

    #else

    @available(macOS 13.0, iOS 16.0, *)
    public struct Mutex<Value>: @unchecked Sendable {
    let lock: OSAllocatedUnfairLock<Value>

    public init(_ initialValue: consuming Value) {
    self.lock = OSAllocatedUnfairLock(uncheckedState: initialValue)
    }

    public borrowing func withLock<Result>(
    _ body: (inout Value) throws -> Result
    ) rethrows -> Result {
    try lock.withLockUnchecked {
    return try body(&$0)
    }
    }

    public borrowing func withLockIfAvailable<Result>(
    _ body: (inout Value) throws -> Result
    ) rethrows -> Result? {
    try lock.withLockIfAvailableUnchecked {
    return try body(&$0)
    }
    }
    }

    #endif
    }
  6. swhitty revised this gist Sep 7, 2024. 1 changed file with 2 additions and 1 deletion.
    3 changes: 2 additions & 1 deletion Mutex.swift
    Original file line number Diff line number Diff line change
    @@ -1,6 +1,7 @@
    // Backports the Swift 6 type Mutex<Value> to Swift 5 and all Darwin platforms via OSAllocatedUnfairLock
    // Backports the Swift 6 type Mutex<Value> to Swift 5 and all Darwin platforms via OSAllocatedUnfairLock.
    // Lightweight version of https://github.com/swhitty/swift-mutex
    // Feel free to use any part of this gist.
    // Note: ~Copyable are not supported

    #if compiler(>=6)

  7. swhitty revised this gist Sep 7, 2024. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion Mutex.swift
    Original file line number Diff line number Diff line change
    @@ -5,7 +5,7 @@
    #if compiler(>=6)

    @available(iOS, introduced: 16.0, deprecated: 18.0, message: "use Mutex from Synchronization module included with Swift 6")
    @available(macOS,introduced: 13.0, deprecated: 15.0, message: "use Mutex from Synchronization module included with Swift 6")
    @available(macOS, introduced: 13.0, deprecated: 15.0, message: "use Mutex from Synchronization module included with Swift 6")
    public struct Mutex<Value>: @unchecked Sendable {
    let lock: OSAllocatedUnfairLock<Value>

  8. swhitty revised this gist Sep 7, 2024. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion Mutex.swift
    Original file line number Diff line number Diff line change
    @@ -1,4 +1,4 @@
    // Backports the Swift 6 type Mutex<Value> to Swift 5 and all Darwin platforms with OSAllocatedUnfairLock
    // Backports the Swift 6 type Mutex<Value> to Swift 5 and all Darwin platforms via OSAllocatedUnfairLock
    // Lightweight version of https://github.com/swhitty/swift-mutex
    // Feel free to use any part of this gist.

  9. swhitty revised this gist Sep 7, 2024. 1 changed file with 6 additions and 3 deletions.
    9 changes: 6 additions & 3 deletions Mutex.swift
    Original file line number Diff line number Diff line change
    @@ -3,6 +3,7 @@
    // Feel free to use any part of this gist.

    #if compiler(>=6)

    @available(iOS, introduced: 16.0, deprecated: 18.0, message: "use Mutex from Synchronization module included with Swift 6")
    @available(macOS,introduced: 13.0, deprecated: 15.0, message: "use Mutex from Synchronization module included with Swift 6")
    public struct Mutex<Value>: @unchecked Sendable {
    @@ -51,14 +52,15 @@ private struct Transferring<T> {
    self.value = value
    }
    }

    #else
    @available(iOS, introduced: 16.0, deprecated: 18.0, message: "use Mutex from Synchronization module included with Swift 6")
    @available(macOS,introduced: 13.0, deprecated: 15.0, message: "use Mutex from Synchronization module included with Swift 6")

    @available(macOS 13.0, iOS 16.0, *)
    public struct Mutex<Value>: @unchecked Sendable {
    let lock: OSAllocatedUnfairLock<Value>

    public init(_ initialValue: consuming Value) {
    self.lock = AllocatedLock(uncheckedState: initialValue)
    self.lock = OSAllocatedUnfairLock(uncheckedState: initialValue)
    }

    public borrowing func withLock<Result>(
    @@ -77,4 +79,5 @@ public struct Mutex<Value>: @unchecked Sendable {
    }
    }
    }

    #endif
  10. swhitty created this gist Sep 7, 2024.
    80 changes: 80 additions & 0 deletions Mutex.swift
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,80 @@
    // Backports the Swift 6 type Mutex<Value> to Swift 5 and all Darwin platforms with OSAllocatedUnfairLock
    // Lightweight version of https://github.com/swhitty/swift-mutex
    // Feel free to use any part of this gist.

    #if compiler(>=6)
    @available(iOS, introduced: 16.0, deprecated: 18.0, message: "use Mutex from Synchronization module included with Swift 6")
    @available(macOS,introduced: 13.0, deprecated: 15.0, message: "use Mutex from Synchronization module included with Swift 6")
    public struct Mutex<Value>: @unchecked Sendable {
    let lock: OSAllocatedUnfairLock<Value>

    public init(_ initialValue: consuming sending Value) {
    self.lock = OSAllocatedUnfairLock(uncheckedState: initialValue)
    }

    public borrowing func withLock<Result, E: Error>(
    _ body: (inout sending Value) throws(E) -> sending Result
    ) throws(E) -> sending Result {
    do {
    return try lock.withLockUnchecked { value in
    nonisolated(unsafe) var copy = value
    defer { value = copy }
    return try Transferring(body(&copy))
    }.value
    } catch let error as E {
    throw error
    } catch {
    preconditionFailure("cannot occur")
    }
    }

    public borrowing func withLockIfAvailable<Result, E>(
    _ body: (inout sending Value) throws(E) -> sending Result
    ) throws(E) -> sending Result? where E: Error {
    do {
    return try lock.withLockIfAvailableUnchecked { value in
    nonisolated(unsafe) var copy = value
    defer { value = copy }
    return try Transferring(body(&copy))
    }?.value
    } catch let error as E {
    throw error
    } catch {
    preconditionFailure("cannot occur")
    }
    }
    }

    private struct Transferring<T> {
    nonisolated(unsafe) var value: T
    init(_ value: T) {
    self.value = value
    }
    }
    #else
    @available(iOS, introduced: 16.0, deprecated: 18.0, message: "use Mutex from Synchronization module included with Swift 6")
    @available(macOS,introduced: 13.0, deprecated: 15.0, message: "use Mutex from Synchronization module included with Swift 6")
    public struct Mutex<Value>: @unchecked Sendable {
    let lock: OSAllocatedUnfairLock<Value>

    public init(_ initialValue: consuming Value) {
    self.lock = AllocatedLock(uncheckedState: initialValue)
    }

    public borrowing func withLock<Result>(
    _ body: (inout Value) throws -> Result
    ) rethrows -> Result {
    try lock.withLockUnchecked {
    return try body(&$0)
    }
    }

    public borrowing func withLockIfAvailable<Result>(
    _ body: (inout Value) throws -> Result
    ) rethrows -> Result? {
    try lock.withLockIfAvailableUnchecked {
    return try body(&$0)
    }
    }
    }
    #endif