Thursday, February 2, 2023
Learning Code
  • Home
  • JavaScript
  • Java
  • Python
  • Swift
  • C++
  • C#
No Result
View All Result
  • Home
  • JavaScript
  • Java
  • Python
  • Swift
  • C++
  • C#
No Result
View All Result
Learning Code
No Result
View All Result
Home Swift

Ultimate Grand Central Dispatch tutorial in Swift

learningcode_x1mckf by learningcode_x1mckf
October 4, 2022
in Swift
0
Ultimate Grand Central Dispatch tutorial in Swift
74
SHARES
1.2k
VIEWS
Share on FacebookShare on Twitter


2018/07/10

Study the ideas of multi-threading with the GCD framework in Swift. Queues, duties, teams all the pieces you will ever want I promise.

iOS

GCD concurrency tutorial for freshmen

The Grand Central Dispatch (GCD, or simply Dispatch) framework is predicated on the underlying thread pool design sample. Which means there are a hard and fast variety of threads spawned by the system – primarily based on some components like CPU cores – they’re all the time out there ready for duties to be executed concurrently. 🚦

Creating threads on the run is an costly activity so GCD organizes duties into particular queues, and afterward the duties ready on these queues are going to be executed on a correct and out there thread from the pool. This strategy results in nice efficiency and low execution latency. We are able to say that the Dispatch framework is a really quick and environment friendly concurrency framework designed for contemporary multicore hardwares and wishes.

Concurrency, multi-tasking, CPU cores, parallelism and threads

A processor can run duties made by you programmatically, that is normally referred to as coding, growing or programming. The code executed by a CPU core is a thread. So your app goes to create a course of that’s made up from threads. 🤓

Up to now a processor had one single core, it might solely take care of one activity at a time. In a while time-slicing was launched, so CPU’s might execute threads concurrently utilizing context switching. As time handed by processors gained extra horse energy and cores so that they had been able to actual multi-tasking utilizing parallelism. ⏱

These days a CPU is a really highly effective unit, it is able to executing billions of duties (cycles) per second. Due to this excessive availability pace Intel launched a expertise referred to as hyperthreading. They divided CPU clock cycles between (normally two) processes working on the similar time, so the variety of out there threads basically doubled. 📈

As you’ll be able to see concurrenct execution will be achieved with varied methods, however you need not care about that a lot. It is as much as the CPU structure the way it solves concurrency, and it is the working system’s activity how a lot thread goes to be spawned for the underlying thread pool. The GCD framework will conceal all of the complexity, however it’s all the time good to grasp the fundamental ideas. 👍


Synchronous and asynchronous execution

Every work merchandise will be executed both synchronously or asynchronously.

Have you ever ever heard of blocking and non-blocking code? This is similar situaton right here. With synchronous duties you will block the execution queue, however with async duties your name will immediately return and the queue can proceed the execution of the remaining duties (or work gadgets as Apple calls them). 🚧

Synchronous execution

When a piece merchandise is executed synchronously with the sync technique, this system waits till execution finishes earlier than the tactic name returns.

Your perform is almost certainly synchronous if it has a return worth, so func load() -> String goes to in all probability block the factor that runs on till the sources is totally loaded and returned again.

Asynchronous execution

When a piece merchandise is executed asynchronously with the async technique, the tactic name returns instantly.

Completion blocks are a superb sing of async strategies, for instance for those who have a look at this technique func load(completion: (String) -> Void) you’ll be able to see that it has no return sort, however the results of the perform is handed again to the caller afterward by a block.

This can be a typical use case, if you need to await one thing inside your technique like studying the contents of an enormous file from the disk, you do not wish to block your CPU, simply due to the gradual IO operation. There will be different duties that aren’t IO heavy in any respect (math operations, and so on.) these will be executed whereas the system is studying your file from the bodily exhausting drive. 💾

With dispatch queues you’ll be able to execute your code synchronously or asynchronously. With syncronous execution the queue waits for the work, with async execution the code returns instantly with out ready for the duty to finish. ⚡️


Dispatch queues

As I discussed earlier than, GCD organizes activity into queues, these are similar to the queues on the shopping center. On each dispatch queue, duties will likely be executed in the identical order as you add them to the queue – FIFO: the primary activity within the line will likely be executed first – however it is best to observe that the order of completion just isn’t assured. Duties will likely be accomplished based on the code complexity. So for those who add two duties to the queue, a gradual one first and a quick one later, the quick one can end earlier than the slower one. ⌛️

Serial and concurrent queues

There are two varieties of dispatch queues. Serial queues can execute one activity at a time, these queues will be utilized to synchronize entry to a particular useful resource. Concurrent queues however can execute a number of duties parallell in the identical time. Serial queue is rather like one line within the mall with one cashier, concurrent queue is like one single line that splits for 2 or extra cashiers. 💰

Predominant, international and customized queues

The foremost queue is a serial one, each activity on the principle queue runs on the principle thread.

World queues are system offered concurrent queues shared by the working system. There are precisely 4 of them organized by excessive, default, low precedence plus an IO throttled background queue.

Customized queues will be created by the consumer. Customized concurrent queues all the time mapped into one of many international queues by specifying a High quality of Service property (QoS). In many of the instances if you wish to run duties in parallel it is strongly recommended to make use of one of many international concurrent queues, it is best to solely create customized serial queues.

System offered queues

  • Serial foremost queue
  • Concurrent international queues
  • excessive precedence international queue
  • default precedence international queue
  • low precedence international queue
  • international background queue (io throttled)

Customized queues by high quality of service

  • userInteractive (UI updates) -> serial foremost queue
  • userInitiated (async UI associated duties) -> excessive precedence international queue
  • default -> default precedence international queue
  • utility -> low precedence international queue
  • background -> international background queue
  • unspecified (lowest) -> low precedence international queue

Sufficient from the idea, let’s examine easy methods to use the Dispatch framework in motion! 🎬


Learn how to use the DispatchQueue class in Swift?

Right here is how one can get all of the queues from above utilizing the model new GCD syntax out there from Swift 3. Please observe that it is best to all the time use a worldwide concurrent queue as an alternative of making your individual one, besides if you’ll use the concurrent queue for locking with boundaries to attain thread safety, extra on that later. 😳

Learn how to get a queue?

import Dispatch

DispatchQueue.foremost
DispatchQueue.international(qos: .userInitiated)
DispatchQueue.international(qos: .userInteractive)
DispatchQueue.international(qos: .background)
DispatchQueue.international(qos: .default)
DispatchQueue.international(qos: .utility)
DispatchQueue.international(qos: .unspecified)
DispatchQueue(label: "com.theswiftdev.queues.serial")
DispatchQueue(label: "com.theswiftdev.queues.concurrent", attributes: .concurrent)

So executing a activity on a background queue and updating the UI on the principle queue after the duty completed is a reasonably straightforward one utilizing Dispatch queues.

DispatchQueue.international(qos: .background).async 
    

    DispatchQueue.foremost.async 
        
    

Sync and async calls on queues

There isn’t a large distinction between sync and async strategies on a queue. Sync is simply an async name with a semaphore (defined later) that waits for the return worth. A sync name will block, however an async name will instantly return. 🎉

let q = DispatchQueue.international()

let textual content = q.sync 
    return "this can block"

print(textual content)

q.async 
    print("this can return immediately")

Principally for those who want a return worth use sync, however in each different case simply go along with async. DEADLOCK WARNING: it is best to by no means name sync on the principle queue, as a result of it will trigger a impasse and a crash. You need to use this snippet in case you are searching for a secure solution to do sync calls on the principle queue / thread. 👌

Do not name sync on a serial queue from the serial queue’s thread!

Delay execution

You possibly can merely delay code execution utilizing the Dispatch framework.

DispatchQueue.foremost.asyncAfter(deadline: .now() + .seconds(2)) 
    

Carry out concurrent loop

Dispatch queue merely lets you carry out iterations concurrently.

DispatchQueue.concurrentPerform(iterations: 5)  (i) in
    print(i)

Debugging

Oh, by the best way it is only for debugging objective, however you’ll be able to return the title of the present queue by utilizing this little extension. Don’t use in manufacturing code!!!

extension DispatchQueue 
    static var currentLabel: String 
        return String(validatingUTF8: __dispatch_queue_get_label(nil))!
    


Utilizing DispatchWorkItem in Swift

DispatchWorkItem encapsulates work that may be carried out. A piece merchandise will be dispatched onto a DispatchQueue and inside a DispatchGroup. A DispatchWorkItem can be set as a DispatchSource occasion, registration, or cancel handler.

So that you similar to with operations by utilizing a piece merchandise you’ll be able to cancel a working activity. Additionally work gadgets can notify a queue when their activity is accomplished.

var workItem: DispatchWorkItem?
workItem = DispatchWorkItem 
    for i in 1..<6 
        guard let merchandise = workItem, !merchandise.isCancelled else 
            print("cancelled")
            break
        
        sleep(1)
        print(String(i))
    


workItem?.notify(queue: .foremost) 
    print("executed")


DispatchQueue.international().asyncAfter(deadline: .now() + .seconds(2)) 
    workItem?.cancel()

DispatchQueue.foremost.async(execute: workItem!)

Concurrent duties with DispatchGroups

So you could carry out a number of community calls so as to assemble the information required by a view controller? That is the place DispatchGroup can assist you. All your lengthy working background activity will be executed concurrently, when all the pieces is prepared you will obtain a notification. Simply watch out you need to use thread-safe information constructions, so all the time modify arrays for instance on the identical thread! 😅

func load(delay: UInt32, completion: () -> Void) 
    sleep(delay)
    completion()


let group = DispatchGroup()

group.enter()
load(delay: 1) 
    print("1")
    group.go away()


group.enter()
load(delay: 2) 
    print("2")
    group.go away()


group.enter()
load(delay: 3) 
    print("3")
    group.go away()


group.notify(queue: .foremost) 
    print("executed")

Observe that you simply all the time need to stability out the enter and go away calls on the group. The dispatch group additionally permits us to trace the completion of various work gadgets, even when they run on totally different queues.

let group = DispatchGroup()
let queue = DispatchQueue(label: "com.theswiftdev.queues.serial")
let workItem = DispatchWorkItem 
    print("begin")
    sleep(1)
    print("finish")


queue.async(group: group) 
    print("group begin")
    sleep(2)
    print("group finish")

DispatchQueue.international().async(group: group, execute: workItem)



group.notify(queue: .foremost) 
    print("executed")

Another factor that you should utilize dispatch teams for: think about that you simply’re displaying a properly animated loading indicator whilst you do some precise work. It would occurs that the work is completed sooner than you’d anticipate and the indicator animation couldn’t end. To unravel this example you’ll be able to add a small delay activity so the group will wait till each of the duties end. 😎

let queue = DispatchQueue.international()
let group = DispatchGroup()
let n = 9
for i in 0..<n 
    queue.async(group: group) 
        print("(i): Working async activity...")
        sleep(3)
        print("(i): Async activity accomplished")
    

group.wait()
print("executed")

Semaphores

A semaphore) is solely a variable used to deal with useful resource sharing in a concurrent system. It is a actually highly effective object, listed below are a couple of vital examples in Swift.

Learn how to make an async activity to synchronous?

The reply is straightforward, you should utilize a semaphore (bonus level for timeouts)!

enum DispatchError: Error 
    case timeout


func asyncMethod(completion: (String) -> Void) 
    sleep(2)
    completion("executed")


func syncMethod() throws -> String 

    let semaphore = DispatchSemaphore(worth: 0)
    let queue = DispatchQueue.international()

    var response: String?
    queue.async 
        asyncMethod  r in
            response = r
            semaphore.sign()
        
    
    semaphore.wait(timeout: .now() + 5)
    guard let end result = response else 
        throw DispatchError.timeout
    
    return end result


let response = strive? syncMethod()
print(response)

Lock / single entry to a useful resource

If you wish to keep away from race situation you’re in all probability going to make use of mutual exclusion. This could possibly be achieved utilizing a semaphore object, but when your object wants heavy studying functionality it is best to take into account a dispatch barrier primarily based answer. 😜

class LockedNumbers 

    let semaphore = DispatchSemaphore(worth: 1)
    var parts: [Int] = []

    func append(_ num: Int) 
        self.semaphore.wait(timeout: DispatchTime.distantFuture)
        print("appended: (num)")
        self.parts.append(num)
        self.semaphore.sign()
    

    func removeLast() 
        self.semaphore.wait(timeout: DispatchTime.distantFuture)
        defer 
            self.semaphore.sign()
        
        guard !self.parts.isEmpty else 
            return
        
        let num = self.parts.removeLast()
        print("eliminated: (num)")
    


let gadgets = LockedNumbers()
gadgets.append(1)
gadgets.append(2)
gadgets.append(5)
gadgets.append(3)
gadgets.removeLast()
gadgets.removeLast()
gadgets.append(3)
print(gadgets.parts)

Anticipate a number of duties to finish

Similar to with dispatch teams, you may as well use a semaphore object to get notified if a number of duties are completed. You simply have to attend for it…

let semaphore = DispatchSemaphore(worth: 0)
let queue = DispatchQueue.international()
let n = 9
for i in 0..<n 
    queue.async 
        print("run (i)")
        sleep(3)
        semaphore.sign()
    

print("wait")
for i in 0..<n 
    semaphore.wait()
    print("accomplished (i)")

print("executed")

Batch execution utilizing a semaphore

You possibly can create a thread pool like conduct to simulate restricted sources utilizing a dispatch semaphore. So for instance if you wish to obtain plenty of photos from a server you’ll be able to run a batch of x each time. Fairly helpful. 🖐

print("begin")
let sem = DispatchSemaphore(worth: 5)
for i in 0..<10 
    DispatchQueue.international().async 
        sem.wait()
        sleep(2)
        print(i)
        sem.sign()
    

print("finish")

The DispatchSource object

A dispatch supply is a basic information sort that coordinates the processing of particular low-level system occasions.

Alerts, descriptors, processes, ports, timers and lots of extra. Every thing is dealt with by the dispatch source object. I actually do not wish to get into the small print, it is fairly low-level stuff. You possibly can monitor information, ports, alerts with dispatch sources. Please simply learn the offical Apple docs. 📄

I would wish to make just one instance right here utilizing a dispatch source timer.

let timer = DispatchSource.makeTimerSource()
timer.schedule(deadline: .now(), repeating: .seconds(1))
timer.setEventHandler 
    print("howdy")

timer.resume()

Thread-safety utilizing the dispatch framework

Thread safety is an inevitable matter if it involves multi-threaded code. At first I discussed that there’s a thread pool underneath the hood of GCD. Each thread has a run loop object related to it, you’ll be able to even run them by hand. In case you create a thread manually a run loop will likely be added to that thread routinely.

let t = Thread 
    print(Thread.present.title ?? "")
     let timer = Timer(timeInterval: 1, repeats: true)  t in
         print("tick")
     
     RunLoop.present.add(timer, forMode: .defaultRunLoopMode)

    RunLoop.present.run()
    RunLoop.present.run(mode: .commonModes, earlier than: Date.distantPast)

t.title = "my-thread"
t.begin()

You shouldn’t do that, demo functions solely, all the time use GCD queues!

Queue != Thread

A GCD queue just isn’t a thread, for those who run a number of async operations on a concurrent queue your code can run on any out there thread that matches the wants.

Thread security is all about avoiding tousled variable states

Think about a mutable array in Swift. It may be modified from any thread. That is not good, as a result of finally the values within it are going to be tousled like hell if the array just isn’t thread secure. For instance a number of threads are attempting to insert values to the array. What occurs? In the event that they run in parallell which aspect goes to be added first? Now because of this you want generally to create thread secure sources.

Serial queues

You need to use a serial queue to implement mutual exclusivity. All of the duties on the queue will run serially (in a FIFO order), just one course of runs at a time and duties have to attend for one another. One large draw back of the answer is pace. 🐌

let q = DispatchQueue(label: "com.theswiftdev.queues.serial")

q.async() 
  


q.sync() 
  

Concurrent queues utilizing boundaries

You possibly can ship a barrier activity to a queue for those who present an additional flag to the async technique. If a activity like this arrives to the queue it will be sure that nothing else will likely be executed till the barrier activity have completed. To sum this up, barrier duties are sync (factors) duties for concurrent queues. Use async boundaries for writes, sync blocks for reads. 😎

let q = DispatchQueue(label: "com.theswiftdev.queues.concurrent", attributes: .concurrent)

q.async(flags: .barrier) 
  


q.sync() 
  

This technique will lead to extraordinarily quick reads in a thread secure surroundings. You too can use serial queues, semaphores, locks all of it depends upon your present scenario, however it’s good to know all of the out there choices is not it? 🤐


A number of anti-patterns

It’s important to be very cautious with deadlocks, race conditions and the readers writers problem. Normally calling the sync technique on a serial queue will trigger you many of the troubles. One other problem is thread security, however we have already coated that half. 😉

let queue = DispatchQueue(label: "com.theswiftdev.queues.serial")

queue.sync 
    
    queue.sync 
        
    



DispatchQueue.international(qos: .utility).sync 
    
    DispatchQueue.foremost.sync 
        
    

The Dispatch framework (aka. GCD) is an incredible one, it has such a possible and it actually takes a while to grasp it. The actual query is that what path goes to take Apple so as to embrace concurrent programming into a complete new stage? Promises or await, perhaps something entirely new, let’s hope that we’ll see one thing in Swift 6.



Source link

You might also like

The abstract Vapor service factory design pattern

SwiftNIO tutorial – The echo server

Introducing – Vapor cheatsheet – The.Swift.Dev.

Share30Tweet19
learningcode_x1mckf

learningcode_x1mckf

Recommended For You

The abstract Vapor service factory design pattern

by learningcode_x1mckf
February 1, 2023
0
The abstract Vapor service factory design pattern

I've written a number of articles about manufacturing unit design patterns on my weblog and this time I might like to speak a couple of particular one, which...

Read more

SwiftNIO tutorial – The echo server

by learningcode_x1mckf
January 27, 2023
0
SwiftNIO tutorial – The echo server

Intoducing SwiftNIO In the event you used a excessive degree net framework, corresponding to Vapor, up to now, you would possibly had some interplay with occasion loops...

Read more

Introducing – Vapor cheatsheet – The.Swift.Dev.

by learningcode_x1mckf
January 23, 2023
0
Introducing – Vapor cheatsheet – The.Swift.Dev.

Out there on Gumroad Thanks for supporting my work by buying the cheatsheet. 🙏 Download now A whole Vapor framework reference for novices. greater than...

Read more

iCloud Programming Tutorial for iOS: An Introduction

by learningcode_x1mckf
January 18, 2023
0
iCloud Programming Tutorial for iOS: An Introduction

Editor’s observe: This week, we work with Ziad Tamim once more to provide you an introduction of iCloud programming. You’ll learn to save and retrieve knowledge from iCloud.On...

Read more

Easy multipart file upload for Swift

by learningcode_x1mckf
January 18, 2023
0
Easy multipart file upload for Swift

I imagine that you've got already heard in regards to the well-known multipart-data add method that everybody likes to add recordsdata and submit type knowledge, but when not,...

Read more
Next Post

25 Malicious JavaScript Libraries Distributed via Official NPM Package Repository

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

Related News

Solving Your Puzzles With Python – Real Python

Solving Your Puzzles With Python – Real Python

November 30, 2022
Full-Stack Java Developer at Hire Resolve – Gauteng Johannesburg

Full-Stack Java Developer at Hire Resolve – Gauteng Johannesburg

December 16, 2022
Time limit for notify – JavaScript – SitePoint Forums

Javascript on mac Safari causing problems – JavaScript – SitePoint Forums

September 28, 2022

Browse by Category

  • C#
  • C++
  • Java
  • JavaScript
  • Python
  • Swift

RECENT POSTS

  • Java :Full Stack Developer – Western Cape saon_careerjunctionza_state
  • Pay What You Want for this Learn to Code JavaScript Certification Bundle
  • UPB Java Jam brings coffeehouse vibes to Taylor Down Under | Culture

CATEGORIES

  • C#
  • C++
  • Java
  • JavaScript
  • Python
  • Swift

© 2022 Copyright Learning Code

No Result
View All Result
  • Home
  • JavaScript
  • Java
  • Python
  • Swift
  • C++
  • C#

© 2022 Copyright Learning Code

Are you sure want to unlock this post?
Unlock left : 0
Are you sure want to cancel subscription?