Skip to content

Commit 120f8b3

Browse files
committed
wip: drop overloads, fix docs
1 parent 300188a commit 120f8b3

File tree

2 files changed

+36
-71
lines changed

2 files changed

+36
-71
lines changed

Sources/System/FileLock.swift

Lines changed: 34 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ extension FileDescriptor.FileLock {
6363
set { rawValue.l_len = CInterop.Offset(newValue) }
6464
}
6565

66-
/// The process ID of the lock holder, filled in by`FileDescriptor.getLock()`.
66+
/// The process ID of the lock holder (if applicable).
6767
///
6868
/// The corresponding C field is `l_pid`
6969
@_alwaysEmitIntoClient
@@ -90,8 +90,8 @@ extension FileDescriptor.FileLock {
9090
}
9191

9292
extension FileDescriptor.FileLock {
93-
/// The kind of a lock: read ("shared"), write ("exclusive"), or none
94-
/// ("unlock").
93+
/// The kind or type of a lock: read (aka "shared"), write (aka "exclusive"), or none
94+
/// (aka "unlock").
9595
@frozen
9696
public struct Kind: RawRepresentable, Hashable {
9797
@_alwaysEmitIntoClient
@@ -128,13 +128,10 @@ extension FileDescriptor.FileLock {
128128

129129
extension FileDescriptor {
130130
/// All bytes in a file
131-
///
132-
/// NOTE: We can't make byteRange optional _and_ generic in our API below because that requires type inference even when passed `nil`.
133-
///
134131
@_alwaysEmitIntoClient
135132
internal var _allFileBytes: Range<Int64> { Int64.min ..< Int64.max }
136133

137-
/// Get any conflicting locks held by other open file descriptions.
134+
/// Get any conflicting locks held by other open file descriptions.
138135
///
139136
/// Open file description locks are associated with an open file
140137
/// description (see `FileDescriptor.open`). Duplicated
@@ -151,24 +148,17 @@ extension FileDescriptor {
151148
///
152149
/// - Parameters:
153150
/// - byteRange: The range of bytes over which to check for a lock. Pass
154-
/// `nil` to consider the entire file (TODO: default value with Swift
155-
/// 5.7)
156-
/// - retryOnInterrupt: Whether to retry the open operation if it throws
151+
/// `nil` to consider the entire file.
152+
/// - retryOnInterrupt: Whether to retry the operation if it throws
157153
/// ``Errno/interrupted``. The default is `true`. Pass `false` to try
158154
/// only once and throw an error upon interruption.
159-
/// - Returns; `.none` if there are no other locks, otherwise returns the
155+
/// - Returns; `.none` if there are no locks, otherwise returns the
160156
/// strongest conflicting lock
161157
///
162158
/// The corresponding C function is `fcntl` with `F_OFD_GETLK`.
163-
///
164-
/// FIXME: Does this only return OFD locks or process locks too?
165-
/// TODO: document byte-range
166-
/// FIXME: Can we just state the OFD docs once and link to it?
167-
/// TODO: would a better API be e.g. `canGetLock(.read)`? or `getConflictingLock()`?
168-
///
169159
@_alwaysEmitIntoClient
170160
public func getConflictingLock(
171-
byteRange: some RangeExpression<Int64>,
161+
byteRange: (some RangeExpression<Int64>)? = Range?.none,
172162
retryOnInterrupt: Bool = true
173163
) throws -> FileDescriptor.FileLock.Kind {
174164
let (start, len) = _mapByteRangeToByteOffsets(byteRange)
@@ -177,15 +167,6 @@ extension FileDescriptor {
177167
).get()
178168
}
179169

180-
181-
@_alwaysEmitIntoClient
182-
public func getConflictingLock(
183-
retryOnInterrupt: Bool = true
184-
) throws -> FileDescriptor.FileLock.Kind {
185-
try getConflictingLock(
186-
byteRange: _allFileBytes, retryOnInterrupt: retryOnInterrupt)
187-
}
188-
189170
@usableFromInline
190171
internal func _getConflictingLock(
191172
start: Int64, length: Int64, retryOnInterrupt: Bool
@@ -202,14 +183,12 @@ extension FileDescriptor {
202183
// 2) Try with a write lock, which will tell us if there's either a
203184
// conflicting read or write lock in place.
204185
var lock = FileDescriptor.FileLock(ofdType: .read, start: start, length: length)
205-
// print(lock.type)
206186
if case let .failure(err) = self._fcntl(
207187
.getOFDLock, &lock, retryOnInterrupt: retryOnInterrupt
208188
) {
209189
return .failure(err)
210190
}
211191
if lock.type == .write {
212-
// print(lock.type)
213192
return .success(.write)
214193
}
215194
guard lock.type == .none else {
@@ -219,7 +198,6 @@ extension FileDescriptor {
219198
lock = FileDescriptor.FileLock(ofdType: .write, start: start, length: length)
220199

221200
let secondTry = self._fcntl(.getOFDLock, &lock, retryOnInterrupt: retryOnInterrupt)
222-
// print(lock.type)
223201
return secondTry.map { lock.type }
224202
}
225203

@@ -229,7 +207,7 @@ extension FileDescriptor {
229207
/// replaced.
230208
///
231209
/// If the lock cannot be set because it is blocked by an existing lock on a
232-
/// file and (TODO: blocking paremeter is false),
210+
/// file and `wait` is `false`,
233211
/// `Errno.resourceTemporarilyUnavailable` is thrown.
234212
///
235213
/// Open file description locks are associated with an open file
@@ -248,41 +226,34 @@ extension FileDescriptor {
248226
/// Passing a lock kind of `.none` will remove a lock (equivalent to calling
249227
/// `FileDescriptor.unlock()`).
250228
///
251-
/// TODO: describe non-blocking
229+
/// - Parameters:
230+
/// - kind: The kind of lock to set
231+
/// - byteRange: The range of bytes over which to lock. Pass
232+
/// `nil` to consider the entire file.
233+
/// - wait: Whether to wait (block) until the request can be completed
234+
/// - retryOnInterrupt: Whether to retry the operation if it throws
235+
/// ``Errno/interrupted``. The default is `true`. Pass `false` to try
236+
/// only once and throw an error upon interruption.
252237
///
253238
/// The corresponding C function is `fcntl` with `F_OFD_SETLK` or
254239
/// `F_OFD_SETLKW`.
255240
@_alwaysEmitIntoClient
256241
public func lock(
257242
_ kind: FileDescriptor.FileLock.Kind = .read,
258-
byteRange: (some RangeExpression<Int64>)? = nil,
259-
nonBlocking: Bool = false, // FIXME: named "wait" or "blocking"? Which default is best?
243+
byteRange: (some RangeExpression<Int64>)? = Range?.none,
244+
wait: Bool = false,
260245
retryOnInterrupt: Bool = true
261246
) throws {
262247
let (start, len) = _mapByteRangeToByteOffsets(byteRange)
263248
try _lock(
264249
kind,
265250
start: start,
266251
length: len,
267-
nonBlocking: nonBlocking,
252+
wait: wait,
268253
retryOnInterrupt: retryOnInterrupt
269254
).get()
270255
}
271256

272-
@_alwaysEmitIntoClient
273-
public func lock(
274-
_ kind: FileDescriptor.FileLock.Kind = .read,
275-
nonBlocking: Bool = false, // FIXME: named "wait" or "blocking"? Which default is best?
276-
retryOnInterrupt: Bool = true
277-
) throws {
278-
try lock(
279-
kind,
280-
byteRange: _allFileBytes,
281-
nonBlocking: nonBlocking,
282-
retryOnInterrupt: retryOnInterrupt)
283-
}
284-
285-
286257
/// Remove an open file description lock.
287258
///
288259
/// Open file description locks are associated with an open file
@@ -301,49 +272,43 @@ extension FileDescriptor {
301272
/// Calling `unlock()` is equivalent to passing `.none` as the lock kind to
302273
/// `FileDescriptor.lock()`.
303274
///
304-
/// TODO: Do we need a non-blocking argument? Does that even make sense?
275+
/// - Parameters:
276+
/// - byteRange: The range of bytes over which to lock. Pass
277+
/// `nil` to consider the entire file.
278+
/// - wait: Whether to wait (block) until the request can be completed
279+
/// - retryOnInterrupt: Whether to retry the operation if it throws
280+
/// ``Errno/interrupted``. The default is `true`. Pass `false` to try
281+
/// only once and throw an error upon interruption.
305282
///
306-
/// The corresponding C function is `fcntl` with `F_OFD_SETLK` (TODO: or
307-
/// `F_OFD_SETLKW`?) and a lock type of `F_UNLCK`.
283+
/// The corresponding C function is `fcntl` with `F_OFD_SETLK` or
284+
/// `F_OFD_SETLKW` and a lock type of `F_UNLCK`.
308285
@_alwaysEmitIntoClient
309286
public func unlock(
310-
byteRange: (some RangeExpression<Int64>)? = nil,
311-
nonBlocking: Bool = false, // FIXME: needed?
287+
byteRange: (some RangeExpression<Int64>)? = Range?.none,
288+
wait: Bool = false, // FIXME: needed?
312289
retryOnInterrupt: Bool = true
313290
) throws {
314291
let (start, len) = _mapByteRangeToByteOffsets(byteRange)
315292
try _lock(
316293
.none,
317294
start: start,
318295
length: len,
319-
nonBlocking: nonBlocking,
296+
wait: wait,
320297
retryOnInterrupt: retryOnInterrupt
321298
).get()
322299
}
323300

324-
@_alwaysEmitIntoClient
325-
public func unlock(
326-
nonBlocking: Bool = false, // FIXME: needed?
327-
retryOnInterrupt: Bool = true
328-
) throws {
329-
try unlock(
330-
byteRange: _allFileBytes,
331-
nonBlocking: nonBlocking,
332-
retryOnInterrupt: retryOnInterrupt)
333-
}
334-
335-
336301
@usableFromInline
337302
internal func _lock(
338303
_ kind: FileDescriptor.FileLock.Kind,
339304
start: Int64,
340305
length: Int64,
341-
nonBlocking: Bool,
306+
wait: Bool,
342307
retryOnInterrupt: Bool
343308
) -> Result<(), Errno> {
344309
var lock = FileDescriptor.FileLock(ofdType: kind, start: start, length: length)
345310
let command: FileDescriptor.Control.Command =
346-
nonBlocking ? .setOFDLock : .setOFDLockWait
311+
wait ? .setOFDLockWait : .setOFDLock
347312
return _fcntl(command, &lock, retryOnInterrupt: retryOnInterrupt)
348313
}
349314
}

Tests/SystemTests/FileLockTest.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,12 +70,12 @@ extension FileOperationsTest {
7070
testOFDs(one: .read, two: .read)
7171

7272
do {
73-
try dup_2.lock(.write, nonBlocking: true)
73+
try dup_2.lock(.write)
7474
} catch let e as Errno {
7575
XCTAssertEqual(.resourceTemporarilyUnavailable, e)
7676
}
7777
do {
78-
try ofd_1.lock(.write, nonBlocking: true)
78+
try ofd_1.lock(.write)
7979
} catch let e as Errno {
8080
XCTAssertEqual(.resourceTemporarilyUnavailable, e)
8181
}

0 commit comments

Comments
 (0)