Skip to content

Instantly share code, notes, and snippets.

@jhanzo
Last active February 7, 2021 15:20
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save jhanzo/8ca2f74230a8dc62b5fac5cae95b141a to your computer and use it in GitHub Desktop.
Save jhanzo/8ca2f74230a8dc62b5fac5cae95b141a to your computer and use it in GitHub Desktop.
Quick overview about semaphores
//In iOS, Grand Central Dispatch brings some utilities for using asynchronous tasks
//Among all functionalities, there is Semaphore which is an old school theory thought by Djikstra
//More info here : https://en.wikipedia.org/wiki/Semaphore_(programming)
//Semaphores give a control access to a common resource through concurrent tasks (done in other threads)
//NB 1: in iOS, all UI jobs has to be done ONLY in main thread, otherwise a fatal error occurs
//NB 2: before using semaphore in iOS you should always wonder if dispatch_group is not enough
//NB 3: for doing an async task in your playground you have to use semaphore concept or at least this two kinds of methods :
// XCPlaygroundPage.currentPage.needsIndefiniteExecution = true
// XCPlaygroundPage.currentPage.finishExecution()
//Available objects :
// dispatch_semaphore_t
// - Description : OS_dispatch_semaphore object
// dispatch_semaphore_create
// - Description : create semaphore pool
// - Parameter : Int, number of pools
// - Returns : nil if number of pools is negative
// dispatch_semaphore_signal
// - Description : Increment semaphore, if previous value is negative it calls waiting thread
// - Parameter : dispatch_semaphore_t, semaphore to increment
// - Returns : 0 if no thread woken
// dispatch_semaphore_wait
// - Description : decrement semaphore, if result is less than zero function waits for a signal
// - Parameters : dispatch_semaphore_t, dispatch_time_t for timeout
// - Returns : returns 0 if success
let url = NSURL(string: "http://www.google.com")
let request = NSURLRequest(URL: url!)
let numberOfSecondsForTimeout = 10.0
// Single block (does not really usefull, dispatch_async should be more relevant)
func singleBlockMethod() {
print("Semaphore - Single Block")
let sem = dispatch_semaphore_create(1);
print("1.1")
NSURLSession.sharedSession().dataTaskWithURL(url!) { (_, _, _) in
print("1.3")
sleep(3)
dispatch_semaphore_signal(sem)
}.resume()
print("1.2")
let timeout = dispatch_time(DISPATCH_TIME_NOW, Int64(numberOfSecondsForTimeout) * Int64(NSEC_PER_SEC))
dispatch_semaphore_wait(sem, timeout)
if dispatch_semaphore_wait(sem, timeout) == 0 {
print("1.4")
} else {
print("1.timeout")
}
}
singleBlockMethod()
//prints something like this :
//1.1...1.2...1.3...(wait 3 seconds)...1.4...
//NB : in this example if you put another int in parameter of dispatch_semaphore_create
//and since dispatch_semaphore_wait decrements semaphore, number is still greater than 0 so method does not wait
//and output would be : 1.1...1.2...1.4
//For having the expected result dispatch_semaphore_wait should be called as many times as specified in
//dispatch_semaphore_create parameter (+1)
func multipleBlockMethod() {
print("Semaphore - Multiple Block")
let timeout = dispatch_time(DISPATCH_TIME_NOW, Int64(numberOfSecondsForTimeout) * Int64(NSEC_PER_SEC))
let sem = dispatch_semaphore_create(0);
print("2.1")
NSURLSession.sharedSession().dataTaskWithURL(url!) { (_, _, _) in
print("2.3")
sleep(3)
dispatch_semaphore_signal(sem)
}.resume()
NSURLSession.sharedSession().dataTaskWithURL(url!) { (_, _, _) in
print("2.5")
sleep(5)
dispatch_semaphore_signal(sem)
}.resume()
print("2.2")
if dispatch_semaphore_wait(sem, timeout) == 0 {
print("2.4")
} else {
print("2.4.timeout")
}
if dispatch_semaphore_wait(sem, timeout) == 0 {
print("2.6")
} else {
print("2.6.timeout")
}
print("2.7")
}
multipleBlockMethod()
//prints something like this :
//2.1...2.2...2.3...(wait 3 seconds)...2.4...2.5...(wait 5 seconds)...2.6...2.7
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment