DispatchQueue+Extensions.swift 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. import Foundation
  2. extension DispatchQueue {
  3. // static let reloadQueue = DispatchQueue.markedQueue(label: "reloadQueue", qos: .ui)
  4. }
  5. extension DispatchQueue {
  6. static var isMain: Bool {
  7. Thread.isMainThread && OperationQueue.main === OperationQueue.current
  8. }
  9. static func safeMainSync<T>(_ block: () throws -> T) rethrows -> T {
  10. if isMain {
  11. return try block()
  12. } else {
  13. return try DispatchQueue.main.sync {
  14. try autoreleasepool(invoking: block)
  15. }
  16. }
  17. }
  18. static func safeMainAsync(_ block: @escaping () -> Void) {
  19. RunLoop.main.perform(inModes: [.default], block: block)
  20. }
  21. }
  22. extension DispatchQueue {
  23. private enum QueueSpecific {
  24. static let key = DispatchSpecificKey<String>()
  25. static let value = AssociationKey<String?>("DispatchQueue.Specific.value")
  26. }
  27. private(set) var specificValue: String? {
  28. get { associations.value(forKey: QueueSpecific.value) }
  29. set { associations.setValue(newValue, forKey: QueueSpecific.value) }
  30. }
  31. static func markedQueue(
  32. label: String = "MarkedQueue",
  33. qos: DispatchQoS = .default,
  34. attributes: DispatchQueue.Attributes = [],
  35. target: DispatchQueue? = nil
  36. ) -> DispatchQueue {
  37. let queueLabel = "\(label).\(UUID())"
  38. let queue = DispatchQueue(
  39. label: queueLabel,
  40. qos: qos,
  41. attributes: attributes,
  42. autoreleaseFrequency: .workItem,
  43. target: target
  44. )
  45. let specificValue = target?.label ?? queueLabel
  46. queue.specificValue = specificValue
  47. queue.setSpecific(key: QueueSpecific.key, value: specificValue)
  48. return queue
  49. }
  50. static var currentLabel: String? { DispatchQueue.getSpecific(key: QueueSpecific.key) }
  51. var isCurrentQueue: Bool {
  52. if let staticSpecific = DispatchQueue.currentLabel,
  53. let instanceSpecific = specificValue,
  54. staticSpecific == instanceSpecific
  55. {
  56. return true
  57. }
  58. return false
  59. }
  60. func safeSync<T>(execute block: () throws -> T) rethrows -> T {
  61. try autoreleasepool {
  62. if self === DispatchQueue.main {
  63. return try DispatchQueue.safeMainSync(block)
  64. } else if isCurrentQueue {
  65. return try block()
  66. } else {
  67. return try sync {
  68. try autoreleasepool(invoking: block)
  69. }
  70. }
  71. }
  72. }
  73. }