Skip to content

Commit 9e692e4

Browse files
gmittertaciidgh
authored andcommitted
Implement Lock.swift on Windows
1 parent 1d199c3 commit 9e692e4

File tree

2 files changed

+47
-0
lines changed

2 files changed

+47
-0
lines changed

Sources/Basic/Lock.swift

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,11 @@ enum ProcessLockError: Swift.Error {
3636
/// by mutiple instances of a process. The `FileLock` is not thread-safe.
3737
public final class FileLock {
3838
/// File descriptor to the lock file.
39+
#if os(Windows)
40+
private var h: HANDLE?
41+
#else
3942
private var fd: CInt?
43+
#endif
4044

4145
/// Path to the lock file.
4246
private let lockFile: AbsolutePath
@@ -53,6 +57,32 @@ public final class FileLock {
5357
///
5458
/// Note: This method can throw if underlying POSIX methods fail.
5559
public func lock() throws {
60+
#if os(Windows)
61+
if h == nil {
62+
let h = lockFile.pathString.withCString(encodedAs: UTF16.self, {
63+
CreateFileW(
64+
$0,
65+
UInt32(GENERIC_READ) | UInt32(GENERIC_WRITE),
66+
0,
67+
nil,
68+
DWORD(OPEN_ALWAYS),
69+
DWORD(FILE_ATTRIBUTE_NORMAL),
70+
nil
71+
)
72+
})
73+
if h == INVALID_HANDLE_VALUE {
74+
throw FileSystemError(errno: Int32(GetLastError()))
75+
}
76+
self.h = h
77+
}
78+
var overlapped = OVERLAPPED()
79+
overlapped.Offset = 0
80+
overlapped.OffsetHigh = 0
81+
overlapped.hEvent = nil
82+
if FALSE == LockFileEx(h, DWORD(LOCKFILE_EXCLUSIVE_LOCK), 0, DWORD(INT_MAX), DWORD(INT_MAX), &overlapped) {
83+
throw ProcessLockError.unableToAquireLock(errno: Int32(GetLastError()))
84+
}
85+
#else
5686
// Open the lock file.
5787
if fd == nil {
5888
let fd = SPMLibc.open(lockFile.pathString, O_WRONLY | O_CREAT | O_CLOEXEC, 0o666)
@@ -70,17 +100,31 @@ public final class FileLock {
70100
if errno == EINTR { continue }
71101
throw ProcessLockError.unableToAquireLock(errno: errno)
72102
}
103+
#endif
73104
}
74105

75106
/// Unlock the held lock.
76107
public func unlock() {
108+
#if os(Windows)
109+
var overlapped = OVERLAPPED()
110+
overlapped.Offset = 0
111+
overlapped.OffsetHigh = 0
112+
overlapped.hEvent = nil
113+
UnlockFileEx(h, 0, DWORD(INT_MAX), DWORD(INT_MAX), &overlapped)
114+
#else
77115
guard let fd = fd else { return }
78116
flock(fd, LOCK_UN)
117+
#endif
79118
}
80119

81120
deinit {
121+
#if os(Windows)
122+
guard let h = h else { return }
123+
CloseHandle(h)
124+
#else
82125
guard let fd = fd else { return }
83126
close(fd)
127+
#endif
84128
}
85129

86130
/// Execute the given block while holding the lock.

Sources/SPMLibc/libc.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@
1010

1111
#if os(Linux)
1212
@_exported import Glibc
13+
#elseif os(Windows)
14+
@_exported import MSVCRT
15+
@_exported import WinSDK
1316
#else
1417
@_exported import Darwin.C
1518
#endif

0 commit comments

Comments
 (0)