Last active
February 7, 2021 15:20
-
-
Save jhanzo/8ca2f74230a8dc62b5fac5cae95b141a to your computer and use it in GitHub Desktop.
Quick overview about semaphores
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
//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