看一下与fetchLoad cancelSemaphore相关的逻辑代码:
repeat {
leftSignal = fetchLoad.cancelSemaphore?.signal() ?? 0
} while leftSignal != 0
使用乐观锁,也就是忙等技术,不断发送signal, 直到另一个线程收到信号, 将Semaphore置空
if let fetchLoad = fetchLoad(for: url), fetchLoad.downloadTaskCount == 0 {
if fetchLoad.cancelSemaphore == nil {
fetchLoad.cancelSemaphore = DispatchSemaphore(value: 0)
}
// 这个中间有个空闲段,在cancelQueue没有执行closure之前,发signal信号是无效的,收不到,所以上面的代码不是发一次signal信号,而是不停的发,保证接收方收到signal信号
cancelQueue.async {
_ = fetchLoad.cancelSemaphore?.wait(timeout: .distantFuture)
//这个置空的操作很重要,如果不置空,上面的signal代码会陷入死循环
fetchLoad.cancelSemaphore = nil
prepareFetchLoad()
}
}
cleanFetchLoad(for: url)
var leftSignal: Int
repeat {
leftSignal = fetchLoad.cancelSemaphore?.signal() ?? 0
} while leftSignal != 0
for content in fetchLoad.contents {
content.options.callbackDispatchQueue.safeAsync {
content.callback.completionHandler?(nil, error as NSError, url, nil)
}
}