Skip to content

Instantly share code, notes, and snippets.

@shakemno
Forked from lamprosg/gcd.swift
Created December 8, 2019 18:16
Show Gist options
  • Save shakemno/fa4b6ea5909b26ab30eee7f18b7c7872 to your computer and use it in GitHub Desktop.
Save shakemno/fa4b6ea5909b26ab30eee7f18b7c7872 to your computer and use it in GitHub Desktop.
(iOS) GCD
//https://medium.com/@nimjea/grand-central-dispatch-in-swift-fdfdd8b22d52
DispatchQueue.main.async {
// Perform your async code here
}
//Synced operations
let northZone = DispatchQueue(label: "perform_task_with_team_north")
//Sync operation
// the program waits until execution finishes before the method call returns
northZone.sync {
for numer in 1...3{ print("North \(numer)")}
}
//Async operation
// executed asynchronously with the async method, the method call returns immediately
northZone.async {
for numer in 1...3{ print("North \(numer)") }
}
// Queues:
// Global Queue - Using to perform non-UI work in the background
// Main Queue - Using to update the UI after completing work in a task on a concurrent queue.
//QoS Priorities:
/*
.userInteractive
.userInitiated
.default
.utility
.background
.unspecified
*/
DispatchQueue.global(qos: .background).async {
// Call your background task
DispatchQueue.main.async {
// UI Updates here for task complete.
}
}
//DispatchQueue with delay
let deadlineTime = DispatchTime.now() + .seconds(1)
DispatchQueue.main.asyncAfter(deadline: deadlineTime) {
//Perform code here
}
//Dispatch groups
let dispatchGroup = DispatchGroup()
dispatchGroup.enter()
loadUseractivities { dispatchGroup.leave() }
dispatchGroup.enter()
loaduserComments { dispatchGroup.leave() }
dispatchGroup.notify(queue: .main) {
print("all activities complete 👍")
}
//DispatchWorkItem
private var pendingRequestWorkItem: DispatchWorkItem?
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
// Cancel the currently pending item
pendingRequestWorkItem?.cancel()
// Wrap our request in a work item
let requestWorkItem = DispatchWorkItem { [weak self] in
self?.resultsLoader.loadResults(forQuery: searchText)
}
// Save the new work item and execute it after 250 ms
pendingRequestWorkItem = requestWorkItem
DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(250),
execute: requestWorkItem)
}
//DispatchSemaphore
https://medium.com/@roykronenfeld/semaphores-in-swift-e296ea80f860
/*
A semaphore consist of a threads queue and a counter value (type Int).
Threads queue is used by the semaphore to keep track on waiting threads in FIFO order
(The first thread entered to the queue will be the first to get access to the shared resource once it is available).
Counter value is used by the semaphore to decide if a thread should get access to a shared resource or not.
The counter value changes when we call signal() or wait() functions.
wait() -> counter--. if counter < 0 thread is freezed. if counter > 0 execute thread
signal() -> counter++. if previousCounter < 0 execute oldest thread in queue. if previousCounter > 0 queue is empty. No one waits
*/
//DispatchSemaphore provides a way to synchronously wait for a group of asynchronous tasks.
//Calling wait() before a signal() will block the current queue until a signal is received.
extension Array where Element == DataSource {
func load() throws -> NoteCollection {
let semaphore = DispatchSemaphore(value: 0)
var loadedCollection: NoteCollection?
// We create a new queue to do our work on, since calling wait() on
// the semaphore will cause it to block the current queue
let loadingQueue = DispatchQueue.global()
loadingQueue.async {
// We extend 'load' to perform its work on a specific queue
self.load(onQueue: loadingQueue) { collection in
loadedCollection = collection
// Once we're done, we signal the semaphore to unblock its queue
semaphore.signal()
}
}
// Wait with a timeout of 5 seconds
semaphore.wait(timeout: .now() + 5)
guard let collection = loadedCollection else {
throw NoteLoadingError.timedOut
}
return collection
}
}
//Using the above new method on Array
//we can now load notes synchronously in a script or command line tool like this:
let dataSources: [DataSource] = [
localDataSource,
iCloudDataSource,
backendDataSource
]
do {
let collection = try dataSources.load()
output(collection)
} catch {
output(error)
}
//DispatchSource
//Observe file changes
class FileObserver {
private let file: File
private let queue: DispatchQueue
private var source: DispatchSourceFileSystemObject?
init(file: File) {
self.file = file
self.queue = DispatchQueue(label: "com.myapp.fileObserving")
}
func start(closure: @escaping () -> Void) {
// We can only convert an NSString into a file system representation
let path = (file.path as NSString)
let fileSystemRepresentation = path.fileSystemRepresentation
// Obtain a descriptor from the file system
let fileDescriptor = open(fileSystemRepresentation, O_EVTONLY)
// Create our dispatch source
let source = DispatchSource.makeFileSystemObjectSource(
fileDescriptor: fileDescriptor,
eventMask: .write,
queue: queue
)
// Assign the closure to it, and resume it to start observing
source.setEventHandler(handler: closure)
source.resume()
self.source = source
}
}
//Use it
let observer = try FileObserver(file: file)
observer.start {
print("File was changed")
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment