Skip to content

Commit 24d3e7b

Browse files
committed
update _Subprocess lib with complete linux support
1 parent 87ae73b commit 24d3e7b

13 files changed

+2224
-2075
lines changed
Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2022 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
#if canImport(os)
14+
internal import os
15+
#if FOUNDATION_FRAMEWORK && canImport(C.os.lock)
16+
internal import C.os.lock
17+
#endif
18+
#elseif canImport(Bionic)
19+
import Bionic
20+
#elseif canImport(Glibc)
21+
import Glibc
22+
#elseif canImport(Musl)
23+
import Musl
24+
#elseif canImport(WinSDK)
25+
import WinSDK
26+
#endif
27+
28+
package struct LockedState<State> {
29+
30+
// Internal implementation for a cheap lock to aid sharing code across platforms
31+
private struct _Lock {
32+
#if canImport(os)
33+
typealias Primitive = os_unfair_lock
34+
#elseif canImport(Bionic) || canImport(Glibc) || canImport(Musl)
35+
typealias Primitive = pthread_mutex_t
36+
#elseif canImport(WinSDK)
37+
typealias Primitive = SRWLOCK
38+
#elseif os(WASI)
39+
// WASI is single-threaded, so we don't need a lock.
40+
typealias Primitive = Void
41+
#endif
42+
43+
typealias PlatformLock = UnsafeMutablePointer<Primitive>
44+
var _platformLock: PlatformLock
45+
46+
fileprivate static func initialize(_ platformLock: PlatformLock) {
47+
#if canImport(os)
48+
platformLock.initialize(to: os_unfair_lock())
49+
#elseif canImport(Bionic) || canImport(Glibc)
50+
pthread_mutex_init(platformLock, nil)
51+
#elseif canImport(WinSDK)
52+
InitializeSRWLock(platformLock)
53+
#elseif os(WASI)
54+
// no-op
55+
#endif
56+
}
57+
58+
fileprivate static func deinitialize(_ platformLock: PlatformLock) {
59+
#if canImport(Bionic) || canImport(Glibc)
60+
pthread_mutex_destroy(platformLock)
61+
#endif
62+
platformLock.deinitialize(count: 1)
63+
}
64+
65+
static fileprivate func lock(_ platformLock: PlatformLock) {
66+
#if canImport(os)
67+
os_unfair_lock_lock(platformLock)
68+
#elseif canImport(Bionic) || canImport(Glibc)
69+
pthread_mutex_lock(platformLock)
70+
#elseif canImport(WinSDK)
71+
AcquireSRWLockExclusive(platformLock)
72+
#elseif os(WASI)
73+
// no-op
74+
#endif
75+
}
76+
77+
static fileprivate func unlock(_ platformLock: PlatformLock) {
78+
#if canImport(os)
79+
os_unfair_lock_unlock(platformLock)
80+
#elseif canImport(Bionic) || canImport(Glibc)
81+
pthread_mutex_unlock(platformLock)
82+
#elseif canImport(WinSDK)
83+
ReleaseSRWLockExclusive(platformLock)
84+
#elseif os(WASI)
85+
// no-op
86+
#endif
87+
}
88+
}
89+
90+
private class _Buffer: ManagedBuffer<State, _Lock.Primitive> {
91+
deinit {
92+
withUnsafeMutablePointerToElements {
93+
_Lock.deinitialize($0)
94+
}
95+
}
96+
}
97+
98+
private let _buffer: ManagedBuffer<State, _Lock.Primitive>
99+
100+
package init(initialState: State) {
101+
_buffer = _Buffer.create(minimumCapacity: 1, makingHeaderWith: { buf in
102+
buf.withUnsafeMutablePointerToElements {
103+
_Lock.initialize($0)
104+
}
105+
return initialState
106+
})
107+
}
108+
109+
package func withLock<T>(_ body: @Sendable (inout State) throws -> T) rethrows -> T {
110+
try withLockUnchecked(body)
111+
}
112+
113+
package func withLockUnchecked<T>(_ body: (inout State) throws -> T) rethrows -> T {
114+
try _buffer.withUnsafeMutablePointers { state, lock in
115+
_Lock.lock(lock)
116+
defer { _Lock.unlock(lock) }
117+
return try body(&state.pointee)
118+
}
119+
}
120+
121+
// Ensures the managed state outlives the locked scope.
122+
package func withLockExtendingLifetimeOfState<T>(_ body: @Sendable (inout State) throws -> T) rethrows -> T {
123+
try _buffer.withUnsafeMutablePointers { state, lock in
124+
_Lock.lock(lock)
125+
return try withExtendedLifetime(state.pointee) {
126+
defer { _Lock.unlock(lock) }
127+
return try body(&state.pointee)
128+
}
129+
}
130+
}
131+
}
132+
133+
extension LockedState where State == Void {
134+
package init() {
135+
self.init(initialState: ())
136+
}
137+
138+
package func withLock<R: Sendable>(_ body: @Sendable () throws -> R) rethrows -> R {
139+
return try withLock { _ in
140+
try body()
141+
}
142+
}
143+
144+
package func lock() {
145+
_buffer.withUnsafeMutablePointerToElements { lock in
146+
_Lock.lock(lock)
147+
}
148+
}
149+
150+
package func unlock() {
151+
_buffer.withUnsafeMutablePointerToElements { lock in
152+
_Lock.unlock(lock)
153+
}
154+
}
155+
}
156+
157+
extension LockedState: @unchecked Sendable where State: Sendable {}
158+

0 commit comments

Comments
 (0)