@@ -36,7 +36,11 @@ enum ProcessLockError: Swift.Error {
36
36
/// by mutiple instances of a process. The `FileLock` is not thread-safe.
37
37
public final class FileLock {
38
38
/// File descriptor to the lock file.
39
+ #if os(Windows)
40
+ private var h : HANDLE ?
41
+ #else
39
42
private var fd : CInt ?
43
+ #endif
40
44
41
45
/// Path to the lock file.
42
46
private let lockFile : AbsolutePath
@@ -53,6 +57,30 @@ public final class FileLock {
53
57
///
54
58
/// Note: This method can throw if underlying POSIX methods fail.
55
59
public func lock( ) throws {
60
+ #if os(Windows)
61
+ if h == nil {
62
+ let h = lockFile. pathString. withCString ( encodedAs: UTF16 . self, {
63
+ CreateFileW ( $0,
64
+ UInt32 ( GENERIC_READ) | UInt32 ( GENERIC_WRITE) ,
65
+ 0 ,
66
+ nil ,
67
+ DWORD ( OPEN_ALWAYS) ,
68
+ DWORD ( FILE_ATTRIBUTE_NORMAL) ,
69
+ nil )
70
+ } )
71
+ if h == INVALID_HANDLE_VALUE {
72
+ throw FileSystemError ( errno: Int32 ( GetLastError ( ) ) )
73
+ }
74
+ self . h = h
75
+ }
76
+ var overlapped = OVERLAPPED ( )
77
+ overlapped. Offset = 0
78
+ overlapped. OffsetHigh = 0
79
+ overlapped. hEvent = nil
80
+ if FALSE == LockFileEx ( h, DWORD ( LOCKFILE_EXCLUSIVE_LOCK) , 0 , DWORD ( INT_MAX) , DWORD ( INT_MAX) , & overlapped) {
81
+ throw ProcessLockError . unableToAquireLock ( errno: Int32 ( GetLastError ( ) ) )
82
+ }
83
+ #else
56
84
// Open the lock file.
57
85
if fd == nil {
58
86
let fd = SPMLibc . open ( lockFile. pathString, O_WRONLY | O_CREAT | O_CLOEXEC, 0o666 )
@@ -70,17 +98,31 @@ public final class FileLock {
70
98
if errno == EINTR { continue }
71
99
throw ProcessLockError . unableToAquireLock ( errno: errno)
72
100
}
101
+ #endif
73
102
}
74
103
75
104
/// Unlock the held lock.
76
105
public func unlock( ) {
106
+ #if os(Windows)
107
+ var overlapped = OVERLAPPED ( )
108
+ overlapped. Offset = 0
109
+ overlapped. OffsetHigh = 0
110
+ overlapped. hEvent = nil
111
+ UnlockFileEx ( h, 0 , DWORD ( INT_MAX) , DWORD ( INT_MAX) , & overlapped)
112
+ #else
77
113
guard let fd = fd else { return }
78
114
flock ( fd, LOCK_UN)
115
+ #endif
79
116
}
80
117
81
118
deinit {
119
+ #if os(Windows)
120
+ guard let h = h else { return }
121
+ CloseHandle ( h)
122
+ #else
82
123
guard let fd = fd else { return }
83
124
close ( fd)
125
+ #endif
84
126
}
85
127
86
128
/// Execute the given block while holding the lock.
0 commit comments