We have function like this in swift 2.2 for printing a log message with the current running thread:
func MyLog(_ message: String) {
if Thread.isMainThre
As Brent Royal-Gordon mentioned in his message on lists.swift.org it's a hole in the current design, but you can use this horrible workaround.
func currentQueueName() -> String? {
let name = __dispatch_queue_get_label(nil)
return String(cString: name, encoding: .utf8)
}
Now DispatchQueue has label property.
The label you assigned to the dispatch queue at creation time.
var label: String { get }
It seems been existed from first, maybe not been exposed via public API.
macOS 10.10+
And please use this only to obtain human-readable labels. Not to identify each GCDQ.
If you want to check whether your code is running on certain GCDQ, you can use dispatchPrecondition(...) function.
If you don't like unsafe pointers and c-strings, there is another, safe solution:
if let currentQueueLabel = OperationQueue.current?.underlyingQueue?.label {
print(currentQueueLabel)
// Do something...
}
I don't know any cases when the currentQueueLabel
will be nil
.
This works best for me:
/// The name/description of the current queue (Operation or Dispatch), if that can be found. Else, the name/description of the thread.
public func queueName() -> String {
if let currentOperationQueue = OperationQueue.current {
if let currentDispatchQueue = currentOperationQueue.underlyingQueue {
return "dispatch queue: \(currentDispatchQueue.label.nonEmpty ?? currentDispatchQueue.description)"
}
else {
return "operation queue: \(currentOperationQueue.name?.nonEmpty ?? currentOperationQueue.description)"
}
}
else {
let currentThread = Thread.current
return "UNKNOWN QUEUE on thread: \(currentThread.name?.nonEmpty ?? currentThread.description)"
}
}
public extension String {
/// Returns this string if it is not empty, else `nil`.
public var nonEmpty: String? {
if self.isEmpty {
return nil
}
else {
return self
}
}
}
This method will work for both OperationQueue
and DispatchQueue
.
func printCurrnetQueueName()
{
print(Thread.current.name!)
}
Here's a wrapper class that offers some safety (revised from here):
import Foundation
/// DispatchQueue wrapper that acts as a reentrant to a synchronous queue;
/// so callers to the `sync` function will check if they are on the current
/// queue and avoid deadlocking the queue (e.g. by executing another queue
/// dispatch call). Instead, it will just execute the given code in place.
public final class SafeSyncQueue {
public init(label: String, attributes: DispatchQueue.Attributes) {
self.queue = DispatchQueue(label: label, attributes: attributes)
self.queueKey = DispatchSpecificKey<QueueIdentity>()
self.queue.setSpecific(key: self.queueKey, value: QueueIdentity(label: self.queue.label))
}
// MARK: - API
/// Note: this will execute without the specified flags if it's on the current queue already
public func sync<T>(flags: DispatchWorkItemFlags? = nil, execute work: () throws -> T) rethrows -> T {
if self.currentQueueIdentity?.label == self.queue.label {
return try work()
} else if let flags = flags {
return try self.queue.sync(flags: flags, execute: work)
} else {
return try self.queue.sync(execute: work)
}
}
// MARK: - Private Structs
private struct QueueIdentity {
let label: String
}
// MARK: - Private Properties
private let queue: DispatchQueue
private let queueKey: DispatchSpecificKey<QueueIdentity>
private var currentQueueIdentity: QueueIdentity? {
return DispatchQueue.getSpecific(key: self.queueKey)
}
}