Skip to content

Commit 6ec1acc

Browse files
committed
use Mutex
1 parent a40e28b commit 6ec1acc

File tree

3 files changed

+104
-140
lines changed

3 files changed

+104
-140
lines changed

.github/workflows/build.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -124,15 +124,15 @@ jobs:
124124
- name: Build
125125
run: swift build --swift-sdk aarch64-unknown-linux-android24
126126

127-
windows_swift_6_2:
127+
windows_swift_6_1:
128128
runs-on: windows-latest
129129
steps:
130130
- name: Checkout
131131
uses: actions/checkout@v4
132132
- name: Install Swift
133133
uses: SwiftyLab/setup-swift@latest
134134
with:
135-
swift-version: "6.2.0"
135+
swift-version: "6.1.2"
136136
visual-studio-components: Microsoft.VisualStudio.Component.Windows11SDK.22621
137137
- name: Version
138138
run: swift --version

Sources/Mutex+Darwin.swift

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
//
2+
// Mutex.swift
3+
// swift-mutex
4+
//
5+
// Created by Simon Whitty on 07/09/2024.
6+
// Copyright 2024 Simon Whitty
7+
//
8+
// Distributed under the permissive MIT license
9+
// Get the latest version from here:
10+
//
11+
// https://github.com/swhitty/swift-mutex
12+
//
13+
// Permission is hereby granted, free of charge, to any person obtaining a copy
14+
// of this software and associated documentation files (the "Software"), to deal
15+
// in the Software without restriction, including without limitation the rights
16+
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
17+
// copies of the Software, and to permit persons to whom the Software is
18+
// furnished to do so, subject to the following conditions:
19+
//
20+
// The above copyright notice and this permission notice shall be included in all
21+
// copies or substantial portions of the Software.
22+
//
23+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24+
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25+
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
26+
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27+
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
28+
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
29+
// SOFTWARE.
30+
//
31+
32+
#if canImport(Darwin)
33+
34+
import struct os.os_unfair_lock_t
35+
import struct os.os_unfair_lock
36+
import func os.os_unfair_lock_lock
37+
import func os.os_unfair_lock_unlock
38+
import func os.os_unfair_lock_trylock
39+
40+
// Backports the Swift 6 type Mutex<Value> to all Darwin platforms
41+
@usableFromInline
42+
struct Mutex<Value: ~Copyable>: ~Copyable {
43+
let storage: Storage<Value>
44+
45+
@usableFromInline
46+
init(_ initialValue: consuming sending Value) {
47+
self.storage = Storage(initialValue)
48+
}
49+
50+
@usableFromInline
51+
borrowing func withLock<Result, E: Error>(
52+
_ body: (inout sending Value) throws(E) -> sending Result
53+
) throws(E) -> sending Result {
54+
storage.lock()
55+
defer { storage.unlock() }
56+
return try body(&storage.value)
57+
}
58+
59+
@usableFromInline
60+
borrowing func withLockIfAvailable<Result, E: Error>(
61+
_ body: (inout sending Value) throws(E) -> sending Result
62+
) throws(E) -> sending Result? {
63+
guard storage.tryLock() else { return nil }
64+
defer { storage.unlock() }
65+
return try body(&storage.value)
66+
}
67+
}
68+
69+
extension Mutex: @unchecked Sendable where Value: ~Copyable { }
70+
71+
final class Storage<Value: ~Copyable> {
72+
private let _lock: os_unfair_lock_t
73+
var value: Value
74+
75+
init(_ initialValue: consuming Value) {
76+
self._lock = .allocate(capacity: 1)
77+
self._lock.initialize(to: os_unfair_lock())
78+
self.value = initialValue
79+
}
80+
81+
func lock() {
82+
os_unfair_lock_lock(_lock)
83+
}
84+
85+
func unlock() {
86+
os_unfair_lock_unlock(_lock)
87+
}
88+
89+
func tryLock() -> Bool {
90+
os_unfair_lock_trylock(_lock)
91+
}
92+
93+
deinit {
94+
self._lock.deinitialize(count: 1)
95+
self._lock.deallocate()
96+
}
97+
}
98+
99+
#endif

Sources/Mutex.swift

Lines changed: 3 additions & 138 deletions
Original file line numberDiff line numberDiff line change
@@ -29,145 +29,10 @@
2929
// SOFTWARE.
3030
//
3131

32-
// Backports the Swift 6 type Mutex<Value> to all Darwin platforms
33-
@usableFromInline
34-
struct Mutex<Value: ~Copyable>: ~Copyable {
35-
let storage: Storage<Value>
32+
#if !canImport(Darwin)
3633

37-
@usableFromInline
38-
init(_ initialValue: consuming sending Value) {
39-
self.storage = Storage(initialValue)
40-
}
34+
import Synchronization
4135

42-
@usableFromInline
43-
borrowing func withLock<Result, E: Error>(
44-
_ body: (inout sending Value) throws(E) -> sending Result
45-
) throws(E) -> sending Result {
46-
storage.lock()
47-
defer { storage.unlock() }
48-
return try body(&storage.value)
49-
}
50-
51-
@usableFromInline
52-
borrowing func withLockIfAvailable<Result, E: Error>(
53-
_ body: (inout sending Value) throws(E) -> sending Result
54-
) throws(E) -> sending Result? {
55-
guard storage.tryLock() else { return nil }
56-
defer { storage.unlock() }
57-
return try body(&storage.value)
58-
}
59-
}
60-
61-
extension Mutex: @unchecked Sendable where Value: ~Copyable { }
62-
63-
#if canImport(Darwin)
64-
65-
import struct os.os_unfair_lock_t
66-
import struct os.os_unfair_lock
67-
import func os.os_unfair_lock_lock
68-
import func os.os_unfair_lock_unlock
69-
import func os.os_unfair_lock_trylock
70-
71-
final class Storage<Value: ~Copyable> {
72-
private let _lock: os_unfair_lock_t
73-
var value: Value
74-
75-
init(_ initialValue: consuming Value) {
76-
self._lock = .allocate(capacity: 1)
77-
self._lock.initialize(to: os_unfair_lock())
78-
self.value = initialValue
79-
}
80-
81-
func lock() {
82-
os_unfair_lock_lock(_lock)
83-
}
84-
85-
func unlock() {
86-
os_unfair_lock_unlock(_lock)
87-
}
88-
89-
func tryLock() -> Bool {
90-
os_unfair_lock_trylock(_lock)
91-
}
92-
93-
deinit {
94-
self._lock.deinitialize(count: 1)
95-
self._lock.deallocate()
96-
}
97-
}
98-
99-
#elseif canImport(Glibc) || canImport(Musl) || canImport(Bionic)
100-
101-
#if canImport(Musl)
102-
import Musl
103-
#elseif canImport(Bionic)
104-
import Android
105-
#else
106-
import Glibc
107-
#endif
108-
109-
final class Storage<Value: ~Copyable> {
110-
private let _lock: UnsafeMutablePointer<pthread_mutex_t>
111-
112-
var value: Value
113-
114-
init(_ initialValue: consuming Value) {
115-
var attr = pthread_mutexattr_t()
116-
pthread_mutexattr_init(&attr)
117-
self._lock = .allocate(capacity: 1)
118-
let err = pthread_mutex_init(self._lock, &attr)
119-
precondition(err == 0, "pthread_mutex_init error: \(err)")
120-
self.value = initialValue
121-
}
122-
123-
func lock() {
124-
let err = pthread_mutex_lock(_lock)
125-
precondition(err == 0, "pthread_mutex_lock error: \(err)")
126-
}
127-
128-
func unlock() {
129-
let err = pthread_mutex_unlock(_lock)
130-
precondition(err == 0, "pthread_mutex_unlock error: \(err)")
131-
}
132-
133-
func tryLock() -> Bool {
134-
pthread_mutex_trylock(_lock) == 0
135-
}
136-
137-
deinit {
138-
let err = pthread_mutex_destroy(self._lock)
139-
precondition(err == 0, "pthread_mutex_destroy error: \(err)")
140-
self._lock.deallocate()
141-
}
142-
}
143-
144-
#elseif canImport(WinSDK)
145-
146-
import ucrt
147-
import WinSDK
148-
149-
final class Storage<Value> {
150-
private let _lock: UnsafeMutablePointer<SRWLOCK>
151-
152-
var value: Value
153-
154-
init(_ initialValue: Value) {
155-
self._lock = .allocate(capacity: 1)
156-
InitializeSRWLock(self._lock)
157-
self.value = initialValue
158-
}
159-
160-
func lock() {
161-
AcquireSRWLockExclusive(_lock)
162-
}
163-
164-
func unlock() {
165-
ReleaseSRWLockExclusive(_lock)
166-
}
167-
168-
func tryLock() -> Bool {
169-
TryAcquireSRWLockExclusive(_lock) != 0
170-
}
171-
}
36+
typealias Mutex = Synchronization.Mutex
17237

17338
#endif

0 commit comments

Comments
 (0)