48 lines
1.3 KiB
Swift
48 lines
1.3 KiB
Swift
//
|
|
// DispatchQueue+Once.swift
|
|
// VDS
|
|
//
|
|
// Created by Matt Bruce on 7/27/22.
|
|
//
|
|
|
|
import Foundation
|
|
|
|
extension DispatchQueue {
|
|
private static var _onceTracker = Set<String>()
|
|
|
|
public class func once(
|
|
file: String = #file,
|
|
function: String = #function,
|
|
line: Int = #line,
|
|
block: () -> Void
|
|
) {
|
|
let token = "\(file):\(function):\(line)"
|
|
once(token: token, block: block)
|
|
}
|
|
|
|
/**
|
|
Executes a block of code, associated with a unique token, only once. The code is thread safe and will
|
|
only execute the code once even in the presence of multithreaded calls.
|
|
|
|
- parameter token: A unique reverse DNS style name such as com.vectorform.<name> or a GUID
|
|
- parameter block: Block to execute once
|
|
*/
|
|
public class func once(
|
|
token: String,
|
|
block: () -> Void
|
|
) {
|
|
// Peek ahead to avoid the intersection.
|
|
guard !_onceTracker.contains(token) else { return }
|
|
|
|
objc_sync_enter(self)
|
|
defer { objc_sync_exit(self) }
|
|
|
|
// Double check we are the first in the critical section.
|
|
guard !_onceTracker.contains(token) else { return }
|
|
|
|
// Execute.
|
|
_onceTracker.insert(token)
|
|
block()
|
|
}
|
|
}
|