Skip to content

Commit ee3e424

Browse files
authored
Discard changes to Sources/JavaKitVM/LockedState.swift
1 parent aa988b1 commit ee3e424

File tree

1 file changed

+160
-0
lines changed

1 file changed

+160
-0
lines changed

Sources/JavaKitVM/LockedState.swift

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

0 commit comments

Comments
 (0)