The documentation for Mutex.withLockIfAvailable(_:) does not specify if it can spuriously fail to acquire the mutex. Normally, the lack of any discussion about spurious failures wouldn't be an issue since we don't document whether or not most other API can spuriously fail either.
What is a "spurious failure"?
Given the following algorithm:
if mutex.tryLock() {
doWork()
mutex.unlock()
}
mutex.tryLock() should return true if the lock was acquired, and false if another thread has currently acquired it. A spurious failure occurs if the function returns false despite no other thread having acquired it.
Why should we document our behavior?
Mutex.withLockIfAvailable(_:) is Swift's spelling of the tryLock() operation, and there is a schism between the C/C++ standards and POSIX as to whether tryLock() might fail spuriously.
C/C++ vs. POSIX
C11's mtx_trylock() and C++11's std::mutex::try_lock() are both allowed to spuriously fail. Per the C++11 standard §30.4.1.1/16:
An implementation may fail to obtain the lock even if it is not held by any other thread. [ Note: This spurious failure is normally uncommon, but allows interesting implementations based on a simple compare and exchange [...] ]
(The standard is referring to weak compare-and-exchange operations which can fail spuriously at the hardware level; strong compare-and-exchange operations cannot fail in this manner.)
But the POSIX standard for pthread_mutex_trylock() makes no such accommodation, instead stating simply:
The function
pthread_mutex_trylock()is identical topthread_mutex_lock()except that if the mutex object referenced bymutexis currently locked (by any thread, including the current thread), the call returns immediately.
Where does Swift stand?
Swift's current documentation is silent on the matter. As a developer who uses the Swift language and its standard library, if I were approaching this documentation in a vacuum, I wouldn't even consider the possibility of a spurious failure. As a rule we don't concern ourselves with "oh it might randomly fail" as something we need to guard against.
But a developer coming from another language will be bringing with knowledge of that language and its standard library. A developer coming to Swift from C or C++ might rightly ask if Mutex.withLockIfAvailable(_:) is safe to use.
I've reviewed the platform-specific implementations of _MutexHandle._tryLock() in the Swift repository and have confirmed that none of these implementations is subject to spurious failure.
Proposed solution
I propose that the documentation for Mutex.withLockIfAvailable(_:) should specifically and clearly indicate whether it can spuriously fail. That way, developers who use Mutex will know what to expect from it and will (hopefully) avoid being confused if they've also read the documentation for the C/C++'s equivalents.
For the full proposal, see here.