Last active
March 9, 2016 09:49
-
-
Save austinzheng/787f3ed68337e033a5aa to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Foundation | |
func main() { | |
print("Starting") | |
// GCD works by dispatching chunks of code (represented by closures, and called 'blocks') onto things called 'dispatch | |
// queues'. These queues run the blocks, either on the main thread or in a background thread. (Queues don't correspond | |
// to threads on a one-to-one basis; GCD is responsible for spinning up threads to service queues.) | |
// Here's a variable representing shared state I want to manipulate from different threads. | |
var value = 0 | |
// I'm going to run 5 concurrent operations, for the sake of this demo. | |
let numberOfQueues = 5 | |
// This is a closure representing some work I want to run in the background. I'll end up running it 5 times, to | |
// simulate 5 tasks. This closure is the 'block' I'll be submitting to my dispatch queue. | |
let doSomething = { | |
// The next two lines are work running on a background queue. | |
// Randomly sleep for some time between 0 and 5 seconds (usleep takes microseconds) | |
let someValue = arc4random_uniform(5000000) | |
usleep(someValue) | |
// Now, I'm going to dispatch back onto the main queue. The main queue is a special queue that represents tasks | |
// running on the main thread. It's often used for synchronization, in a similar way to how mutexes and locks might | |
// protect shared mutable state in a C program. | |
// THIS IS VERY IMPORTANT: if you have shared mutable state, YOU SHOULD ONLY MODIFY IT USING CODE RUNNING ON THE | |
// SAME SERIAL QUEUE (usually the main queue). This is a very common iOS application development pattern. | |
dispatch_async(dispatch_get_main_queue()) { | |
// Everything in this closure is happening on the main queue. | |
// Increment value by one. | |
value += 1 | |
print("After waiting \(someValue) microseconds, 'value' is now \(value)") | |
if value == numberOfQueues { | |
// Once all 5 queues have returned, then kill the program. | |
print("All queues done, goodbye") | |
exit(EXIT_SUCCESS) | |
} | |
} | |
} | |
// WORKING WITH QUEUES: | |
// You can create dispatch queues yourself. The first argument is a C string that names the queue (and is optional, so | |
// I omitted it). The second argument determines whether the queue executes the blocks one at a time, or multiple | |
// blocks at once (concurrent). More info on that below. | |
// let runQueue = dispatch_queue_create(nil, DISPATCH_QUEUE_SERIAL) | |
// In addition to making queues, GCD comes with a couple of prebuilt queues. These 'global queues' are going to run on | |
// background threads. There are a couple of QOS_CLASS_* identifiers, which you can use to determine how important | |
// the code running on that queue is (and therefore what priority it'll get). The second argument is always 0. | |
// The global queues are *concurrent*, which means they don't need to wait for a block to finish before starting | |
// another one. Exactly how many blocks can run at once on a concurrent queue is determined by GCD. In practice this | |
// number is probably above 5, which means that all 5 of our tasks will start at the same time. However, if we had | |
// (e.g.) 100 tasks, some of those tasks might have to wait until earlier tasks are finished before they have a | |
// chance to start running. | |
let backgroundQueue = dispatch_get_global_queue(QOS_CLASS_DEFAULT, 0) | |
// DISPATCHING WORK ONTO QUEUES: | |
// Now, run my block (doSomething), five times. | |
dispatch_async(backgroundQueue, doSomething) | |
dispatch_async(backgroundQueue, doSomething) | |
dispatch_async(backgroundQueue, doSomething) | |
dispatch_async(backgroundQueue, doSomething) | |
dispatch_async(backgroundQueue, doSomething) | |
// dispatch_main() 'parks' the main thread and will run any blocks that are dispatched onto it. It doesn't return; | |
// once you call it your program belongs to GCD forever. | |
dispatch_main() | |
} | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment