@@ -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,32 @@ 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 (
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
56
86
// Open the lock file.
57
87
if fd == nil {
58
88
let fd = SPMLibc . open ( lockFile. pathString, O_WRONLY | O_CREAT | O_CLOEXEC, 0o666 )
@@ -70,17 +100,31 @@ public final class FileLock {
70
100
if errno == EINTR { continue }
71
101
throw ProcessLockError . unableToAquireLock ( errno: errno)
72
102
}
103
+ #endif
73
104
}
74
105
75
106
/// Unlock the held lock.
76
107
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
77
115
guard let fd = fd else { return }
78
116
flock ( fd, LOCK_UN)
117
+ #endif
79
118
}
80
119
81
120
deinit {
121
+ #if os(Windows)
122
+ guard let h = h else { return }
123
+ CloseHandle ( h)
124
+ #else
82
125
guard let fd = fd else { return }
83
126
close ( fd)
127
+ #endif
84
128
}
85
129
86
130
/// Execute the given block while holding the lock.
0 commit comments