├── .DS_Store
├── .nojekyll
├── Assignments
├── Project.md
└── wire.jpeg
├── LICENSE
├── Lessons
├── .DS_Store
├── 01-Intro-Concurrency-&-Parallelism
│ ├── .DS_Store
│ ├── Lesson1.md
│ └── assets
│ │ ├── .DS_Store
│ │ ├── 414px-Dual_Core_Generic.svg.png
│ │ ├── Figure_4.4.png
│ │ ├── Threads(solution).playground
│ │ ├── Contents.swift
│ │ ├── contents.xcplayground
│ │ ├── playground.xcworkspace
│ │ │ ├── contents.xcworkspacedata
│ │ │ ├── xcshareddata
│ │ │ │ └── IDEWorkspaceChecks.plist
│ │ │ └── xcuserdata
│ │ │ │ ├── gordoneliel.xcuserdatad
│ │ │ │ └── UserInterfaceState.xcuserstate
│ │ │ │ └── thomas_vandegriff.xcuserdatad
│ │ │ │ └── UserInterfaceState.xcuserstate
│ │ └── timeline.xctimeline
│ │ ├── Threads.playground.zip
│ │ ├── Threads.playground
│ │ ├── Contents.swift
│ │ ├── contents.xcplayground
│ │ └── playground.xcworkspace
│ │ │ ├── contents.xcworkspacedata
│ │ │ ├── xcshareddata
│ │ │ └── IDEWorkspaceChecks.plist
│ │ │ └── xcuserdata
│ │ │ ├── adrianagonzalezmartinez.xcuserdatad
│ │ │ └── UserInterfaceState.xcuserstate
│ │ │ ├── gordoneliel.xcuserdatad
│ │ │ └── UserInterfaceState.xcuserstate
│ │ │ └── thomas_vandegriff.xcuserdatad
│ │ │ └── UserInterfaceState.xcuserstate
│ │ ├── concurrency.key
│ │ ├── figure_4.3.png
│ │ └── iOS_runtime_process.png
├── 02-Grand-Central_Dispatch-Pt1
│ ├── .DS_Store
│ ├── Lesson2.md
│ ├── assets
│ │ ├── .DS_Store
│ │ ├── GCDPlay.playground.zip
│ │ ├── GCDPlay.playground
│ │ │ ├── Async Queue.xcplaygroundpage
│ │ │ │ └── Contents.swift
│ │ │ ├── AsyncBackgroundAndUtility.xcplaygroundpage
│ │ │ │ └── Contents.swift
│ │ │ ├── Pages
│ │ │ │ ├── Async Queue.xcplaygroundpage
│ │ │ │ │ └── Contents.swift
│ │ │ │ ├── AsyncBackgroundAndUtility.xcplaygroundpage
│ │ │ │ │ └── Contents.swift
│ │ │ │ ├── AsyncUserInitiated.xcplaygroundpage
│ │ │ │ │ └── Contents.swift
│ │ │ │ ├── AsyncUserInitiatedAndUtility.xcplaygroundpage
│ │ │ │ │ └── Contents.swift
│ │ │ │ ├── AsyncUserInitiatedAndUtitlityAndMain.xcplaygroundpage
│ │ │ │ │ └── Contents.swift
│ │ │ │ ├── Concurrent.xcplaygroundpage
│ │ │ │ │ └── Contents.swift
│ │ │ │ ├── DispatchQueueSync*.xcplaygroundpage
│ │ │ │ │ └── Contents.swift
│ │ │ │ ├── SameQueueAsync.xcplaygroundpage
│ │ │ │ │ └── Contents.swift
│ │ │ │ └── Sync Queue.xcplaygroundpage
│ │ │ │ │ └── Contents.swift
│ │ │ ├── contents.xcplayground
│ │ │ └── playground.xcworkspace
│ │ │ │ ├── contents.xcworkspacedata
│ │ │ │ ├── xcshareddata
│ │ │ │ ├── IDEWorkspaceChecks.plist
│ │ │ │ └── WorkspaceSettings.xcsettings
│ │ │ │ └── xcuserdata
│ │ │ │ ├── adrianagonzalezmartinez.xcuserdatad
│ │ │ │ └── UserInterfaceState.xcuserstate
│ │ │ │ ├── gordoneliel.xcuserdatad
│ │ │ │ ├── UserInterfaceState.xcuserstate
│ │ │ │ └── WorkspaceSettings.xcsettings
│ │ │ │ └── thomas_vandegriff.xcuserdatad
│ │ │ │ └── UserInterfaceState.xcuserstate
│ │ ├── SIMD.png
│ │ ├── activity_diag_template.png
│ │ ├── activity_diag_template1.png
│ │ ├── asynchronous.png
│ │ ├── deadlock.png
│ │ ├── iOS_runtime_process.png
│ │ ├── iOS_runtime_process_with-queues.png
│ │ ├── queue-line.png
│ │ ├── sync_deadlock_base.png
│ │ ├── synchronous.png
│ │ ├── synchronous2.png
│ │ ├── thread_pool.png
│ │ └── thread_pool1.png
│ └── bkups_(delete_when_not_needed)
│ │ ├── Readme copy 2.md
│ │ ├── Readme copy.md
│ │ └── Readme.md
├── 03-Grand-Central_Dispatch-Pt2
│ ├── .DS_Store
│ ├── Lesson3.md
│ └── assets
│ │ ├── Critical_section_fg copy.jpg
│ │ ├── Critical_section_fg.jpg
│ │ ├── Critical_section_fg.png
│ │ ├── activity_diag_template.png
│ │ ├── concurrent_queue.png
│ │ ├── iOS_runtime_process_with-queues.png
│ │ ├── serial_queue.png
│ │ └── sync_deadlock_base.png
├── 04-Grand-Central_Dispatch-Pt3
│ ├── .DS_Store
│ ├── Lesson4.md
│ └── assets
│ │ ├── .DS_Store
│ │ ├── DispatchGroups_ex1.playground.zip
│ │ ├── DispatchGroups_ex1.playground
│ │ ├── Contents.swift
│ │ └── contents.xcplayground
│ │ ├── QoSClass_enum.png
│ │ ├── QoS_classes.png
│ │ ├── QoS_ex2.playground
│ │ ├── Contents.swift
│ │ └── contents.xcplayground
│ │ ├── QoS_ex2.zip
│ │ ├── QoS_exercise1.playground.zip
│ │ ├── QoS_exercise1.playground
│ │ ├── Contents.swift
│ │ ├── contents.xcplayground
│ │ └── playground.xcworkspace
│ │ │ └── contents.xcworkspacedata
│ │ ├── gcd_queues.png
│ │ └── special_QoS_classes.png
├── 05-Semaphores
│ └── Lesson5.md
├── 06-Operations-Pt1
│ ├── .DS_Store
│ ├── Lesson6.md
│ └── assets
│ │ ├── .DS_Store
│ │ ├── BlockOperation_ex2.playground.zip
│ │ ├── BlockOperation_ex2.playground
│ │ ├── Contents.swift
│ │ ├── Sources
│ │ │ └── Duration.swift
│ │ ├── contents.xcplayground
│ │ └── playground.xcworkspace
│ │ │ ├── contents.xcworkspacedata
│ │ │ ├── xcshareddata
│ │ │ └── IDEWorkspaceChecks.plist
│ │ │ └── xcuserdata
│ │ │ └── thomas_vandegriff.xcuserdatad
│ │ │ └── UserInterfaceState.xcuserstate
│ │ ├── Operation-Queue.png
│ │ └── Operation_states.png
├── 07-Operations-Pt2
│ └── Lesson7.md
├── 08-Operations-Pt3
│ └── Lesson8.md
├── 09-Pitfalls-Challenges
│ ├── .DS_Store
│ ├── Lesson9.md
│ └── assets
│ │ ├── Sojourner_on_Mars_PIA01122.png
│ │ └── priority_inversion.png
├── 10-Course-Review-and-Workshop
│ └── Lesson10.md
├── old_02-Grand-Central_Dispatch
│ ├── .DS_Store
│ └── assets
│ │ └── GCDPlay.playground
│ │ └── playground.xcworkspace
│ │ ├── contents.xcworkspacedata
│ │ └── xcuserdata
│ │ └── thomas_vandegriff.xcuserdatad
│ │ └── UserInterfaceState.xcuserstate
├── old_04-xxx
│ ├── .DS_Store
│ └── Readme.md
├── old_0x-Operations-Pt1
│ └── Readme.md
├── old_bdd
│ ├── .DS_Store
│ ├── Readme.md
│ └── assets
│ │ └── bdd.key
├── old_challenges-with-concurrency
│ ├── .DS_Store
│ ├── Readme.md
│ └── assets
│ │ ├── .DS_Store
│ │ ├── concurrency-challenges.key
│ │ └── concurrency-challenges.playground
│ │ ├── Pages
│ │ ├── CriticalSection.xcplaygroundpage
│ │ │ └── Contents.swift
│ │ └── Untitled Page 2.xcplaygroundpage
│ │ │ ├── Contents.swift
│ │ │ └── Sources
│ │ │ └── Sync.swift
│ │ ├── contents.xcplayground
│ │ └── playground.xcworkspace
│ │ ├── contents.xcworkspacedata
│ │ ├── xcshareddata
│ │ └── IDEWorkspaceChecks.plist
│ │ └── xcuserdata
│ │ ├── gordoneliel.xcuserdatad
│ │ └── UserInterfaceState.xcuserstate
│ │ └── thomas_vandegriff.xcuserdatad
│ │ └── UserInterfaceState.xcuserstate
├── old_dispatch-queues
│ ├── .DS_Store
│ ├── Readme.md
│ └── assets
│ │ ├── .DS_Store
│ │ ├── Concurrency2.key
│ │ └── GCDPlay.playground
│ │ ├── Async Queue.xcplaygroundpage
│ │ └── Contents.swift
│ │ ├── AsyncBackgroundAndUtility.xcplaygroundpage
│ │ └── Contents.swift
│ │ ├── Pages
│ │ ├── Async Queue.xcplaygroundpage
│ │ │ └── Contents.swift
│ │ ├── AsyncBackgroundAndUtility.xcplaygroundpage
│ │ │ └── Contents.swift
│ │ ├── AsyncUserInitiated.xcplaygroundpage
│ │ │ └── Contents.swift
│ │ ├── AsyncUserInitiatedAndUtility.xcplaygroundpage
│ │ │ └── Contents.swift
│ │ ├── AsyncUserInitiatedAndUtitlityAndMain.xcplaygroundpage
│ │ │ └── Contents.swift
│ │ ├── Concurrent.xcplaygroundpage
│ │ │ └── Contents.swift
│ │ ├── DispatchQueueSync*.xcplaygroundpage
│ │ │ └── Contents.swift
│ │ ├── SameQueueAsync.xcplaygroundpage
│ │ │ └── Contents.swift
│ │ └── Sync Queue.xcplaygroundpage
│ │ │ └── Contents.swift
│ │ ├── contents.xcplayground
│ │ └── playground.xcworkspace
│ │ ├── contents.xcworkspacedata
│ │ ├── xcshareddata
│ │ ├── IDEWorkspaceChecks.plist
│ │ └── WorkspaceSettings.xcsettings
│ │ └── xcuserdata
│ │ ├── adrianagonzalezmartinez.xcuserdatad
│ │ └── UserInterfaceState.xcuserstate
│ │ ├── gordoneliel.xcuserdatad
│ │ ├── UserInterfaceState.xcuserstate
│ │ └── WorkspaceSettings.xcsettings
│ │ └── thomas_vandegriff.xcuserdatad
│ │ └── UserInterfaceState.xcuserstate
├── old_executing-work-gcd
│ ├── .DS_Store
│ ├── Readme.md
│ └── assets
│ │ ├── .DS_Store
│ │ └── executing-work-gcd.key
├── old_interview-practice-problem-concurrency
│ └── Readme.md
├── old_intro-to-testing
│ ├── .DS_Store
│ ├── Readme.md
│ └── assets
│ │ ├── .DS_Store
│ │ ├── intro-testing.key
│ │ ├── target-membership.png
│ │ └── testable-import.png
├── old_operations_1
│ ├── .DS_Store
│ ├── Readme.md
│ └── assets
│ │ ├── .DS_Store
│ │ ├── operations.key
│ │ └── operations.playground
│ │ ├── Contents.swift
│ │ ├── contents.xcplayground
│ │ ├── playground.xcworkspace
│ │ ├── contents.xcworkspacedata
│ │ ├── xcshareddata
│ │ │ └── IDEWorkspaceChecks.plist
│ │ └── xcuserdata
│ │ │ ├── gordoneliel.xcuserdatad
│ │ │ └── UserInterfaceState.xcuserstate
│ │ │ └── thomas_vandegriff.xcuserdatad
│ │ │ └── UserInterfaceState.xcuserstate
│ │ └── timeline.xctimeline
├── old_operations_2
│ ├── .DS_Store
│ └── assets
│ │ └── operations.playground
│ │ └── playground.xcworkspace
│ │ ├── contents.xcworkspacedata
│ │ └── xcuserdata
│ │ └── thomas_vandegriff.xcuserdatad
│ │ └── UserInterfaceState.xcuserstate
├── old_xcode-project-management
│ ├── .DS_Store
│ ├── Readme.md
│ └── assets
│ │ ├── .DS_Store
│ │ ├── target-membership.png
│ │ ├── xcode-project.key
│ │ ├── xcworkspace.png
│ │ └── xcworkspace01.png
└── operations
│ ├── .DS_Store
│ └── assets
│ └── operations.playground
│ └── playground.xcworkspace
│ ├── contents.xcworkspacedata
│ └── xcuserdata
│ └── thomas_vandegriff.xcuserdatad
│ └── UserInterfaceState.xcuserstate
├── README.md
├── StudyGuide.md
├── Web
├── .DS_Store
├── .nojekyll
├── logo-icononly.svg
├── style.css
└── sw.js
├── _navbar.md
├── _sidebar.md
└── index.html
/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Make-School-Courses/MOB-2.3-Concurrency-Parallelism-in-iOS/0ae12a6aa027257fa2f2d34fb98a32d941586347/.DS_Store
--------------------------------------------------------------------------------
/.nojekyll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Make-School-Courses/MOB-2.3-Concurrency-Parallelism-in-iOS/0ae12a6aa027257fa2f2d34fb98a32d941586347/.nojekyll
--------------------------------------------------------------------------------
/Assignments/Project.md:
--------------------------------------------------------------------------------
1 | # Music Player App
2 |
3 | ## Introduction
4 |
5 | So far in your journey as an iOS developer, you've learned how to: build responsive UI, structure an app using MVC, persist data locally and remotely, interact with a backend service and used a variety of APIs available by Apple.
6 |
7 | There are still many other topics you can explore, but with what you know today, you are able to build apps for any domain you can think of.
8 |
9 | This project will combine your current expertise with the content from MOB 2.3 are able to build an app that's responsive and optimizes resources.
10 |
11 | ## Learning Outcomes
12 |
13 | By the end of this project, you should be able to...
14 |
15 | 1. Build a functional app that satisfies the requirements listed below.
16 | 1. Implement common practices to aid with concurrency and persistence in an iOS app.
17 | 1. Use GCD and/or Operations to work with the main and background threads.
18 | 1. Use Xcode's Time Profiler to check the performance of your app.
19 | 1. Be capable of explaining your coding decisions.
20 |
21 | ## Description
22 |
23 | Your task is to create an app that let's users discover new music. The app will also let users preview songs and save them as favorite songs.
24 |
25 | - There's a login page to authenticate the user with Spotify's API/SDK
26 | - The home page should display new releases (albums).
27 | - When you tap on an album, you will go to another view controller to view the tracks.
28 | - Users can listen to a preview of the songs.
29 | - Users can also save songs by marking them as favorite.
30 | - There's another view controller to list all of your favorite songs. You can preview the song from this VC too.
31 | - Optionally, add a VC for an artist's info and top tracks.
32 |
33 | Check the resources for helpful documentation!
34 |
35 |
36 | ## Wireframes
37 |
38 | 
39 |
40 | ## Requirements
41 |
42 | 1. Adhere to the description.
43 | 1. You must use the [Spotify API](https://developer.spotify.com/documentation/web-api/) or [Spotify SDK](https://developer.spotify.com/documentation/ios/)
44 | 1. Allow for the tracks to be previewed (30-sec clips)
45 | 1. Use a persistence method to save the favorite tracks, up to your criteria which one to use.
46 | 1. Use GCD and/or Operations to handle concurrency.
47 | 1. Authenticate users with the Spotify API/SDK - should also be able to log out
48 | 1. Time profile your app and show evidence of it.
49 |
50 | ## Stretch challenges
51 |
52 | 1. Add favorite songs directly to a user's playlist in Spotify
53 | 1. Create a VC for an artist's info and top tracks.
54 | 1. Get creative with your designs!
55 | 1. Implement Apple Sign In
56 |
57 | ## Rubric
58 |
59 | You must score at least 70 points to pass the assignment. Breakdown of points below:
60 |
61 | 1. **(15 points):** Code Quality: intuitive variable names, conventional casing, clear comments, modules are flexible and local, short line lengths, proper formatting.
62 | 1. **(10 points)** Create a usable design that follows iOS UI Guidelines
63 | 1. **(15 points)** Displays 10 most played artists
64 | 1. **(15 points)** Tracks can be previewed
65 | 1. **(15 points)** Each artist has a view that displays the top 10 tracks by the artist
66 | 1. **(15 points)** Ability to favorite a top track, and view all favorites in a list in a separate view
67 | 1. **(5 points)** Uses Spotify API/SDK
68 | 1. **(5 points)** Evidence of using Time Profiler
69 | 1. **(5 points)** Code on GitHub. Include a [README file](https://github.com/matiassingers/awesome-readme)
70 |
71 | ## Resources
72 | - [Spotify API Docs](https://developer.spotify.com/documentation/web-api/)
73 | - [Spotify SDK Docs](https://developer.spotify.com/documentation/ios/)
74 | - [Spotify Authorization Guide](https://developer.spotify.com/documentation/general/guides/authorization-guide/)
75 | - [Spartan Library](https://github.com/Daltron/Spartan)
76 |
77 | ## Past Students' Work
78 |
79 | - [Example 1](https://github.com/MondaleFelix/MusicApp)
80 | - [Example 2](https://github.com/caocmai/spotiFav)
81 | - [Example 3](https://github.com/ellojess/cantatio)
82 |
--------------------------------------------------------------------------------
/Assignments/wire.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Make-School-Courses/MOB-2.3-Concurrency-Parallelism-in-iOS/0ae12a6aa027257fa2f2d34fb98a32d941586347/Assignments/wire.jpeg
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018 Product College Courses
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/Lessons/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Make-School-Courses/MOB-2.3-Concurrency-Parallelism-in-iOS/0ae12a6aa027257fa2f2d34fb98a32d941586347/Lessons/.DS_Store
--------------------------------------------------------------------------------
/Lessons/01-Intro-Concurrency-&-Parallelism/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Make-School-Courses/MOB-2.3-Concurrency-Parallelism-in-iOS/0ae12a6aa027257fa2f2d34fb98a32d941586347/Lessons/01-Intro-Concurrency-&-Parallelism/.DS_Store
--------------------------------------------------------------------------------
/Lessons/01-Intro-Concurrency-&-Parallelism/assets/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Make-School-Courses/MOB-2.3-Concurrency-Parallelism-in-iOS/0ae12a6aa027257fa2f2d34fb98a32d941586347/Lessons/01-Intro-Concurrency-&-Parallelism/assets/.DS_Store
--------------------------------------------------------------------------------
/Lessons/01-Intro-Concurrency-&-Parallelism/assets/414px-Dual_Core_Generic.svg.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Make-School-Courses/MOB-2.3-Concurrency-Parallelism-in-iOS/0ae12a6aa027257fa2f2d34fb98a32d941586347/Lessons/01-Intro-Concurrency-&-Parallelism/assets/414px-Dual_Core_Generic.svg.png
--------------------------------------------------------------------------------
/Lessons/01-Intro-Concurrency-&-Parallelism/assets/Figure_4.4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Make-School-Courses/MOB-2.3-Concurrency-Parallelism-in-iOS/0ae12a6aa027257fa2f2d34fb98a32d941586347/Lessons/01-Intro-Concurrency-&-Parallelism/assets/Figure_4.4.png
--------------------------------------------------------------------------------
/Lessons/01-Intro-Concurrency-&-Parallelism/assets/Threads(solution).playground/Contents.swift:
--------------------------------------------------------------------------------
1 | //: Playground - noun: a place where people can play
2 |
3 | import Foundation
4 | import PlaygroundSupport
5 |
6 | PlaygroundPage.current.needsIndefiniteExecution = true
7 |
8 | let calculation = {
9 | for i in 0...100 {
10 | print(i)
11 | }
12 | }
13 |
14 | let thread = Thread {
15 | print("On thread: \(Thread.current) doing work")
16 | calculation()
17 | }
18 |
19 | print("On thread: \(Thread.current) doing nothing")
20 | thread.name = "Background Thread"
21 | thread.qualityOfService = .userInitiated
22 |
23 | thread.start()
24 |
--------------------------------------------------------------------------------
/Lessons/01-Intro-Concurrency-&-Parallelism/assets/Threads(solution).playground/contents.xcplayground:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/Lessons/01-Intro-Concurrency-&-Parallelism/assets/Threads(solution).playground/playground.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/Lessons/01-Intro-Concurrency-&-Parallelism/assets/Threads(solution).playground/playground.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/Lessons/01-Intro-Concurrency-&-Parallelism/assets/Threads(solution).playground/playground.xcworkspace/xcuserdata/gordoneliel.xcuserdatad/UserInterfaceState.xcuserstate:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Make-School-Courses/MOB-2.3-Concurrency-Parallelism-in-iOS/0ae12a6aa027257fa2f2d34fb98a32d941586347/Lessons/01-Intro-Concurrency-&-Parallelism/assets/Threads(solution).playground/playground.xcworkspace/xcuserdata/gordoneliel.xcuserdatad/UserInterfaceState.xcuserstate
--------------------------------------------------------------------------------
/Lessons/01-Intro-Concurrency-&-Parallelism/assets/Threads(solution).playground/playground.xcworkspace/xcuserdata/thomas_vandegriff.xcuserdatad/UserInterfaceState.xcuserstate:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Make-School-Courses/MOB-2.3-Concurrency-Parallelism-in-iOS/0ae12a6aa027257fa2f2d34fb98a32d941586347/Lessons/01-Intro-Concurrency-&-Parallelism/assets/Threads(solution).playground/playground.xcworkspace/xcuserdata/thomas_vandegriff.xcuserdatad/UserInterfaceState.xcuserstate
--------------------------------------------------------------------------------
/Lessons/01-Intro-Concurrency-&-Parallelism/assets/Threads(solution).playground/timeline.xctimeline:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/Lessons/01-Intro-Concurrency-&-Parallelism/assets/Threads.playground.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Make-School-Courses/MOB-2.3-Concurrency-Parallelism-in-iOS/0ae12a6aa027257fa2f2d34fb98a32d941586347/Lessons/01-Intro-Concurrency-&-Parallelism/assets/Threads.playground.zip
--------------------------------------------------------------------------------
/Lessons/01-Intro-Concurrency-&-Parallelism/assets/Threads.playground/Contents.swift:
--------------------------------------------------------------------------------
1 | //: Playground - noun: a place where people can play
2 |
3 | import Foundation
4 | import PlaygroundSupport
5 |
6 | PlaygroundPage.current.needsIndefiniteExecution = true
7 |
8 | let calculation = {
9 | for i in 0...100 {
10 | print(i)
11 | }
12 | }
13 |
14 | let thread = Thread {
15 |
16 | //TODO: What must the thread do here to match the expected output listed below?
17 | }
18 |
19 | print("On thread: \(Thread.current) doing nothing")
20 | //TODO: Give new thread its proper name, as in expected output...
21 | thread.qualityOfService = .userInitiated
22 |
23 | thread.start()
24 |
25 | /* EXPECTED OUTPUT:
26 | On thread: {number = 1, name = main} doing nothing
27 | On thread: {number = 3, name = Background Thread} doing work
28 | 0
29 | 1
30 | 2
31 | 3
32 | 4
33 | 5
34 | 6
35 | 7
36 | 8
37 | 9
38 | 10
39 | 11
40 | ...
41 | 100
42 | */
43 |
--------------------------------------------------------------------------------
/Lessons/01-Intro-Concurrency-&-Parallelism/assets/Threads.playground/contents.xcplayground:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/Lessons/01-Intro-Concurrency-&-Parallelism/assets/Threads.playground/playground.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/Lessons/01-Intro-Concurrency-&-Parallelism/assets/Threads.playground/playground.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/Lessons/01-Intro-Concurrency-&-Parallelism/assets/Threads.playground/playground.xcworkspace/xcuserdata/adrianagonzalezmartinez.xcuserdatad/UserInterfaceState.xcuserstate:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Make-School-Courses/MOB-2.3-Concurrency-Parallelism-in-iOS/0ae12a6aa027257fa2f2d34fb98a32d941586347/Lessons/01-Intro-Concurrency-&-Parallelism/assets/Threads.playground/playground.xcworkspace/xcuserdata/adrianagonzalezmartinez.xcuserdatad/UserInterfaceState.xcuserstate
--------------------------------------------------------------------------------
/Lessons/01-Intro-Concurrency-&-Parallelism/assets/Threads.playground/playground.xcworkspace/xcuserdata/gordoneliel.xcuserdatad/UserInterfaceState.xcuserstate:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Make-School-Courses/MOB-2.3-Concurrency-Parallelism-in-iOS/0ae12a6aa027257fa2f2d34fb98a32d941586347/Lessons/01-Intro-Concurrency-&-Parallelism/assets/Threads.playground/playground.xcworkspace/xcuserdata/gordoneliel.xcuserdatad/UserInterfaceState.xcuserstate
--------------------------------------------------------------------------------
/Lessons/01-Intro-Concurrency-&-Parallelism/assets/Threads.playground/playground.xcworkspace/xcuserdata/thomas_vandegriff.xcuserdatad/UserInterfaceState.xcuserstate:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Make-School-Courses/MOB-2.3-Concurrency-Parallelism-in-iOS/0ae12a6aa027257fa2f2d34fb98a32d941586347/Lessons/01-Intro-Concurrency-&-Parallelism/assets/Threads.playground/playground.xcworkspace/xcuserdata/thomas_vandegriff.xcuserdatad/UserInterfaceState.xcuserstate
--------------------------------------------------------------------------------
/Lessons/01-Intro-Concurrency-&-Parallelism/assets/concurrency.key:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Make-School-Courses/MOB-2.3-Concurrency-Parallelism-in-iOS/0ae12a6aa027257fa2f2d34fb98a32d941586347/Lessons/01-Intro-Concurrency-&-Parallelism/assets/concurrency.key
--------------------------------------------------------------------------------
/Lessons/01-Intro-Concurrency-&-Parallelism/assets/figure_4.3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Make-School-Courses/MOB-2.3-Concurrency-Parallelism-in-iOS/0ae12a6aa027257fa2f2d34fb98a32d941586347/Lessons/01-Intro-Concurrency-&-Parallelism/assets/figure_4.3.png
--------------------------------------------------------------------------------
/Lessons/01-Intro-Concurrency-&-Parallelism/assets/iOS_runtime_process.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Make-School-Courses/MOB-2.3-Concurrency-Parallelism-in-iOS/0ae12a6aa027257fa2f2d34fb98a32d941586347/Lessons/01-Intro-Concurrency-&-Parallelism/assets/iOS_runtime_process.png
--------------------------------------------------------------------------------
/Lessons/02-Grand-Central_Dispatch-Pt1/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Make-School-Courses/MOB-2.3-Concurrency-Parallelism-in-iOS/0ae12a6aa027257fa2f2d34fb98a32d941586347/Lessons/02-Grand-Central_Dispatch-Pt1/.DS_Store
--------------------------------------------------------------------------------
/Lessons/02-Grand-Central_Dispatch-Pt1/assets/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Make-School-Courses/MOB-2.3-Concurrency-Parallelism-in-iOS/0ae12a6aa027257fa2f2d34fb98a32d941586347/Lessons/02-Grand-Central_Dispatch-Pt1/assets/.DS_Store
--------------------------------------------------------------------------------
/Lessons/02-Grand-Central_Dispatch-Pt1/assets/GCDPlay.playground.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Make-School-Courses/MOB-2.3-Concurrency-Parallelism-in-iOS/0ae12a6aa027257fa2f2d34fb98a32d941586347/Lessons/02-Grand-Central_Dispatch-Pt1/assets/GCDPlay.playground.zip
--------------------------------------------------------------------------------
/Lessons/02-Grand-Central_Dispatch-Pt1/assets/GCDPlay.playground/Async Queue.xcplaygroundpage/Contents.swift:
--------------------------------------------------------------------------------
1 | //: [Previous](@previous)
2 |
3 | import Foundation
4 |
5 |
6 | let queue = DispatchQueue(label: "com.makeschool.queue")
7 |
8 | queue.sync {
9 | for i in 0..<10 {
10 | print("🍎 ", i)
11 | }
12 | }
13 |
14 | for i in 100..<110 {
15 | print("🐳 ", i)
16 | }
17 |
18 |
19 | //: [Next](@next)
20 |
--------------------------------------------------------------------------------
/Lessons/02-Grand-Central_Dispatch-Pt1/assets/GCDPlay.playground/AsyncBackgroundAndUtility.xcplaygroundpage/Contents.swift:
--------------------------------------------------------------------------------
1 | //: [Previous](@previous)
2 |
3 | import Foundation
4 |
5 | let queue1 = DispatchQueue(label: "com.makeschool.queue1", qos: .userInitiated)
6 | let queue2 = DispatchQueue(label: "com.makeschool.queue2", qos: .utility)
7 |
8 | queue1.async {
9 | for i in 0..<10 {
10 | print("🍎 ", i)
11 | }
12 | }
13 |
14 | queue2.async {
15 | for i in 0..<10 {
16 | print("🐳 ", i)
17 | }
18 | }
19 |
20 |
21 | //: [Next](@next)
22 |
--------------------------------------------------------------------------------
/Lessons/02-Grand-Central_Dispatch-Pt1/assets/GCDPlay.playground/Pages/Async Queue.xcplaygroundpage/Contents.swift:
--------------------------------------------------------------------------------
1 | //: [Previous](@previous)
2 |
3 | import Foundation
4 |
5 |
6 | let queue = DispatchQueue(label: "com.makeschool.queue")
7 |
8 | queue.async {
9 | for i in 0..<10 {
10 | print("🍎 ", i)
11 | }
12 | }
13 |
14 | for i in 100..<110 {
15 | print("🐳 ", i)
16 | }
17 |
18 |
19 | //: [Next](@next)
20 |
--------------------------------------------------------------------------------
/Lessons/02-Grand-Central_Dispatch-Pt1/assets/GCDPlay.playground/Pages/AsyncBackgroundAndUtility.xcplaygroundpage/Contents.swift:
--------------------------------------------------------------------------------
1 | //: [Previous](@previous)
2 |
3 | import Foundation
4 | import PlaygroundSupport
5 |
6 | PlaygroundPage.current.needsIndefiniteExecution = true
7 |
8 | let queue1 = DispatchQueue(label: "com.makeschool.queue1", qos: .background)
9 | let queue2 = DispatchQueue(label: "com.makeschool.queue2", qos: .utility)
10 |
11 | queue1.async {
12 | for i in 0..<10 {
13 | print("🍎 ", i)
14 | }
15 | }
16 |
17 | queue2.async {
18 | for i in 100..<110 {
19 | print("🐳 ", i)
20 | }
21 | }
22 |
23 |
24 | //: [Next](@next)
25 |
--------------------------------------------------------------------------------
/Lessons/02-Grand-Central_Dispatch-Pt1/assets/GCDPlay.playground/Pages/AsyncUserInitiated.xcplaygroundpage/Contents.swift:
--------------------------------------------------------------------------------
1 | //: [Previous](@previous)
2 |
3 | import Foundation
4 |
5 | let queue1 = DispatchQueue(label: "com.makeschool.queue1", qos: .userInitiated)
6 | let queue2 = DispatchQueue(label: "com.makeschool.queue2", qos: .userInitiated)
7 |
8 | queue1.async {
9 | for i in 0..<10 {
10 | print("🍎 ", i)
11 | }
12 | }
13 |
14 | queue2.async {
15 | for i in 100..<110 {
16 | print("🐳 ", i)
17 | }
18 | }
19 |
20 |
21 | //: [Next](@next)
22 |
--------------------------------------------------------------------------------
/Lessons/02-Grand-Central_Dispatch-Pt1/assets/GCDPlay.playground/Pages/AsyncUserInitiatedAndUtility.xcplaygroundpage/Contents.swift:
--------------------------------------------------------------------------------
1 | //: [Previous](@previous)
2 |
3 | import Foundation
4 |
5 | let queue1 = DispatchQueue(label: "com.makeschool.queue1", qos: .userInitiated)
6 | let queue2 = DispatchQueue(label: "com.makeschool.queue2", qos: .utility)
7 |
8 | queue1.async {
9 | for i in 0..<10 {
10 | print("🍎 ", i)
11 | }
12 | }
13 |
14 | queue2.async {
15 | for i in 100..<110 {
16 | print("🐳 ", i)
17 | }
18 | }
19 |
20 |
21 | //: [Next](@next)
22 |
--------------------------------------------------------------------------------
/Lessons/02-Grand-Central_Dispatch-Pt1/assets/GCDPlay.playground/Pages/AsyncUserInitiatedAndUtitlityAndMain.xcplaygroundpage/Contents.swift:
--------------------------------------------------------------------------------
1 | //: Playground - noun: a place where people can play
2 |
3 | import UIKit
4 |
5 | let queue1 = DispatchQueue(label: "com.makeschool.queue1", qos: .userInitiated)
6 | let queue2 = DispatchQueue(label: "com.makeschool.queue2", qos: .utility)
7 |
8 | queue1.async {
9 | for i in 0..<10 {
10 | print("🍎 ", i)
11 | }
12 | }
13 | queue2.async {
14 | for i in 100..<110 {
15 | print("🐳 ", i)
16 | }
17 | }
18 |
19 | for i in 100..<110 {
20 | print("🍑 ", i)
21 | }
22 |
23 | //: [Next](@next)
24 |
--------------------------------------------------------------------------------
/Lessons/02-Grand-Central_Dispatch-Pt1/assets/GCDPlay.playground/Pages/Concurrent.xcplaygroundpage/Contents.swift:
--------------------------------------------------------------------------------
1 | //: [Previous](@previous)
2 |
3 | import Foundation
4 |
5 | let queue = DispatchQueue(label: "sample.concurrent", qos: .utility, attributes: .concurrent)
6 |
7 | queue.async {
8 | for i in 0..<10 {
9 | print("🍎 ", i)
10 | }
11 | }
12 | queue.async {
13 | for i in 100..<110 {
14 | print("🐳 ", i)
15 | }
16 | }
17 |
18 | queue.async {
19 | for i in 1000..<1010 {
20 | print("🍑 ", i)
21 | }
22 | }
23 |
24 | //: [Next](@next)
25 |
--------------------------------------------------------------------------------
/Lessons/02-Grand-Central_Dispatch-Pt1/assets/GCDPlay.playground/Pages/DispatchQueueSync*.xcplaygroundpage/Contents.swift:
--------------------------------------------------------------------------------
1 | //: [Previous](@previous)
2 |
3 | import Foundation
4 | import UIKit
5 |
6 | let queue = DispatchQueue(
7 | label: "sample.concurrent",
8 | qos: .userInitiated,
9 | attributes: .concurrent
10 | )
11 |
12 | queue.async {
13 | print("I am \(Thread.current) an async thread")
14 | print(45)
15 | }
16 |
17 | queue.async {
18 | print("I am \(Thread.current) a sync thread")
19 | Thread.sleep(forTimeInterval: 10)
20 | }
21 |
22 | print("I am on the main thread - \(Thread.current)")
23 |
24 | //: [Next](@next)
25 |
--------------------------------------------------------------------------------
/Lessons/02-Grand-Central_Dispatch-Pt1/assets/GCDPlay.playground/Pages/SameQueueAsync.xcplaygroundpage/Contents.swift:
--------------------------------------------------------------------------------
1 | //: Playground - noun: a place where people can play
2 |
3 | import UIKit
4 |
5 | // Same (serial) queue of execution
6 | let queue = DispatchQueue(label: "com.makeschool.queue1", qos: .utility)
7 |
8 | queue.async {
9 | for i in 0..<10 {
10 | print("🍎 ", i)
11 | }
12 | }
13 | queue.async {
14 | for i in 100..<110 {
15 | print("🐳 ", i)
16 | }
17 | }
18 |
19 | queue.async {
20 | for i in 1000..<1010 {
21 | print("🍑 ", i)
22 | }
23 | }
24 |
25 | //: [Next](@next)
26 |
--------------------------------------------------------------------------------
/Lessons/02-Grand-Central_Dispatch-Pt1/assets/GCDPlay.playground/Pages/Sync Queue.xcplaygroundpage/Contents.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 |
3 | let queue = DispatchQueue(label: "com.makeschool.queue")
4 |
5 | queue.sync {
6 | for i in 0..<10 {
7 | print("🍎 ", i)
8 | }
9 | }
10 |
11 | for i in 100..<110 {
12 | print("🐳 ", i)
13 | }
14 |
15 |
--------------------------------------------------------------------------------
/Lessons/02-Grand-Central_Dispatch-Pt1/assets/GCDPlay.playground/contents.xcplayground:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/Lessons/02-Grand-Central_Dispatch-Pt1/assets/GCDPlay.playground/playground.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/Lessons/02-Grand-Central_Dispatch-Pt1/assets/GCDPlay.playground/playground.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/Lessons/02-Grand-Central_Dispatch-Pt1/assets/GCDPlay.playground/playground.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | BuildSystemType
6 | Latest
7 |
8 |
9 |
--------------------------------------------------------------------------------
/Lessons/02-Grand-Central_Dispatch-Pt1/assets/GCDPlay.playground/playground.xcworkspace/xcuserdata/adrianagonzalezmartinez.xcuserdatad/UserInterfaceState.xcuserstate:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Make-School-Courses/MOB-2.3-Concurrency-Parallelism-in-iOS/0ae12a6aa027257fa2f2d34fb98a32d941586347/Lessons/02-Grand-Central_Dispatch-Pt1/assets/GCDPlay.playground/playground.xcworkspace/xcuserdata/adrianagonzalezmartinez.xcuserdatad/UserInterfaceState.xcuserstate
--------------------------------------------------------------------------------
/Lessons/02-Grand-Central_Dispatch-Pt1/assets/GCDPlay.playground/playground.xcworkspace/xcuserdata/gordoneliel.xcuserdatad/UserInterfaceState.xcuserstate:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Make-School-Courses/MOB-2.3-Concurrency-Parallelism-in-iOS/0ae12a6aa027257fa2f2d34fb98a32d941586347/Lessons/02-Grand-Central_Dispatch-Pt1/assets/GCDPlay.playground/playground.xcworkspace/xcuserdata/gordoneliel.xcuserdatad/UserInterfaceState.xcuserstate
--------------------------------------------------------------------------------
/Lessons/02-Grand-Central_Dispatch-Pt1/assets/GCDPlay.playground/playground.xcworkspace/xcuserdata/gordoneliel.xcuserdatad/WorkspaceSettings.xcsettings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | BuildLocationStyle
6 | UseAppPreferences
7 | BuildSystemType
8 | Latest
9 | CustomBuildLocationType
10 | RelativeToDerivedData
11 | DerivedDataLocationStyle
12 | Default
13 | EnabledFullIndexStoreVisibility
14 |
15 | IssueFilterStyle
16 | ShowActiveSchemeOnly
17 | LiveSourceIssuesEnabled
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/Lessons/02-Grand-Central_Dispatch-Pt1/assets/GCDPlay.playground/playground.xcworkspace/xcuserdata/thomas_vandegriff.xcuserdatad/UserInterfaceState.xcuserstate:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Make-School-Courses/MOB-2.3-Concurrency-Parallelism-in-iOS/0ae12a6aa027257fa2f2d34fb98a32d941586347/Lessons/02-Grand-Central_Dispatch-Pt1/assets/GCDPlay.playground/playground.xcworkspace/xcuserdata/thomas_vandegriff.xcuserdatad/UserInterfaceState.xcuserstate
--------------------------------------------------------------------------------
/Lessons/02-Grand-Central_Dispatch-Pt1/assets/SIMD.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Make-School-Courses/MOB-2.3-Concurrency-Parallelism-in-iOS/0ae12a6aa027257fa2f2d34fb98a32d941586347/Lessons/02-Grand-Central_Dispatch-Pt1/assets/SIMD.png
--------------------------------------------------------------------------------
/Lessons/02-Grand-Central_Dispatch-Pt1/assets/activity_diag_template.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Make-School-Courses/MOB-2.3-Concurrency-Parallelism-in-iOS/0ae12a6aa027257fa2f2d34fb98a32d941586347/Lessons/02-Grand-Central_Dispatch-Pt1/assets/activity_diag_template.png
--------------------------------------------------------------------------------
/Lessons/02-Grand-Central_Dispatch-Pt1/assets/activity_diag_template1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Make-School-Courses/MOB-2.3-Concurrency-Parallelism-in-iOS/0ae12a6aa027257fa2f2d34fb98a32d941586347/Lessons/02-Grand-Central_Dispatch-Pt1/assets/activity_diag_template1.png
--------------------------------------------------------------------------------
/Lessons/02-Grand-Central_Dispatch-Pt1/assets/asynchronous.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Make-School-Courses/MOB-2.3-Concurrency-Parallelism-in-iOS/0ae12a6aa027257fa2f2d34fb98a32d941586347/Lessons/02-Grand-Central_Dispatch-Pt1/assets/asynchronous.png
--------------------------------------------------------------------------------
/Lessons/02-Grand-Central_Dispatch-Pt1/assets/deadlock.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Make-School-Courses/MOB-2.3-Concurrency-Parallelism-in-iOS/0ae12a6aa027257fa2f2d34fb98a32d941586347/Lessons/02-Grand-Central_Dispatch-Pt1/assets/deadlock.png
--------------------------------------------------------------------------------
/Lessons/02-Grand-Central_Dispatch-Pt1/assets/iOS_runtime_process.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Make-School-Courses/MOB-2.3-Concurrency-Parallelism-in-iOS/0ae12a6aa027257fa2f2d34fb98a32d941586347/Lessons/02-Grand-Central_Dispatch-Pt1/assets/iOS_runtime_process.png
--------------------------------------------------------------------------------
/Lessons/02-Grand-Central_Dispatch-Pt1/assets/iOS_runtime_process_with-queues.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Make-School-Courses/MOB-2.3-Concurrency-Parallelism-in-iOS/0ae12a6aa027257fa2f2d34fb98a32d941586347/Lessons/02-Grand-Central_Dispatch-Pt1/assets/iOS_runtime_process_with-queues.png
--------------------------------------------------------------------------------
/Lessons/02-Grand-Central_Dispatch-Pt1/assets/queue-line.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Make-School-Courses/MOB-2.3-Concurrency-Parallelism-in-iOS/0ae12a6aa027257fa2f2d34fb98a32d941586347/Lessons/02-Grand-Central_Dispatch-Pt1/assets/queue-line.png
--------------------------------------------------------------------------------
/Lessons/02-Grand-Central_Dispatch-Pt1/assets/sync_deadlock_base.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Make-School-Courses/MOB-2.3-Concurrency-Parallelism-in-iOS/0ae12a6aa027257fa2f2d34fb98a32d941586347/Lessons/02-Grand-Central_Dispatch-Pt1/assets/sync_deadlock_base.png
--------------------------------------------------------------------------------
/Lessons/02-Grand-Central_Dispatch-Pt1/assets/synchronous.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Make-School-Courses/MOB-2.3-Concurrency-Parallelism-in-iOS/0ae12a6aa027257fa2f2d34fb98a32d941586347/Lessons/02-Grand-Central_Dispatch-Pt1/assets/synchronous.png
--------------------------------------------------------------------------------
/Lessons/02-Grand-Central_Dispatch-Pt1/assets/synchronous2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Make-School-Courses/MOB-2.3-Concurrency-Parallelism-in-iOS/0ae12a6aa027257fa2f2d34fb98a32d941586347/Lessons/02-Grand-Central_Dispatch-Pt1/assets/synchronous2.png
--------------------------------------------------------------------------------
/Lessons/02-Grand-Central_Dispatch-Pt1/assets/thread_pool.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Make-School-Courses/MOB-2.3-Concurrency-Parallelism-in-iOS/0ae12a6aa027257fa2f2d34fb98a32d941586347/Lessons/02-Grand-Central_Dispatch-Pt1/assets/thread_pool.png
--------------------------------------------------------------------------------
/Lessons/02-Grand-Central_Dispatch-Pt1/assets/thread_pool1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Make-School-Courses/MOB-2.3-Concurrency-Parallelism-in-iOS/0ae12a6aa027257fa2f2d34fb98a32d941586347/Lessons/02-Grand-Central_Dispatch-Pt1/assets/thread_pool1.png
--------------------------------------------------------------------------------
/Lessons/02-Grand-Central_Dispatch-Pt1/bkups_(delete_when_not_needed)/Readme copy.md:
--------------------------------------------------------------------------------
1 | # Grand Central Dispatch
2 |
3 |
10 |
11 | ## Minute-by-Minute [OPTIONAL]
12 |
13 | | **Elapsed** | **Time** | **Activity** |
14 | | ----------- | --------- | ------------------------- |
15 | | 0:00 | 0:05 | Objectives |
16 | | 0:05 | 0:15 | Overview |
17 | | 0:20 | 0:45 | In Class Activity I |
18 | | 1:05 | 0:10 | BREAK |
19 | | 1:15 | 0:45 | In Class Activity II |
20 | | TOTAL | 2:00 | |
21 |
22 |
23 |
24 | ## Learning Objectives (5 min)
25 |
26 | 1. Identify and describe
27 | 1. Define
28 | 1. Design
29 | 1. Implement
30 |
31 | ## Initial Exercise (15 min)
32 |
33 |
34 |
35 |
36 |
37 |
38 |
47 |
48 |
49 |
50 |
56 |
57 | ## Overview/TT I (20 min)
58 |
59 | ### Topics for this Session
60 |
61 | - GCD vs Operations
62 | - Dispatch Queues
63 | - FIFO
64 | - Serial vs Concurrent
65 | - QoS Priorities
66 | - Default Queues
67 | - Custom Queues
68 | - The Main Queue
69 | - Synchronous vs Asynchronous
70 |
71 | ### GCD and Operations (cont'd)
72 |
73 | In Lesson 1, we introduced the two Apple-provided APIs you use in iOS to manage concurrent tasks *without* working with threads *directly*: **Grand Central Dispatch (GCD)** and **Operations.**
74 |
75 | Before we dive deeper into GCD, let's quickly compare the two to begin your understanding of when and how to use them:
76 |
77 | | Grand Central Dispatch | Operations |
78 | | ------------- | ------------- |
79 | | A *lightweight* way to represent units of work that are going to be executed concurrently. GCD uses **closures** to handle what runs on another thread. | Operations are **objects** that encapsulate data and functionality. Operations add a little *extra development overhead* compared to GCD. |
80 | | The system takes care of scheduling for you. Adding dependencies, cancelling or suspending code blocks is labor intensive | Allow for greater control over the submitted tasks, including some control over scheduling through adding dependencies among various operations and can re-use, cancel or suspend them. |
81 | | GCD is good to use for simple, common tasks that need to be run only once and in the background. | Operations make it easier to do complex tasks. Use them when you need (a) task reusability, (b) considerable communication between tasks, or (c) to closely monitor task execution. |
82 |
83 | Apple recommends using the API with the "highest-level of abstraction" (which is Operations), though most developers use a combination of both APIs.
84 |
85 | And because Operations are build on top of GCD, it is important to master the lower-level API first...
86 |
87 | > *Note: Where Swift uses closures (functions) to handle the code that runs on another thread, C#, Typescript, Python, JavaScript and other languages use the the more common Async/Await pattern. The original plans for Swift 5.0 included adding the Async/Await pattern, but this was removed from the Swift specification until some future release.*
88 |
89 | ### Why use GCD?
90 |
91 | GCD's design improves simplicity, portability and performance.
92 |
93 | - It can help you __*improve your app’s responsiveness*__ by deferring computationally expensive tasks from the foreground (`main` thread) to the background (non-UI threads).
94 |
95 | - It __*simplifies__* the creation and the execution of asynchronous or synchronous tasks.
96 |
97 | - It’s a concurrency model that is __*much easier to work with__* than locks and threads.
98 |
99 | Though GCD still uses threads in its implementation, developers do not have to manage threads themselves.
100 |
101 | GCD's tasks are so lightweight to enqueue that Apple, in its 2009 technical brief on GCD, stated that "only 15 instructions are required for implementation, whereas creating traditional threads could require several hundred instructions." 1
102 |
103 | ### What does GCD do?
104 |
105 | GCD is Apple's implementation of C's `libdispatch` library. It runs directly in the UNIX layer of iOS.
106 |
107 |
108 |
109 | GCD works by allowing specific __*tasks*__ — functions or closures — that can be run in parallel to be __*queued up*__ for execution and, depending on availability of processing resources, __*schedule*__ them to execute on any of the available processor cores (referred to as "routing" by Apple). 1
110 |
111 | GCD abstracts the notion of threads, and exposes __*dispatch queues*__ to handle __*work items*__ (*work items* are blocks 2 of code that you want to execute). These tasks are assigned (dispatched) to a dispatch queue, which processes them in a __*First-In-First-Out (FIFO)*__ order.
112 |
113 | Allowing the `libdispatch` library and the operating system to manage threads means developers have much fewer lines of code to write and less to debug; and the library can optimize thread management behind the scenes much more efficiently than a developer.
114 |
115 | > 2 Note: Apple's documentation sometimes refers to a `block` in lieu of a `closure` because `block` was the name used in Objective-C. In the context of concurrency in iOS, you can consider `block` and `closure` interchangeable> [action]
116 |
117 | *Sources include:*
118 | - wikipedia
119 | - Apple docs
120 |
121 | ### Threads, Tasks & DispatchQueues in GCD
122 |
123 | Grand Central Dispatch still uses threads at a low level but abstracts them away from the developer.
124 |
125 | You work with threads by creating `DispatchQueues`.
126 |
127 |
128 |
129 |
130 |
131 | __*DispatchQueues*__
132 |
133 | A `DispatchQueue` is an object that manages the execution of tasks serially or concurrently on your app's `main` thread or on a `background thread`.
134 |
135 | 
136 | Photo credit: FreeImages.com/Sigurd Decroos
137 |
138 | DispatchQueues:
139 | - maintain a queue of tasks and execute these tasks, either serially or concurrently, in their turn.
140 | - hide all thread management related activities. (You can configure a queue, but you won’t interact directly with a thread.)
141 | - are *thread safe*: They can be accessed from different threads simultaneously without locking. (Developers can use `DispatchQueues` to make their own code thread safe.)
142 | - are *FIFO* 3 queues.
143 |
144 | Except for the dispatch queue representing your app's `main` thread, the system makes no guarantees about which thread it uses to execute a task.
145 |
146 | Work submitted to dispatch queues executes on a pool of threads managed by the system.
147 |
148 | When you create a queue, the OS will potentially create and assign one or more threads to the queue. If existing threads are available in the pool, they can be reused; if not, then the OS will create them as necessary.
149 |
150 | __*Thread Pools*__
151 | Thread creation and destruction are expensive processes. Instead of creating a new thread whenever a task is to be executed, then destroying it when the task finishes, available threads are taken from a thread pool ([Thread Pool pattern](https://en.wikipedia.org/wiki/Thread_pool)).
152 |
153 | 
154 |
155 | *A sample thread pool (green boxes) with waiting tasks (blue) and completed tasks (yellow)*
156 | *Source:* https://en.wikipedia.org/wiki/Thread_pool
157 |
158 |
159 |
160 |
161 |
162 | __*Tasks*__
163 |
164 |
165 |
166 | A task can be expressed either as a function or as a "block" of code (eg, a closure). Tasks encapsulate code and data into a single object in
167 |
168 |
169 | Blocks are an extension to the syntax of C, C++, and Objective-C programming languages that encapsulate code and data into a single object in a way similar to a closure.[11] GCD can still be used in environments where blocks are not available.[15]
170 |
171 |
172 | A task in Grand Central Dispatch can be used either to create a work item that is placed in a queue or assign it to an event source. If a task is assigned to an event source, then a work unit is made from the block or function when the event triggers, and the work unit is placed in an appropriate queue. This is described by Apple as more efficient than creating a thread whose sole purpose is to wait on a single event triggering.
173 |
174 |
175 |
176 | > 3 FIFO: First In, First Out — Tasks run in the order in which they are added to the queue — the first task in the queue will be the first to start. Though each block of code will be *started* in the order they were submitted, because more than one code block can be executed at the same time, the order in which tasks *finish* isn't guaranteed.
177 |
178 |
179 |
180 |
181 | , either anonymous code blocks or functions, — anonymous code blocks (closures) or functions —
182 |
183 |
184 |
185 | Dispatch queues are *FIFO* 3 queues to which your application can submit tasks in the form of block objects.
186 |
187 |
188 |
189 |
190 |
191 | ### Synchronous & Asynchronous Tasks
192 |
193 | Tasks placed into a queue can either run __*synchronously*__ or __*asynchronously.*__
194 |
195 | **Synchronous**
196 | Submits a work item for execution on the current queue and returns after that block finishes executing.
197 |
198 | your app will wait and block the current run loop until execution finishes before moving on to the next task
199 |
200 |
201 | A synchronous function returns control to the caller after the task is completed.
202 |
203 | An asynchronous function returns immediately, ordering the task to be done but not waiting for it. Thus, an asynchronous function does not block the current thread of execution from proceeding on to the next function.
204 |
205 |
206 | 
207 |
208 |
209 | **Asynchronous**
210 |
211 | Schedules a work item for immediate execution, and returns immediately.
212 |
213 | a task that is run asynchronously will start, but return execution to your app immediately. This way, the app is free to run other tasks while the first one is executing.
214 |
215 | Asynchronous tasks are started by one thread but actually run on a different thread, taking advantage of additional processor resources to finish their work more quickly.
216 |
217 |
218 |
219 | 
220 |
221 |
222 |
223 |
224 | You schedule work items synchronously or asynchronously. When you schedule a work item synchronously, your code waits until that item finishes execution. When you schedule a work item asynchronously, your code continues executing while the work item runs elsewhere.
225 |
226 |
227 |
228 | ### The Main queue
229 |
230 |
231 |
232 | Important
233 | Attempting to synchronously execute a work item on the main queue results in deadlock.
234 |
235 |
236 |
237 |
238 |
239 |
240 |
241 | ## In Class Activity I (30 min)
242 |
243 | - I do, We do, You do
244 | - Reading & Discussion Questions in small groups
245 | - Draw a picture/diagram
246 | - Complete Challenges solo or in pair
247 | - Q&A about tutorials
248 | - Pair up and code review
249 | - Pair program
250 | - Formative assessment
251 | - Form into groups
252 | - etc (get creative :D)
253 |
254 | ## Overview/TT II (optional) (20 min)
255 |
256 |
257 | #### Serial Queues
258 |
259 | The library automatically creates several queues with different priority levels that execute several tasks concurrently, selecting the optimal number of tasks to run based on the operating environment.
260 |
261 | A client to the library may also create any number of serial queues, which execute tasks in the order they are submitted, one at a time.[12] Because a serial queue can only run one task at a time, each task submitted to the queue is critical with regard to the other tasks on the queue, and thus a serial queue can be used instead of a lock on a contended resource.
262 |
263 | #### concurrent queues
264 |
265 | - requires QoS Priority
266 |
267 | ##### QoS levels
268 |
269 |
270 | #### Default Queues
271 |
272 |
273 | #### Custom Queues
274 |
275 |
276 |
277 |
278 |
279 |
280 |
281 |
282 |
283 |
284 | #### Calling Sync on Current Queue
285 |
286 | < never call Sync on main queue >
287 |
288 |
289 | #### Calling xxxx
290 |
291 |
292 | When designing tasks for concurrent execution, do not call methods that block the current thread of execution. When a task scheduled by a concurrent dispatch queue blocks a thread, the system creates additional threads to run other queued concurrent tasks. If too many tasks block, the system may run out of threads for your app.
293 |
294 | Another way that apps consume too many threads is by creating too many private concurrent dispatch queues. Because each dispatch queue consumes thread resources, creating additional concurrent dispatch queues exacerbates the thread consumption problem. Instead of creating private concurrent queues, submit tasks to one of the global concurrent dispatch queues. For serial tasks, set the target of your serial queue to one of the global concurrent queues. That way, you can maintain the serialized behavior of the queue while minimizing the number of separate queues creating threads.
295 |
296 |
297 | https://developer.apple.com/documentation/dispatch/dispatchqueue
298 |
299 |
300 |
303 |
304 |
305 |
306 | ## In Class Activity II (optional) (30 min)
307 |
308 |
311 |
312 |
313 |
314 | ## After Class
315 | 1. Research:
316 | - `DispatchObject`
317 | -
318 |
319 | 2. Assignment:
320 | -
321 |
322 |
323 |
324 |
325 | ## Wrap Up (5 min)
326 |
327 | - Continue working on your current tutorial
328 | - Complete reading
329 | - Complete challenges
330 |
331 | ## Additional Resources
332 |
333 | 1. [Slides]()
334 | 2. [Grand_Central_Dispatch - wikipedia](https://en.wikipedia.org/wiki/Grand_Central_Dispatch) 1
335 | 3. [Async/await - wikipedia](https://en.wikipedia.org/wiki/Async/await)
336 | 4. [Coroutine - wikipedia](https://en.wikipedia.org/wiki/Coroutine)
337 | 5. []()
338 |
339 | 8.
340 |
341 |
342 |
343 |
344 | https://gist.github.com/lattner/429b9070918248274f25b714dcfc7619
345 |
346 |
347 | https://developer.apple.com/documentation/dispatch/dispatchqueue
348 |
--------------------------------------------------------------------------------
/Lessons/02-Grand-Central_Dispatch-Pt1/bkups_(delete_when_not_needed)/Readme.md:
--------------------------------------------------------------------------------
1 | # GCD: Threads & Queues
2 |
3 |
4 |
5 |
12 |
13 | ## Minute-by-Minute [OPTIONAL]
14 |
15 | | **Elapsed** | **Time** | **Activity** |
16 | | ----------- | --------- | ------------------------- |
17 | | 0:00 | 0:05 | Objectives |
18 | | 0:05 | 0:15 | Overview |
19 | | 0:20 | 0:45 | In Class Activity I |
20 | | 1:05 | 0:10 | BREAK |
21 | | 1:15 | 0:45 | In Class Activity II |
22 | | TOTAL | 2:00 | |
23 |
24 |
25 |
26 | ## Learning Objectives (5 min)
27 |
28 | 1. Identify and describe
29 | 1. Define
30 | 1. Design
31 | 1. Implement
32 |
33 | ## Initial Exercise (15 min)
34 |
35 |
36 |
37 |
38 |
39 |
40 |
49 |
50 |
51 |
52 |
58 |
59 | ## Overview/TT I (20 min)
60 |
61 | ### Topics for this Session
62 |
63 | - GCD vs Operations
64 | - Dispatch Queues
65 | - FIFO
66 | - Serial vs Concurrent
67 | - QoS Priorities
68 | - Default Queues
69 | - Custom Queues
70 | - The Main Queue
71 | - Synchronous vs Asynchronous
72 |
73 | ### GCD and Operations (cont'd)
74 |
75 | In Lesson 1, we introduced the two Apple-provided APIs you use in iOS to manage concurrent tasks *without* working with threads *directly*: **Grand Central Dispatch (GCD)** and **Operations.**
76 |
77 | Before we dive deeper into GCD, let's quickly compare the two to begin your understanding of when and how to use them:
78 |
79 |
80 | | Grand Central Dispatch | Operations |
81 | | ------------- | ------------- |
82 | | A *lightweight* way to represent units of work that are going to be executed concurrently. GCD uses **closures** to handle what runs on another thread. | Operations are **objects** that encapsulate data and functionality. Operations add a little *extra development overhead* compared to GCD. |
83 | | The system takes care of scheduling for you. Adding dependencies, cancelling or suspending code blocks is labor intensive | Allow for greater control over the submitted tasks, including some control over scheduling through adding dependencies among various operations and can re-use, cancel or suspend them. |
84 | | GCD is good to use for simple, common tasks that need to be run only once and in the background. | Operations make it easier to do complex tasks. Use them when you need (a) task reusability, (b) considerable communication between tasks, or (c) to closely monitor task execution. |
85 |
86 | Apple recommends using the API with the "highest-level of abstraction" (which is Operations), though most developers use a combination of both APIs.
87 |
88 | And because Operations are build on top of GCD, it is important to master the lower-level API first...
89 |
90 | > *Note: Where Swift uses closures (functions) to handle the code that runs on another thread, C#, Typescript, Python, JavaScript and other languages use the the more common Async/Await pattern. The original plans for Swift 5.0 included adding the Async/Await pattern, but this was removed from the Swift specification until some future release.*
91 |
92 | ### Why use GCD?
93 |
94 | GCD's design improves simplicity, portability and performance.
95 |
96 | - It can help you __*improve your app’s responsiveness*__ by deferring computationally expensive tasks from the foreground (`main` thread) to the background (non-UI threads).
97 |
98 | - It __*simplifies__* the creation and the execution of asynchronous or synchronous tasks.
99 |
100 | - It’s a concurrency model that is __*much easier to work with__* than locks and threads.
101 |
102 | Though GCD still uses threads in its implementation, developers do not have to manage threads themselves.
103 |
104 | GCD's tasks are so lightweight to enqueue that Apple, in its 2009 technical brief on GCD, stated that "only 15 instructions are required for implementation, whereas creating traditional threads could require several hundred instructions." 1
105 |
106 | ### What does GCD do?
107 |
108 | GCD is Apple's implementation of C's `libdispatch` library. It runs directly in the UNIX layer of iOS.
109 |
110 |
111 |
112 | GCD works by allowing specific __*tasks*__ — functions or closures — that can be run in parallel to be __*queued up*__ for execution and, depending on availability of processing resources, __*schedule*__ them to execute on any of the available processor cores (referred to as "routing" by Apple). 1
113 |
114 | GCD abstracts the notion of threads, and exposes __*dispatch queues*__ to handle __*work items*__ (*work items* are blocks 2 of code that you want to execute). These tasks are assigned (dispatched) to a dispatch queue, which processes them in a __*First-In-First-Out (FIFO)*__ order.
115 |
116 | Allowing the `libdispatch` library and the operating system to manage threads means developers have much fewer lines of code to write and less to debug; and the library can optimize thread management behind the scenes much more efficiently than a developer.
117 |
118 | > 2 Note: Apple's documentation sometimes refers to a `block` in lieu of a `closure` because `block` was the name used in Objective-C. In the context of concurrency in iOS, you can consider `block` and `closure` interchangeable> [action]
119 |
120 | *Sources include:*
121 | - wikipedia
122 | - Apple docs
123 |
124 | ### Threads, Tasks & DispatchQueues in GCD
125 |
126 | Grand Central Dispatch still uses threads at a low level but abstracts them away from the developer.
127 |
128 | You work with threads by creating `DispatchQueues`.
129 |
130 | 
131 |
132 |
133 | Photo credit: FreeImages.com/Sigurd Decroos
134 |
135 |
136 |
137 | __*DispatchQueues*__
138 |
139 | A `DispatchQueue` is an object that manages the execution of tasks serially or concurrently on your app's `main` thread or on a `background thread`.
140 |
141 | DispatchQueues:
142 | - maintain a queue of tasks and execute these tasks, either serially or concurrently, in their turn.
143 | - hide all thread management related activities. (You can configure a queue, but you won’t interact directly with a thread.)
144 | - are *thread safe*: They can be accessed from different threads simultaneously without locking. (Developers can use `DispatchQueues` to make their own code thread safe.)
145 | - are *FIFO* 3 queues.
146 |
147 | Except for the dispatch queue representing your app's `main` thread, the system makes no guarantees about which thread it uses to execute a task.
148 |
149 | Work submitted to dispatch queues executes on a pool of threads managed by the system.
150 |
151 | When you create a queue, the OS will potentially create and assign one or more threads to the queue. If existing threads are available in the pool, they can be reused; if not, then the OS will create them as necessary.
152 |
153 | __*Thread Pools*__
154 | Thread creation and destruction are expensive processes. Instead of creating a new thread whenever a task is to be executed, then destroying it when the task finishes, available threads are taken from a thread pool ([Thread Pool pattern](https://en.wikipedia.org/wiki/Thread_pool)).
155 |
156 | 
157 |
158 | *A sample thread pool (green boxes) with waiting tasks (blue) and completed tasks (yellow)*
159 | *Source:* https://en.wikipedia.org/wiki/Thread_pool
160 |
161 |
162 |
163 |
164 |
165 | __*Tasks*__
166 |
167 |
168 |
169 | A task can be expressed either as a function or as a "block" of code (eg, a closure). Tasks encapsulate code and data into a single object in
170 |
171 |
172 | Blocks are an extension to the syntax of C, C++, and Objective-C programming languages that encapsulate code and data into a single object in a way similar to a closure.[11] GCD can still be used in environments where blocks are not available.[15]
173 |
174 |
175 | A task in Grand Central Dispatch can be used either to create a work item that is placed in a queue or assign it to an event source. If a task is assigned to an event source, then a work unit is made from the block or function when the event triggers, and the work unit is placed in an appropriate queue. This is described by Apple as more efficient than creating a thread whose sole purpose is to wait on a single event triggering.
176 |
177 |
178 |
179 | > 3 FIFO: First In, First Out — Tasks run in the order in which they are added to the queue — the first task in the queue will be the first to start. Though each block of code will be *started* in the order they were submitted, because more than one code block can be executed at the same time, the order in which tasks *finish* isn't guaranteed.
180 |
181 |
182 |
183 |
184 | , either anonymous code blocks or functions, — anonymous code blocks (closures) or functions —
185 |
186 |
187 |
188 | Dispatch queues are *FIFO* 3 queues to which your application can submit tasks in the form of block objects.
189 |
190 |
191 |
192 |
193 |
194 | ### Synchronous & Asynchronous Tasks
195 |
196 | Tasks placed into a queue can either run __*synchronously*__ or __*asynchronously.*__
197 |
198 | **Synchronous**
199 | Submits a work item for execution on the current queue and returns after that block finishes executing.
200 |
201 | your app will wait and block the current run loop until execution finishes before moving on to the next task
202 |
203 |
204 | A synchronous function returns control to the caller after the task is completed.
205 |
206 | An asynchronous function returns immediately, ordering the task to be done but not waiting for it. Thus, an asynchronous function does not block the current thread of execution from proceeding on to the next function.
207 |
208 |
209 | 
210 |
211 |
212 | **Asynchronous**
213 |
214 | Schedules a work item for immediate execution, and returns immediately.
215 |
216 | a task that is run asynchronously will start, but return execution to your app immediately. This way, the app is free to run other tasks while the first one is executing.
217 |
218 | Asynchronous tasks are started by one thread but actually run on a different thread, taking advantage of additional processor resources to finish their work more quickly.
219 |
220 |
221 |
222 | 
223 |
224 |
225 |
226 |
227 | You schedule work items synchronously or asynchronously. When you schedule a work item synchronously, your code waits until that item finishes execution. When you schedule a work item asynchronously, your code continues executing while the work item runs elsewhere.
228 |
229 |
230 |
231 | ### The Main queue
232 |
233 |
234 |
235 | Important
236 | Attempting to synchronously execute a work item on the main queue results in deadlock.
237 |
238 |
239 |
240 |
241 |
242 |
243 |
244 | ## In Class Activity I (30 min)
245 |
246 | - I do, We do, You do
247 | - Reading & Discussion Questions in small groups
248 | - Draw a picture/diagram
249 | - Complete Challenges solo or in pair
250 | - Q&A about tutorials
251 | - Pair up and code review
252 | - Pair program
253 | - Formative assessment
254 | - Form into groups
255 | - etc (get creative :D)
256 |
257 | ## Overview/TT II (optional) (20 min)
258 |
259 |
260 | #### Serial Queues
261 |
262 | The library automatically creates several queues with different priority levels that execute several tasks concurrently, selecting the optimal number of tasks to run based on the operating environment.
263 |
264 | A client to the library may also create any number of serial queues, which execute tasks in the order they are submitted, one at a time.[12] Because a serial queue can only run one task at a time, each task submitted to the queue is critical with regard to the other tasks on the queue, and thus a serial queue can be used instead of a lock on a contended resource.
265 |
266 | #### concurrent queues
267 |
268 | - requires QoS Priority
269 |
270 | ##### QoS levels
271 |
272 |
273 | #### Default Queues
274 |
275 |
276 | #### Custom Queues
277 |
278 |
279 |
280 |
281 |
282 |
283 |
284 |
285 |
286 |
287 | #### Calling Sync on Current Queue
288 |
289 | < never call Sync on main queue >
290 |
291 |
292 | #### Calling xxxx
293 |
294 |
295 | When designing tasks for concurrent execution, do not call methods that block the current thread of execution. When a task scheduled by a concurrent dispatch queue blocks a thread, the system creates additional threads to run other queued concurrent tasks. If too many tasks block, the system may run out of threads for your app.
296 |
297 | Another way that apps consume too many threads is by creating too many private concurrent dispatch queues. Because each dispatch queue consumes thread resources, creating additional concurrent dispatch queues exacerbates the thread consumption problem. Instead of creating private concurrent queues, submit tasks to one of the global concurrent dispatch queues. For serial tasks, set the target of your serial queue to one of the global concurrent queues. That way, you can maintain the serialized behavior of the queue while minimizing the number of separate queues creating threads.
298 |
299 |
300 | https://developer.apple.com/documentation/dispatch/dispatchqueue
301 |
302 |
303 |
306 |
307 |
308 |
309 | ## In Class Activity II (optional) (30 min)
310 |
311 |
314 |
315 |
316 |
317 | ## After Class
318 | 1. Research:
319 | - `DispatchObject`
320 | -
321 |
322 | 2. Assignment:
323 | -
324 |
325 |
326 |
327 |
328 | ## Wrap Up (5 min)
329 |
330 | - Continue working on your current tutorial
331 | - Complete reading
332 | - Complete challenges
333 |
334 | ## Additional Resources
335 |
336 | 1. [Slides]()
337 | 2. [Grand_Central_Dispatch - wikipedia](https://en.wikipedia.org/wiki/Grand_Central_Dispatch) 1
338 | 3. [Async/await - wikipedia](https://en.wikipedia.org/wiki/Async/await)
339 | 4. [Coroutine - wikipedia](https://en.wikipedia.org/wiki/Coroutine)
340 | 5. []()
341 |
342 | 8.
343 |
344 |
345 |
346 |
347 | https://gist.github.com/lattner/429b9070918248274f25b714dcfc7619
348 |
349 |
350 | https://developer.apple.com/documentation/dispatch/dispatchqueue
351 |
--------------------------------------------------------------------------------
/Lessons/03-Grand-Central_Dispatch-Pt2/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Make-School-Courses/MOB-2.3-Concurrency-Parallelism-in-iOS/0ae12a6aa027257fa2f2d34fb98a32d941586347/Lessons/03-Grand-Central_Dispatch-Pt2/.DS_Store
--------------------------------------------------------------------------------
/Lessons/03-Grand-Central_Dispatch-Pt2/assets/Critical_section_fg copy.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Make-School-Courses/MOB-2.3-Concurrency-Parallelism-in-iOS/0ae12a6aa027257fa2f2d34fb98a32d941586347/Lessons/03-Grand-Central_Dispatch-Pt2/assets/Critical_section_fg copy.jpg
--------------------------------------------------------------------------------
/Lessons/03-Grand-Central_Dispatch-Pt2/assets/Critical_section_fg.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Make-School-Courses/MOB-2.3-Concurrency-Parallelism-in-iOS/0ae12a6aa027257fa2f2d34fb98a32d941586347/Lessons/03-Grand-Central_Dispatch-Pt2/assets/Critical_section_fg.jpg
--------------------------------------------------------------------------------
/Lessons/03-Grand-Central_Dispatch-Pt2/assets/Critical_section_fg.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Make-School-Courses/MOB-2.3-Concurrency-Parallelism-in-iOS/0ae12a6aa027257fa2f2d34fb98a32d941586347/Lessons/03-Grand-Central_Dispatch-Pt2/assets/Critical_section_fg.png
--------------------------------------------------------------------------------
/Lessons/03-Grand-Central_Dispatch-Pt2/assets/activity_diag_template.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Make-School-Courses/MOB-2.3-Concurrency-Parallelism-in-iOS/0ae12a6aa027257fa2f2d34fb98a32d941586347/Lessons/03-Grand-Central_Dispatch-Pt2/assets/activity_diag_template.png
--------------------------------------------------------------------------------
/Lessons/03-Grand-Central_Dispatch-Pt2/assets/concurrent_queue.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Make-School-Courses/MOB-2.3-Concurrency-Parallelism-in-iOS/0ae12a6aa027257fa2f2d34fb98a32d941586347/Lessons/03-Grand-Central_Dispatch-Pt2/assets/concurrent_queue.png
--------------------------------------------------------------------------------
/Lessons/03-Grand-Central_Dispatch-Pt2/assets/iOS_runtime_process_with-queues.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Make-School-Courses/MOB-2.3-Concurrency-Parallelism-in-iOS/0ae12a6aa027257fa2f2d34fb98a32d941586347/Lessons/03-Grand-Central_Dispatch-Pt2/assets/iOS_runtime_process_with-queues.png
--------------------------------------------------------------------------------
/Lessons/03-Grand-Central_Dispatch-Pt2/assets/serial_queue.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Make-School-Courses/MOB-2.3-Concurrency-Parallelism-in-iOS/0ae12a6aa027257fa2f2d34fb98a32d941586347/Lessons/03-Grand-Central_Dispatch-Pt2/assets/serial_queue.png
--------------------------------------------------------------------------------
/Lessons/03-Grand-Central_Dispatch-Pt2/assets/sync_deadlock_base.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Make-School-Courses/MOB-2.3-Concurrency-Parallelism-in-iOS/0ae12a6aa027257fa2f2d34fb98a32d941586347/Lessons/03-Grand-Central_Dispatch-Pt2/assets/sync_deadlock_base.png
--------------------------------------------------------------------------------
/Lessons/04-Grand-Central_Dispatch-Pt3/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Make-School-Courses/MOB-2.3-Concurrency-Parallelism-in-iOS/0ae12a6aa027257fa2f2d34fb98a32d941586347/Lessons/04-Grand-Central_Dispatch-Pt3/.DS_Store
--------------------------------------------------------------------------------
/Lessons/04-Grand-Central_Dispatch-Pt3/assets/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Make-School-Courses/MOB-2.3-Concurrency-Parallelism-in-iOS/0ae12a6aa027257fa2f2d34fb98a32d941586347/Lessons/04-Grand-Central_Dispatch-Pt3/assets/.DS_Store
--------------------------------------------------------------------------------
/Lessons/04-Grand-Central_Dispatch-Pt3/assets/DispatchGroups_ex1.playground.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Make-School-Courses/MOB-2.3-Concurrency-Parallelism-in-iOS/0ae12a6aa027257fa2f2d34fb98a32d941586347/Lessons/04-Grand-Central_Dispatch-Pt3/assets/DispatchGroups_ex1.playground.zip
--------------------------------------------------------------------------------
/Lessons/04-Grand-Central_Dispatch-Pt3/assets/DispatchGroups_ex1.playground/Contents.swift:
--------------------------------------------------------------------------------
1 | import UIKit
2 | import PlaygroundSupport
3 |
4 | /*: Tell the playground to continue running, even after it thinks execution has ended.
5 | You need to do this when working with background tasks. */
6 |
7 | PlaygroundPage.current.needsIndefiniteExecution = true
8 |
9 | let group = DispatchGroup()
10 | let myGlobalQueue = DispatchQueue.global(qos: .userInitiated)
11 |
12 | myGlobalQueue.async(group: group) {
13 | print("Start task 1")
14 | Thread.sleep(until: Date().addingTimeInterval(10))
15 | print("End task 1")
16 | }
17 |
18 | myGlobalQueue.async(group: group) {
19 | print("Start task 2")
20 | Thread.sleep(until: Date().addingTimeInterval(2))
21 | print("End task 2")
22 | }
23 |
24 | if group.wait(timeout: .now() + 5) == .timedOut {
25 | print("Hey, I've been waiting too long!")
26 | } else {
27 | print("All tasks completed")
28 | }
29 |
30 | /*: Instruct Xcode that the playground page has finished execution. */
31 | PlaygroundPage.current.finishExecution()
32 |
--------------------------------------------------------------------------------
/Lessons/04-Grand-Central_Dispatch-Pt3/assets/DispatchGroups_ex1.playground/contents.xcplayground:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/Lessons/04-Grand-Central_Dispatch-Pt3/assets/QoSClass_enum.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Make-School-Courses/MOB-2.3-Concurrency-Parallelism-in-iOS/0ae12a6aa027257fa2f2d34fb98a32d941586347/Lessons/04-Grand-Central_Dispatch-Pt3/assets/QoSClass_enum.png
--------------------------------------------------------------------------------
/Lessons/04-Grand-Central_Dispatch-Pt3/assets/QoS_classes.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Make-School-Courses/MOB-2.3-Concurrency-Parallelism-in-iOS/0ae12a6aa027257fa2f2d34fb98a32d941586347/Lessons/04-Grand-Central_Dispatch-Pt3/assets/QoS_classes.png
--------------------------------------------------------------------------------
/Lessons/04-Grand-Central_Dispatch-Pt3/assets/QoS_ex2.playground/Contents.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 |
3 | let queue1 = DispatchQueue(label: "com.makeschool.queue1", qos: DispatchQoS.userInitiated)
4 | let queue2 = DispatchQueue(label: "com.makeschool.queue2", qos: DispatchQoS.utility)
5 |
6 | queue1.async {
7 | for i in 0..<10 {
8 | print("🍎 ", i)
9 | }
10 | }
11 |
12 | queue2.async {
13 | for i in 100..<110 {
14 | print("🐳 ", i)
15 | }
16 | }
17 |
18 | for i in 100..<110 {
19 | print("😬 ", i)
20 | }
21 |
--------------------------------------------------------------------------------
/Lessons/04-Grand-Central_Dispatch-Pt3/assets/QoS_ex2.playground/contents.xcplayground:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/Lessons/04-Grand-Central_Dispatch-Pt3/assets/QoS_ex2.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Make-School-Courses/MOB-2.3-Concurrency-Parallelism-in-iOS/0ae12a6aa027257fa2f2d34fb98a32d941586347/Lessons/04-Grand-Central_Dispatch-Pt3/assets/QoS_ex2.zip
--------------------------------------------------------------------------------
/Lessons/04-Grand-Central_Dispatch-Pt3/assets/QoS_exercise1.playground.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Make-School-Courses/MOB-2.3-Concurrency-Parallelism-in-iOS/0ae12a6aa027257fa2f2d34fb98a32d941586347/Lessons/04-Grand-Central_Dispatch-Pt3/assets/QoS_exercise1.playground.zip
--------------------------------------------------------------------------------
/Lessons/04-Grand-Central_Dispatch-Pt3/assets/QoS_exercise1.playground/Contents.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 |
3 | let queue1 = DispatchQueue(label: "com.makeschool.queue1", qos: DispatchQoS.userInitiated)
4 | let queue2 = DispatchQueue(label: "com.makeschool.queue2", qos: DispatchQoS.userInitiated)
5 |
6 | queue1.async {
7 | for i in 0..<10 {
8 | print("🍎 ", i)
9 | }
10 | }
11 |
12 | queue2.async {
13 | for i in 100..<110 {
14 | print("🐳 ", i)
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/Lessons/04-Grand-Central_Dispatch-Pt3/assets/QoS_exercise1.playground/contents.xcplayground:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/Lessons/04-Grand-Central_Dispatch-Pt3/assets/QoS_exercise1.playground/playground.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
--------------------------------------------------------------------------------
/Lessons/04-Grand-Central_Dispatch-Pt3/assets/gcd_queues.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Make-School-Courses/MOB-2.3-Concurrency-Parallelism-in-iOS/0ae12a6aa027257fa2f2d34fb98a32d941586347/Lessons/04-Grand-Central_Dispatch-Pt3/assets/gcd_queues.png
--------------------------------------------------------------------------------
/Lessons/04-Grand-Central_Dispatch-Pt3/assets/special_QoS_classes.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Make-School-Courses/MOB-2.3-Concurrency-Parallelism-in-iOS/0ae12a6aa027257fa2f2d34fb98a32d941586347/Lessons/04-Grand-Central_Dispatch-Pt3/assets/special_QoS_classes.png
--------------------------------------------------------------------------------
/Lessons/05-Semaphores/Lesson5.md:
--------------------------------------------------------------------------------
1 | # Semaphores
2 |
3 | ## Minute-by-Minute
4 |
5 | | **Elapsed** | **Time** | **Activity** |
6 | | ----------- | --------- | ------------------------- |
7 | | 0:00 | 0:05 | Objectives |
8 | | 0:05 | 0:15 | Overview |
9 | | 0:20 | 0:45 | In Class Activity I |
10 | | 1:05 | 0:10 | BREAK |
11 | | 1:15 | 0:45 | In Class Activity II |
12 | | TOTAL | 2:00 | |
13 |
14 | ## Why you should know this
15 |
16 | Semaphores are a well known topic in every Operating Systems class. They help solving synchronization problems and it's simple to lay out how they work. They are a tool that comes with GDC, so even if we don't use them in our every day life, it's important to know how they can help us, when should we use them and they help strengthen our thought process.
17 |
18 | ## Learning Objectives (5 min)
19 |
20 | 1. Define what a semaphore is.
21 | 1. Understand how semaphores work.
22 | 1. Implement solutions to given scenarios using semaphores.
23 | 1. Use semaphores in Swift.
24 |
25 | ## Initial Exercise (15 min)
26 |
27 | Review solution to **JankyTable app** assignment from last lesson.
28 |
29 | - One or more volunteers present their solutions. Opens a class discussion.
30 |
31 | ## An intro to semaphores (15 min)
32 |
33 | #### Semaphores in real life
34 |
35 | A system of signals used to communicate visually:
36 | - Flags
37 | - Lights
38 | - Or other mechanism
39 |
40 | #### Semaphores in software
41 | A data structure that is useful for solving a variety of synchronization problems. Semaphores were invented by Edsger Dijkstra.
42 |
43 | #### A formal definition
44 | When we create a semaphore, we can initialize its value to any integer.
45 | After that the only operations we are allowed to perform are:
46 | - increment (increase by one)
47 | - decrement (decrease by one)
48 |
49 |
50 | We cannot read the current value of the semaphore.
51 |
52 | When a thread decrements the semaphore, if the result is negative, the thread **blocks** itself and cannot continue until another thread increments the semaphore.
53 |
54 | When a thread increments the semaphore, if there are other threads waiting, one of the waiting threads gets **unblocked**.
55 |
56 | ##### What does the initial value mean?
57 | If the value is **positive**, then it represents the number of threads that can decrement without blocking. If it is **negative**, then it represents the number of threads that have blocked and are waiting. If the value is **zero**, it means there are no threads waiting, but if a thread tries to decrement, it will block.
58 |
59 | ##### Some things to note
60 |
61 | - There is no way to know before a thread decrements a semaphore whether it will block or not.
62 | - After a thread increments a semaphore and another thread gets woken up, both threads continue running concurrently. There is no way to know which thread, if either, will continue immediately.
63 | - When we signal a semaphore, we don’t necessarily know whether another thread is waiting, so the number of unblocked threads may be zero or one.
64 |
65 | ##### Why semaphores?
66 | - Semaphores impose constraints that help programmers avoid errors.
67 | - Solutions using semaphores are often clean and organized, making it easy to demonstrate their correctness.
68 | - Semaphores can be implemented efficiently on many systems, so solutions that use semaphores are portable and usually efficient.
69 |
70 | #### Syntax
71 | To make it easy to understand how semaphores work, for now we'll use pseudo code to implement semaphores.
72 |
73 | ```swift
74 | sem = Semaphore(1)
75 | ```
76 | Creates a new semaphore. The initial value of the semaphore is passed as a parameter to the constructor.
77 |
78 | The semaphore operations:
79 | ```swift
80 | sem.signal()
81 | sem.wait()
82 | ```
83 |
84 | ### Signaling
85 |
86 | The simplest use for a semaphore is signaling, which means that one thread sends a signal to another thread to indicate that something has happened.
87 |
88 | Signaling makes it possible to guarantee that a section of code in one thread will run before a section of code in another thread; in other words, it solves the
89 | serialization problem.
90 | Assume that we have a semaphore named sem with initial value 0, and that
91 | Threads A and B have shared access to it.
92 |
93 | | **Thread A** | **Thread B** |
94 | | ----------- | ------------- |
95 | | statement a1 | sem.wait() |
96 | | sem.signal() | statement b1 |
97 |
98 | **Q:** What does statement represent?
99 | **Q:** Can you give a concrete example of what a1 and b1 can be?
100 | **Q:** What is the semaphore doing in this program?
101 |
102 | *Whiteboard for scenarios*
103 |
104 | **Q:** What happens when B gets to the wait statement first?
105 |
106 | **Q:** What happens when A gets to the signal statement first?
107 |
108 |
109 |
110 | **NOTE on naming semamphores**
111 | It is a good idea to give a semaphore a name that indicates what it represents.
112 | For example:
113 | `a1done.signal()` means *signal that a1 is done*
114 | `a1done.wait()` means *wait until a1 is done*
115 |
116 | ## In Class Activity I (20 min)
117 |
118 | ### Rendezvous
119 | Generalize the signal pattern so that it works both ways. Thread A has to wait for Thread B and vice versa.
120 |
121 | Given:
122 |
123 | | **Thread A** | **Thread B** |
124 | | ----------- | ------------- |
125 | | statement a1 | statement b1 |
126 | | statement a2 | statement b2 |
127 |
128 | We want to guarantee that a1 happens before b2 and b1 happens before a2. Use semaphores to make this possible.
129 |
130 | Hints:
131 | - Be sure to specify the names and initial values of your semaphores.
132 | - We don’t care about the order of a1 and b1. Either order should be possible.
133 |
134 | **Part 1** - Individually write a solution for the problem above. Write it down.
135 | **Part 2** - Compare with a partner both solutions. See how they're similar or different.
136 | **Part 3** - A volunteer writes the answer on a whiteboard. Opens a class discussion.
137 |
138 | **Q:** Why is this problem called rendezvous?
139 |
140 |
173 |
174 | ## Mutual Exclusion (10 min)
175 | A second common use for semaphores is to enforce mutual exclusion. We have already seen one use for mutual exclusion, controlling concurrent access to shared variables. T
176 |
177 | he mutex guarantees that only one thread accesses the shared variable at a time.
178 |
179 | A mutex is like a token that passes from one thread to another, allowing one thread at a time to proceed. For example (can be done in real life): Tossing a ball around the class and only the person holding it can talk.
180 |
181 | In order for a thread to access a shared variable, it has to “get” the mutex; when it is done, it “releases” the mutex. Only one thread can hold the mutex at a time.
182 |
183 | **Q:** In the ball analogy, what is the shared variable? the mutex? the thread?
184 |
185 |
186 | ## In Class Activity II (20 min)
187 |
188 | Add semaphores to the following example to enforce mutual exclusion to the shared variable count.
189 |
190 | | **Thread A** | **Thread B** |
191 | | ----------- | ------------- |
192 | | count = count + 1 | count = count + 1 |
193 |
194 | Hint: Create a semaphore named mutex that is initialized to 1. A value of one means that a thread may proceed and access the shared variable; a value of zero means that it has to wait for another thread to release the mutex.
195 |
196 | **Part 1** - Individually write a solution for the problem above. Write it down.
197 | **Part 2** - Compare with a partner both solutions. See how they're similar or different.
198 | **Part 3** - A volunteer writes the answer on a whiteboard. Opens a class discussion.
199 |
200 | **Q:** When do we call signal() and wait()?
201 |
203 |
204 |
216 |
217 | ## DispatchSemaphore (10 min)
218 | An object that controls access to a resource across multiple execution contexts through use of a traditional counting semaphore.
219 |
220 | A dispatch semaphore is an efficient implementation of a traditional counting semaphore.
221 |
222 | You increment a semaphore count by calling the signal() method, and decrement a semaphore count by calling wait() or one of its variants that specifies a timeout.
223 |
224 | Two components:
225 |
226 | A threads queue - 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).
227 |
228 | A counter value - 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.
229 |
230 | *Flowchart*
231 |
232 | ## In Class Activity III (20 min)
233 |
234 | ```Swift
235 | let semaphore = DispatchSemaphore(value: 1)
236 | DispatchQueue.global().async {
237 | print("Person 1 - wait")
238 | semaphore.wait()
239 | print("Person 1 - wait finished")
240 | sleep(1) // Person 1 playing with Switch
241 | print("Person 1 - done with Switch")
242 | semaphore.signal()
243 | }
244 | DispatchQueue.global().async {
245 | print("Person 2 - wait")
246 | semaphore.wait()
247 | print("Person 2 - wait finished")
248 | sleep(1) // Person 2 playing with Switch
249 | print("Person 2 - done with Switch")
250 | semaphore.signal()
251 | }
252 | ```
253 |
254 | ## Assignment
255 |
256 | What's wrong with the code?
257 |
258 | ```Swift
259 | var array = [Int]()
260 | DispatchQueue.concurrentPerform(iterations: 10){
261 | index in
262 |
263 | let last = array.last ?? 0
264 | array.append(last + 1)
265 | print(array)
266 | }
267 |
268 | ```
269 |
270 | Evaluation: Must submit a working code snippet to Gradescope. Graded on completion.
271 |
272 | ## After Class
273 | 1. Research:
274 | - Meaning of symmetric vs asymmetric solutions.
275 | - What is meant by "critical section" in a program.
276 | - Difference between Dispatch Groups and Semaphores?
277 | - Multiplex (challenge)
278 | 2. NSLock
279 |
280 | 3. Assignment: Solve the **Dining Philosophers Problem** (challenge):
281 | - https://github.com/raywenderlich/swift-algorithm-club/tree/master/DiningPhilosophers
282 |
283 |
284 | ## Wrap Up (5 min)
285 |
286 | - Complete reading
287 | - Complete challenges
288 |
289 | ## Additional Resources
290 |
291 | 1. [Slides](https://docs.google.com/presentation/d/1Q3YKFpPtePLoi2uEDt-z5hl7ct6qn3lMX380rUHg39I/edit?usp=sharing)
292 | 2. "The Little Book of Semaphores" by Allen B. Downey
293 | 3. [Dispatch Semaphore from Apple Docs](https://developer.apple.com/documentation/dispatch/dispatchsemaphore)
294 | 4. [An article on semaphores](https://medium.com/swiftly-swift/a-quick-look-at-semaphores-6b7b85233ddb)
295 | 5. [Semaphore flowchart](https://medium.com/@roykronenfeld/semaphores-in-swift-e296ea80f860)
296 |
--------------------------------------------------------------------------------
/Lessons/06-Operations-Pt1/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Make-School-Courses/MOB-2.3-Concurrency-Parallelism-in-iOS/0ae12a6aa027257fa2f2d34fb98a32d941586347/Lessons/06-Operations-Pt1/.DS_Store
--------------------------------------------------------------------------------
/Lessons/06-Operations-Pt1/assets/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Make-School-Courses/MOB-2.3-Concurrency-Parallelism-in-iOS/0ae12a6aa027257fa2f2d34fb98a32d941586347/Lessons/06-Operations-Pt1/assets/.DS_Store
--------------------------------------------------------------------------------
/Lessons/06-Operations-Pt1/assets/BlockOperation_ex2.playground.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Make-School-Courses/MOB-2.3-Concurrency-Parallelism-in-iOS/0ae12a6aa027257fa2f2d34fb98a32d941586347/Lessons/06-Operations-Pt1/assets/BlockOperation_ex2.playground.zip
--------------------------------------------------------------------------------
/Lessons/06-Operations-Pt1/assets/BlockOperation_ex2.playground/Contents.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 |
3 | let phrase = "Mobile is the greatest!"
4 | let tokenOperation = BlockOperation()
5 |
6 | for token in phrase.split(separator: " ") {
7 | tokenOperation.addExecutionBlock {
8 | print(token)
9 | sleep(2)
10 | }
11 | }
12 |
13 | // TODO: create completionBlock
14 |
15 | duration {
16 | //TODO: start the operation
17 | }
18 |
--------------------------------------------------------------------------------
/Lessons/06-Operations-Pt1/assets/BlockOperation_ex2.playground/Sources/Duration.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 |
3 | public func duration(_ block: () -> ()) -> TimeInterval {
4 | let startTime = Date()
5 | block()
6 | return Date().timeIntervalSince(startTime)
7 | }
8 |
--------------------------------------------------------------------------------
/Lessons/06-Operations-Pt1/assets/BlockOperation_ex2.playground/contents.xcplayground:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/Lessons/06-Operations-Pt1/assets/BlockOperation_ex2.playground/playground.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/Lessons/06-Operations-Pt1/assets/BlockOperation_ex2.playground/playground.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/Lessons/06-Operations-Pt1/assets/BlockOperation_ex2.playground/playground.xcworkspace/xcuserdata/thomas_vandegriff.xcuserdatad/UserInterfaceState.xcuserstate:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Make-School-Courses/MOB-2.3-Concurrency-Parallelism-in-iOS/0ae12a6aa027257fa2f2d34fb98a32d941586347/Lessons/06-Operations-Pt1/assets/BlockOperation_ex2.playground/playground.xcworkspace/xcuserdata/thomas_vandegriff.xcuserdatad/UserInterfaceState.xcuserstate
--------------------------------------------------------------------------------
/Lessons/06-Operations-Pt1/assets/Operation-Queue.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Make-School-Courses/MOB-2.3-Concurrency-Parallelism-in-iOS/0ae12a6aa027257fa2f2d34fb98a32d941586347/Lessons/06-Operations-Pt1/assets/Operation-Queue.png
--------------------------------------------------------------------------------
/Lessons/06-Operations-Pt1/assets/Operation_states.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Make-School-Courses/MOB-2.3-Concurrency-Parallelism-in-iOS/0ae12a6aa027257fa2f2d34fb98a32d941586347/Lessons/06-Operations-Pt1/assets/Operation_states.png
--------------------------------------------------------------------------------
/Lessons/08-Operations-Pt3/Lesson8.md:
--------------------------------------------------------------------------------
1 | # Operations Pt. 3
2 |
3 |
5 |
6 | ## Learning Objectives
7 |
8 | 1. Identify use cases of Operations with dependencies.
9 | 1. Implement dependencies.
10 | 1. Review Operations by implementing a solution in a project.
11 |
12 |
13 | ## Dependencies
14 |
15 | (Refer to slides)
16 |
17 | ## In Class Activity I
18 |
19 | ### Pair Programming activity - Introduction
20 |
21 |
22 | **We'll do this activity in pairs.** One of you will code while the other guides the activity using this repo. Then at some point you will switch roles.
23 |
24 | Get the starter project [here](https://github.com/amelinagzz/operations-starter). Build it, run it and tap where it says **“Show Tilt Shift”**. What we’ll see is an example of what we want to achieve for a collection of images. It's a blur effect. 🤓
25 |
26 | Tilt shifting is a technique used on images to alter the depth of field. This results in a change in focus as you can tell from comparing both images.
27 |
28 | Now go back and select **“Show Table View”**. You’ll notice it’s an empty table with some activity indicators, but nothing ever shows up. Let’s fix that. 😦
29 |
30 | We’ll start using an over simplified approach to then make it better.
31 |
32 | Files breakdown:
33 |
34 | - `ExampleViewController.swift`- The VC with the example image to demonstrate the filter effect
35 | - `PhotoCell.swift` - Custom cell with the layout to display one image
36 | - `TiltShiftFilter.swift` - Class that create and applies the filter
37 | - `TiltShiftOperation.swift` - Operation class responsible to handle filter application
38 | - `TiltShiftTableViewController.swift` - VC with the tableview that needs to be fixed
39 | - `NetworkImageOperation.swift` - Operation that will be used later to download images from urls
40 | - `AsyncOperation.swift` - Operation implementation with KVO
41 | - Assets - contains the 10 images you will use for the first part of this activity
42 |
43 | ### Step 1
44 |
45 | Go to `TiltShiftTableViewController.swift` and on the `cellForRowAt` method, get an image to then apply the filter to it.
46 |
47 | ```Swift
48 | override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
49 | let cell = tableView.dequeueReusableCell(withIdentifier: "normal", for: indexPath) as! PhotoCell
50 | let name = "\(indexPath.row).png" //these files can be found in the assets folder
51 | let inputImage = UIImage(named:name)!
52 |
53 | //Creating the filter
54 | guard let filter = TiltShiftFilter(image:inputImage, radius:3), let output = filter.outputImage else{
55 | print("Failed to generate image")
56 | cell.display(image: nil)
57 | return cell
58 | }
59 |
60 | let fromRect = CGRect (origin: .zero, size: inputImage.size)
61 | let context = CIContext() //context used to turn the image back to UIImage
62 | guard let cgImage = context.createCGImage(output, from: fromRect) else{
63 | print("Image generation failed")
64 | cell.display(image:nil)
65 | return cell
66 | }
67 |
68 | cell.display(image: UIImage(cgImage:cgImage))
69 | return cell
70 | }
71 | ```
72 |
73 | Now run the app and notice how the table takes forever to load (you might want to wait up to a minute or two 😵) and is pretty much unusable. But the images are there now!
74 |
75 | **Can you guess what is it that we need to do to improve the user experience?**
76 |
77 | If any of you said moving the tilt shifting off the main thread and into a background thread, you are correct ✅
78 |
79 |
80 | ### Step 2 - Using an operation
81 |
82 | Let’s move the Core Image operations into `TiltShiftOperation` which is an Operation subclass.
83 |
84 | Add this property to you class:
85 | `private static let context = CIContext()`
86 | The reason why this property is *static* is because we don’t want to create a new context with each instance of the operation. CIContext should be reused if possible and it’s also *thread safe*.
87 |
88 | Add two properties: `outputImage` and `inputImage`. Both of type `UIImage?`.
89 |
90 | Add the initializer.
91 | ```Swift
92 | init(image: UIImage? = nil) {
93 | inputImage = image
94 | super.init()
95 | }
96 | ```
97 |
98 | Now let’s override the main method. Here goes the long running task we want to do. **Make sure you move the right code into the main method.** (hint: we tried to do this for each cell) See if you can do it on your own. And then confirm you have it right with the following:
99 |
100 | ```swift
101 | override func main() {
102 | if let inputImage = inputImage{
103 | guard let filter = TiltShiftFilter(image: inputImage, radius:3),
104 | let output = filter.outputImage else {
105 | print("Failed to generate tilt shift image")
106 | return
107 | }
108 |
109 | let fromRect = CGRect(origin: .zero, size: inputImage.size)
110 | guard let cgImage = TiltShiftOperation.context.createCGImage(output, from: fromRect) else {
111 | print("No image generated")
112 | return
113 | }
114 | outputImage = UIImage(cgImage: cgImage)
115 | }
116 | }
117 | ```
118 |
119 | After that is correctly set up. **We need to go back to our table and make it use our operation.** Try running it manually, using the `start()` method. It should look something like this:
120 |
121 | ```swift
122 | override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
123 | let cell = tableView.dequeueReusableCell(withIdentifier: "normal", for: indexPath) as! PhotoCell
124 | let name = "\(indexPath.row).png"
125 | let inputImage = UIImage(named:name)!
126 | print("Filtering")
127 | let op = TiltShiftOperation(image: inputImage)
128 | op.start()
129 |
130 | cell.display(image: op.outputImage)
131 | print("Done")
132 |
133 | return cell
134 | }
135 | ```
136 |
137 | Build and run. Is this a lot better? How about performance? Think about what is it that changed and how it’s not good yet.
138 |
139 | **Q: What is the problem?**
140 |
141 | If you said it’s the `start()` call, correct! When we call the start method directly, we are performing a *synchronous* call on the main thread. So even when we moved out the filtering code into an Operation, we are still not using it correctly to take advantage of it.
142 |
143 | Another thing that could have gone really wrong, was if the operation wasn’t ready and we call start on it. Sure crash. ❌
144 |
145 |
146 | ### Step 3 - Updating the table
147 |
148 | Go to `TiltShiftTableViewController` and create a new `OperationQueue` at the scope of the class (at the top). We'll use the queue to run the TiltShiftOperation instead of doing it manually.
149 |
150 | ```swift
151 | let operationQueue = OperationQueue()
152 | ```
153 |
154 | Now replace the contents of `cellForRowAt` to run the operation with the queue. Like this:
155 |
156 | ```swift
157 | override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
158 | let cell = tableView.dequeueReusableCell(withIdentifier: "normal", for: indexPath) as! PhotoCell
159 | let name = "\(indexPath.row).png"
160 | let inputImage = UIImage(named:name)!
161 | let tiltOperation = TiltShiftOperation(image: inputImage)
162 | tiltOperation.completionBlock = {
163 | DispatchQueue.main.async {
164 | guard let cell = tableView.cellForRow(at: indexPath) as? PhotoCell else { return }
165 | cell.isLoading = false
166 | cell.display(image: tiltOperation.outputImage)
167 | }
168 | }
169 | operationQueue.addOperation(tiltOperation)
170 | return cell
171 | }
172 | ```
173 |
174 | Build and run. What’s different from the last time? Is this better? 🤔 It should be! Now each image applies the filter at its own pace.
175 |
176 | **SWITCH TIME 🔛** If you are pair programming, give the control to the other teammate.
177 |
178 | ### Step 4 - Downloading images
179 |
180 | Right now the app uses images from the Assets Catalog. Let’s change that so that it downloads images from URLs, which is closer to a real use case.
181 |
182 | Take some time to look at `NetworkImageOperation.swift` before moving on. See the similarities and differences between this one and `TiltShiftOperation.swift` which you coded out entirely.
183 |
184 | Now go to `TiltShiftTableViewController` and get list of URLs form the Photos plist. If you get stuck check it below.
185 |
186 | ```Swift
187 | private var urls: [URL] = []
188 | override func viewDidLoad() {
189 | super.viewDidLoad()
190 | guard let plist = Bundle.main.url(forResource: "Photos",
191 | withExtension: "plist"),
192 | let contents = try? Data(contentsOf: plist),
193 | let serial = try? PropertyListSerialization.propertyList(
194 | from: contents,
195 | format: nil),
196 | let serialUrls = serial as? [String] else {
197 | print("Something went horribly wrong!")
198 | return
199 | }
200 | urls = serialUrls.compactMap(URL.init)
201 | }
202 | ```
203 |
204 | **Food for thought: What is compactMap doing?** Think about if and share with your partner.
205 |
206 | Now change `cellForRowAt` one more time to use the `NetworkImageOperation` class and send to it the corresponding element from the urls array. Try it out, it should look as follows:
207 |
208 | ```swift
209 | override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
210 | let cell = tableView.dequeueReusableCell(withIdentifier: "normal", for: indexPath) as! PhotoCell
211 |
212 | let networkOperation = NetworkImageOperation(url: urls[indexPath.row])
213 | networkOperation.completionBlock = {
214 | DispatchQueue.main.async {
215 | guard let cell = tableView.cellForRow(at: indexPath) as? PhotoCell else { return }
216 | cell.isLoading = false
217 | cell.display(image: networkOperation.image)
218 | }
219 | }
220 | operationQueue.addOperation(networkOperation)
221 | return cell
222 | }
223 | ```
224 |
225 | Build and run. You should see a smoother scroll.
226 |
227 | ### Step 5 - Using dependencies
228 |
229 | What we are here for! Dependencies.
230 |
231 | Now that we have an operation that downloads the image and another that applies the filter, let’s combine them together to have one happening after the other. Using dependencies 😎
232 |
233 | To start we are going to need a protocol to pass data between operations. Create a new file and call it `ImageDataProvider` and add the following:
234 |
235 | ```Swift
236 | import UIKit
237 | protocol ImageDataProvider {
238 | var image: UIImage? { get }
239 | }
240 |
241 | ```
242 |
243 | Both `NetworkImageOperation` and `TiltShiftOperation` should conform to this protocol. You can try doing that in extensions.
244 |
245 | ```Swift
246 | extension NetworkImageOperation: ImageDataProvider {}
247 |
248 | extension TiltShiftOperation: ImageDataProvider {
249 | var image: UIImage? { return outputImage }
250 | }
251 | ```
252 |
253 | We know `TiltShiftOperation` needs an image as input. Let’s also make it check if any of its dependencies give the image as output.
254 |
255 | Add this at the beginning of `main()` in `TiltShiftOperation`:
256 |
257 | ```Swift
258 | let dependencyImage = dependencies
259 | .compactMap { ($0 as? ImageDataProvider)?.image }
260 | .first
261 | guard let inputImage = inputImage ?? dependencyImage else {
262 | return
263 | }
264 | ```
265 | At this point you will need to get rid of the safety `if ... let` that we had before because now we are using a `guard` statement for the same purpose.
266 |
267 | Let’s go back to 'TiltShiftTableViewcontroller' change what’s in `cellForRowAt` again (this is the last time I promise), specifically the line where we set and declare the operation.
268 |
269 | ```Swift
270 | let networkOperation = NetworkImageOperation(url: urls[indexPath.row])
271 | let tiltShiftOp = TiltShiftOperation()
272 | tiltShiftOp.addDependency(networkOperation)
273 | ```
274 |
275 | See how we have now **2 operations and a dependency** that ties them together.
276 |
277 | Now instead of setting the completionBlock, set it on the `tiltShiftOp` which is the one giving you back the image.
278 |
279 | Replace it with this:
280 | ```Swift
281 | tiltShiftOp.completionBlock = {
282 | DispatchQueue.main.async {
283 | guard let cell = tableView.cellForRow(at: indexPath) as? PhotoCell else { return }
284 | cell.isLoading = false
285 | cell.display(image: tiltShiftOp.outputImage)
286 | }
287 | }
288 | ```
289 |
290 | **Our tilt shift depends on the download. Does this mean we should only add the network operation to the queue?**
291 |
292 | ```swift
293 | operationQueue.addOperation(networkOperation)
294 | ```
295 |
296 | **Or both?**
297 |
298 | ```swift
299 | operationQueue.addOperation(networkOperation)
300 | operationQueue.addOperation(tiltShiftOp)
301 | ```
302 |
303 | Try both and see what is the answer. Then you should have the tableview working in the end.
304 |
305 | ### Step 6 - Final fix
306 |
307 | You have probably noticed that the cells don't clean up before being reused. We are not caching these images but we can make it better by cleaning up the cell using the method `prepareForReuse`. Open `PhotoCell.swift` and add the following:
308 |
309 | ```swift
310 | override func prepareForReuse() {
311 | nasaImageView.image = nil
312 | activityIndicator.startAnimating()
313 | }
314 | ```
315 |
316 | Try running it again and this time you should not see the previous images before new ones get placed.
317 |
318 | Congrats you made it! You used dependencies with Operations to establish the following order:
319 |
320 | 1. Download images from urls
321 | 2. Apply Filters to the images
322 |
323 | You also used an operation queue to run these to make sure things happened async. Great job 👍🏼
324 |
325 | ## Wrap Up
326 |
327 | - You pair programmed today's exercise. Make sure both of you get a working copy of the project.
328 |
329 | ## Additional Resources
330 |
331 | 1. [Slides](https://docs.google.com/presentation/d/1ZS9ZQaGVD5bsQ3kkDOBDZY_fRgh45Xgsb1NHPhuXAbI/edit?usp=sharing)
332 | 1. Concurrency by Tutorials Book
333 |
--------------------------------------------------------------------------------
/Lessons/09-Pitfalls-Challenges/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Make-School-Courses/MOB-2.3-Concurrency-Parallelism-in-iOS/0ae12a6aa027257fa2f2d34fb98a32d941586347/Lessons/09-Pitfalls-Challenges/.DS_Store
--------------------------------------------------------------------------------
/Lessons/09-Pitfalls-Challenges/Lesson9.md:
--------------------------------------------------------------------------------
1 | # Concurrency Pitfalls & Challenges
2 |
3 |
5 |
6 | ## Why you should know this
7 |
8 | Concurrency gives us many benefits when it comes to solving performance issues. Today we'll learn about the most well-known problems we can encounter if we are not being careful with our apps and how to solve them 😉.
9 |
10 | ## Learning Objectives
11 |
12 | 1. Identify, describe, and propose solutions to the following concurrency challenges:
13 | - **Race Conditions**
14 | - **Priority Inversion**
15 | 2. Identify and describe how to use __*dispatch barriers*__ to alleviate issues caused by locks and semaphores
16 |
17 |
18 | ## Race conditions
19 |
20 | Let's say we have a program that depends on the timing of one or more processes to function correctly.
21 |
22 | If a thread runs or finishes at an unexpected time, it may cause unpredictable behavior:
23 | - incorrect output
24 | - program deadlock
25 |
26 | Any situation where several processes access and manipulate shared data concurrently and where the result depends on timing of these processes, which are “racing” is a **race condition**.
27 |
28 | 🌀Note: **Thread-safe** is the term we use to describe a program, code, or data structure free of race conditions when accessed by multiple threads.
29 |
30 | ### An example
31 |
32 | **Situation:** We have two threads executing and both of them are trying to update a `count` variable.
33 |
34 | **Fact:** Reads and writes are separate tasks that the computer cannot execute in a single operation.
35 |
36 | **What we do in each thread:** `count += 1`
37 |
38 | **What really happens:**
39 | 1. We load the value of the variable `count` into memory.
40 | 1. We increment the value of `count` by one in memory.
41 | 1. We write the updated count back to disk.
42 |
43 | (Whiteboard drawing + explaining)
44 |
45 | **Result:** Race conditions lead to complicated debugging due to the non-deterministic characteristic of these scenarios.
46 |
47 | **How can we solve it:** Serial queues 👍🏼
48 |
49 | If we have a variable that needs to be accessed concurrently, we can wrap reads and writes in a serial queue.
50 |
51 | ```Swift
52 | private let countQueue = DispatchQueue(label: "countqueue")
53 | private var count = 0
54 | public var count: Int {
55 | get {
56 | return countQueue.sync {
57 | count
58 | }
59 | }
60 | set {
61 | countQueue.sync {
62 | count = newValue
63 | }
64 | }
65 | }
66 | ```
67 |
68 | Here we are controlling the access to the variable an making sure that only a single thread at a time can access the variable.
69 |
70 | **What's another solution you can think of?**
71 |
72 | (Whiteboard drawing + explaining with locks)
73 |
74 | ### Thread barrier
75 | Our previous solution is effective for simple situations. But there are times when the shared resource needs more complex logic. To make up for that we can use a solution from GCD, called **dispatch barrier**.
76 |
77 | The main idea is that we create a concurrent queue where we can process all the read tasks we want, they can all run at the same time. But when the variable needs to be written to, then we lock the queue so that submitted tasks complete but no new submissions are run until the update is done.
78 |
79 | (whiteboard diagram)
80 |
81 | *Implementation*
82 |
83 | ```Swift
84 | private let countQueue = DispatchQueue(label: "countqueue", attributes: .concurrent)
85 | private var count = 0
86 | public var count: Int {
87 | get {
88 | return countQueue.sync {
89 | count
90 | }
91 | }
92 | set {
93 | countQueue.async(flags: .barrier) { [unowned self] in
94 | self.count = newValue
95 | }
96 | }
97 | }
98 | ```
99 | (explanation of code snippet)
100 |
101 | ## NSLock
102 |
103 | An NSLock object implements a basic mutex for Cocoa applications. The interface for all locks is actually defined by the NSLocking protocol, which defines the **lock** and **unlock** methods. You use these methods to acquire and release the lock just as you would any mutex.
104 |
105 | Check out [this example](https://github.com/evgenyneu/keychain-swift/blob/master/Sources/KeychainSwift.swift) from the library KeychainSwift and observe how they use locks.
106 |
107 | ## In Class-Activity I (10 min)
108 |
109 | Take this code snippet into a playground and see what it does. What's wrong with it? What is the concurrency problem?
110 |
111 | ```Swift
112 | var array = [Int]()
113 |
114 | DispatchQueue.concurrentPerform(iterations: 100){ index in
115 | let last = array.last ?? 0
116 | array.append(last + 1)
117 | print(array)
118 | }
119 | ```
120 | Using NSLock, try to fix it. More info on what `concurrentPerform` does [in the docs](https://developer.apple.com/documentation/dispatch/dispatchqueue/2016088-concurrentperform).
121 |
122 | ## Priority Inversion
123 |
124 | ### General Example
125 | In 1995, NASA sent the Pathfinder mission to Mars.
126 |
127 | 
128 |
129 | Not too long after a successful landing on our red neighboring planet, the mission almost came to an abrupt end.
130 |
131 | The Mars rover (Sojourner) kept rebooting for unknown reasons – it suffered from a phenomenon called __*priority inversion*__.
132 |
133 | Read more about what happened [here](http://www.cse.chalmers.se/~risat/Report_MarsPathFinder.pdf).
134 |
135 | ### How it happens
136 |
137 | The problem can occur when you have a high-priority and a low-priority task share a common resource:
138 |
139 | 
140 |
141 | - When the low-priority task takes a lock to the common resource, it is supposed to finish off quickly in order to release its lock and to let the high-priority task execute without significant delays.
142 | - Since the high-priority task is blocked from running as long as the low-priority task has the lock, there is a window of opportunity for medium-priority tasks to run and to preempt the low-priority task, because the medium-priority tasks have now the highest priority of all currently runnable tasks.
143 | - At this moment, the medium-priority tasks hinder the low-priority task from releasing its lock, therefore effectively gaining priority over the still waiting, high-priority tasks.
144 |
145 |
146 | ### Priority Inversion in iOS
147 | Since GCD exposes background queues with different priorities, including one which even is I/O throttled, it’s good to know about this possibility.
148 |
149 | Priority inversion most commonly occurs in iOS when a queue with a lower quality of service is given a higher system priority than a queue with a higher QoS.
150 | - As a result, blocking, spinning, and polling may occur.
151 |
152 | You may recall that the QoS of a Dispatch or an Operation Queue can be changed based on the QoS of the tasks which you, the developer, submit to it.
153 |
154 | If you submit multiple tasks to a `.utility` queue with the higher-priority `.userInteractive` QoS,2 the system could upgrade the QoS of that queue with a priority *higher* than that of a `.userInitiated` queue. Suddenly, all the tasks in the queue — most of which are really of the `.utility` QoS — will end up running before the tasks from the `.userInitiated` queue.
155 |
156 | > 2 Remember your QoS levels:
157 | > - `.userInteractive` — Tasks submitted to this queue should complete virtually instantaneously.
158 | > - `.userInitiated` — Tasks performed in this queue should take a few seconds or less to complete.
159 | > - `.utility` — Tasks can take a few seconds to a few minutes in this queue.
160 | > - `.background` — Use this queue for work that will take significant time, minutes or more.
161 |
162 |
163 | ### How to avoid it
164 | In the case of *synchronous* work, the system will try to resolve the priority inversion automatically by raising the QoS of the lower priority work for the duration of the inversion.1
165 |
166 | But using multiple queues with different priorities adds even more complexity and unpredictability to concurrent programs.
167 |
168 | Thus, it is highly recommended (by Apple) that Developers should try to ensure that priority inversions don’t occur in the first place, so the system isn’t forced to attempt a resolution.
169 |
170 | Priority inversion is easy to avoid:
171 | - In general, don’t use different priorities.
172 | - If you need a higher QoS, use a different queue that with the desired QoS.
173 | - When you’re using GCD, always use the default priority queue (directly, or as a target queue)
174 |
175 | *Sources:*
176 | - https://www.objc.io/issues/2-concurrency/concurrency-apis-and-pitfalls/
177 | - Resource 21 below
178 |
179 | ## In Class-Activity II
180 |
181 | ### Common questions regarding concurrency in iOS.
182 |
183 |
184 |
185 | In pairs or groups of 3, choose up to 4 questions to ask each other. Some of these questions are very common in iOS interviews, meaning it's important we know how to explain the concepts and give examples.
186 |
187 | 1. What is Concurrency?
188 | 1. What is Parallelism?
189 | 1. What are most commonly used APIs to implement concurrency in iOS?
190 | 1. What is a queue? What is their relationship with FIFO?
191 | 1. What are all the different types of queues and their priorities?
192 | 1. What is the difference between an asynchronous and a synchronous task?
193 | 1. What is the difference between a serial and a concurrent queue?
194 | 1. How does GCD work?
195 | 1. Explain the relationship between a process, a thread and a task.
196 | 1. Are there any threads running by default? Which ones?
197 | 1. How does iOS support multithreading?
198 | 1. What is NSOperation? and NSOperationQueue?
199 | 1. What is QoS?
200 | 1. Explain priority inversion.
201 | 1. Explain dependencies in Operations.
202 | 1. When do you use GCD vs Operations?
203 | 1. How do we know if we have a race condition?
204 | 1. What is deadlock?
205 | 1. What is context switching in multithreading?
206 | 1. What are the ways we can execute an Operation? How are they different?
207 | 1. What is DispatchSemaphore and when can we use it?
208 | 1. What happens if you call sync() on the current or main queue?
209 |
210 |
211 | ## After Class
212 |
213 | 1. Research:
214 | - study **Priority Inversions** section in Resource 21 below
215 |
216 | 2. Assignment(s):
217 | - Continue working on your final project
218 |
219 |
220 | ## Wrap Up
221 |
222 | - Complete answering the questions as a way to study for the final exam.
223 |
224 | ## Additional Resources
225 |
226 | 1. [Slides](https://docs.google.com/presentation/d/1JvRyyZy50ndg0__U_dAQkIar78tIHrIJ_qK8FnL28SM/edit#slide=id.p)
227 | 2. [Prioritize Work with Quality of Service Classes - from Apple](https://developer.apple.com/library/archive/documentation/Performance/Conceptual/EnergyGuide-iOS/PrioritizeWorkWithQoS.html) 1
228 | 3. [Threading Programming Guide - from Apple](https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/Multithreading/ThreadSafety/ThreadSafety.html#//apple_ref/doc/uid/10000057i-CH8-SW1)
229 | 4. [What really happened on Mars? - and article by Glenn Reeves](https://users.cs.duke.edu/~carla/mars.html)
230 | 5. [iOS Concurrency — Underlying Truth - an article](https://medium.com/@chetan15aga/ios-concurrency-underlying-truth-1021a0bb2a98)
231 | 6. [NSLock](https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/Multithreading/ThreadSafety/ThreadSafety.html#//apple_ref/doc/uid/10000057i-CH8-SW1)
232 | 7. Book - Comncurrency by Tutorials
233 | 8. [Slides](https://docs.google.com/presentation/d/1JvRyyZy50ndg0__U_dAQkIar78tIHrIJ_qK8FnL28SM/edit?usp=sharing)
234 | 3. [Priority inversion - wikipedia](https://en.wikipedia.org/wiki/Priority_inversion)
235 | 4. [Threading Programming Guide - from Apple](https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/Multithreading/ThreadSafety/ThreadSafety.html#//apple_ref/doc/uid/10000057i-CH8-SW1)
236 | 5. [What really happened on Mars? - and article by Glenn Reeves](https://users.cs.duke.edu/~carla/mars.html)
237 | 6. [iOS Concurrency — Underlying Truth - an article](https://medium.com/@chetan15aga/ios-concurrency-underlying-truth-1021a0bb2a98)
238 |
--------------------------------------------------------------------------------
/Lessons/09-Pitfalls-Challenges/assets/Sojourner_on_Mars_PIA01122.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Make-School-Courses/MOB-2.3-Concurrency-Parallelism-in-iOS/0ae12a6aa027257fa2f2d34fb98a32d941586347/Lessons/09-Pitfalls-Challenges/assets/Sojourner_on_Mars_PIA01122.png
--------------------------------------------------------------------------------
/Lessons/09-Pitfalls-Challenges/assets/priority_inversion.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Make-School-Courses/MOB-2.3-Concurrency-Parallelism-in-iOS/0ae12a6aa027257fa2f2d34fb98a32d941586347/Lessons/09-Pitfalls-Challenges/assets/priority_inversion.png
--------------------------------------------------------------------------------
/Lessons/10-Course-Review-and-Workshop/Lesson10.md:
--------------------------------------------------------------------------------
1 | # Tools + Testing + Review
2 |
3 |
8 |
9 | ## Learning Objectives
10 |
11 | 1. Describe:
12 | - the challenges and benefits of unit testing **Asynchronous Operations**
13 | 2. Implement basic examples of:
14 | - unit tests of an **Asynchronous Operation** (a background dataTask) using the `XCTestExpectation` class,
15 |
16 |
19 |
20 | ## Initial Exercise
21 |
22 | - Let's play a **Quizlet game**.... [Link to study flash cards](https://quizlet.com/530974042/mob-23-final-exam-prep-flash-cards/)
23 |
24 | ## Tools - Instruments 🛠
25 |
26 | Instruments is a powerful performance analysis and testing tool. It comes with Xcode's toolset.
27 |
28 | You can use it during:
29 | - development
30 | - testing
31 | - debugging
32 |
33 | It provides tools called **Instruments** that are used to profile errors in you app.
34 |
35 | An **Instrument** collects data over a period of time.
36 |
37 | ## Time Profiler
38 |
39 | Uses data provided by the operating system to collect call stacks of relevant threads at a fixed time interval.
40 |
41 | **Why?**
42 |
43 | - We can analyze an app's responsiveness and performance.
44 |
45 |
46 | ## Instruments walkthrough
47 |
48 | ### ⬆️ Track Viewer (top)
49 | A track shows time series trace data corresponding to one source of events (such as a process, thread or CPU core)
50 |
51 | ### ⬇️ Detail view (bottom)
52 | Explore trace data for a selected track. See the functions called on each thread during the trace.
53 |
54 | ### ➡️ Extended Detail View (right)
55 | Provides richer info from the Instruments in use. (For example, for Time Profiler, we see the heaviest call stack)
56 |
57 | ### ↔️ Inspection Head
58 | A selector placed at a specific time in the trace.Selects all traced events or intervals occurring at that time.
59 |
60 | ## Demo time 👩🏻💻
61 |
62 | ## Profiling Tips
63 |
64 | - Time Profiler shows how your app is spending time
65 | - Check main thread when responsiveness issues occur
66 | - Profile with difficult workloads or older devices
67 | - Instruments supports all platforms and the simulator. But watch out when using the simulator. 👀
68 | - Gives you trends, are things getting faster or slower? Observes all the threads in your app at a fixed interval of time and correlates the information.
69 |
70 | ## Try it out
71 |
72 | 10 min - Take out an Xcode project (maybe your final project 😀) and run the Time Profiler. See if everything looks good so far.
73 |
74 | ## Unit Testing Asynchronous Operations
75 |
76 | ### Synchronous Operation Testing
77 | Unit testing is most commonly applied to __*synchronous*__ operations because their outputs can be observed and validated immediately after invoking the function under test.
78 |
79 | Whether the output is a function return value, a state change, or the result of methods invoked on a dependency, all of these results occur right away and in the same thread.
80 |
81 | And, with __*synchronous*__ operations, when you write the assertions in the `Then` phase of your unit test, you are reasonably guaranteed that the outputs have already been set, so you can safely compare *actual* results against your *expected* ones.
82 |
83 | Simple. Only one thread. And no worries that your outputs might not be set prior to test completion.
84 |
85 | ### Asynchronous Operation Testing
86 | However, modern iOS development requires a great deal of __*asynchronous*__ operations in which results might not come immediately after a function is invoked.
87 |
88 | __*Asynchronous*__ operations are operations that do not execute directly within the current flow of code. This might be because they run:
89 | - on a different thread
90 | - in a delegate method
91 | - in a callback
92 |
93 | Key examples:
94 | - Networking (most common)
95 | - Core Data
96 | - Resource-expensive screen drawing code or events
97 |
98 | Asynchronous operations are typically developed in one of two ways:
99 | - Completion handler block
100 | - Delegate method
101 |
102 | Networking is the most common __*asynchronous*__ operation. Fetching data from remote web services has latency — it takes time to for signals to travel across the globe — and has many variables that can result in errors or delays.
103 |
104 |
105 |
106 | ### Benefits & Challenges
107 | Testing __*asynchronous*__ code comes with the benefit of uncovering poor design decisions and facilitating clean implementations.
108 |
109 | The core challenge is that, in typical unit tests, a test is considered over as soon as its function returns.
110 |
111 | With __*asynchronous*__ operations:
112 | - Functions do not return their result to the caller immediately but deliver it later via callback functions, blocks, notifications, or similar mechanisms, which makes testing more difficult.
113 | - When the function under test returns, any __*asynchronous*__ code will be ignored because it will run after the test has already finished.
114 |
115 | This makes unit testing __*difficult*__ because results can be unpredictable: In the `Then` phase of your unit test, the results may or may not have been set to the outputs for you to observe and verify. When you write your assertions, the test may pass this time (if the outputs have been set), but fail at another time (if the outputs haven’t been set).
116 |
117 | It can also result in __*false positives.*__
118 |
119 | As a result, asynchronous testing requires special handling.
120 |
121 |
124 |
125 | ### Expectations
126 | Fortunately, Xcode has built-in support to help with unit testing of __*asynchronous*__ operations.
127 |
128 | To test that __*asynchronous*__ operations behave as expected, you create one or more **Expectations** within your test, and then __*fulfill*__ those expectations when the __*asynchronous*__ operation completes successfully.
129 |
130 | Apple describes the `XCTestExpectation` class as "An expected outcome in an asynchronous test."
131 |
132 | ```Swift
133 | class XCTestExpectation : NSObject
134 | ```
135 |
136 | ...and the `XCTestExpectation` class's `fulfill()` function is simply described as "Marks the expectation as having been met."
137 |
138 |
139 | ```Swift
140 | func fulfill()
141 | ```
142 |
143 | > Note that it is an error to call the `fulfill()` method on an expectation that has already been fulfilled, or when the test case that vended the expectation has already completed.
144 |
145 |
146 | ### Example Scenario
147 | Steps required to unit test __*asynchronous*__ operations will vary depending on the function(s) under test.
148 |
149 | In general, when using the `XCTestExpectation` class, your test method waits until all expectations are fulfilled or a specified timeout expires.
150 |
151 | To illustrate a common scenario, here are the general steps you would execute to create a unit test for a background download task using an instance of the the `XCTestExpectation` class: 1
152 |
153 | 1. Create a new instance of `XCTestExpectation`.
154 |
155 | 2. Use URLSession's `dataTask(with:)` method to create a background data task that executes your download work on a background thread.
156 |
157 | 3. After starting the data task, use the `wait(for expectations:_)` function of the `XCtest` class — with the timeout parameter that you specify — to set how long the main thread will wait for the expectation to be fulfilled.
158 |
159 | ```Swift
160 | /*!
161 | * @method -waitForExpectations:timeout:
162 | * Wait on a group of expectations for up to the specified timeout. May return early based on fulfillment
163 | * of the waited on expectations.
164 | */
165 | open func wait(for expectations: [XCTestExpectation], timeout seconds: TimeInterval)
166 | ```
167 |
168 | 4. When the data task completes, its `completion handler` verifies that the downloaded data is non-nil, and fulfills the expectation by calling its` fulfill()` method to indicate that the background task completed successfully.
169 |
170 | #### Successful Completion
171 | The fulfillment of the expectation on the background thread provides a point of synchronization to indicate that the background task is complete. As long as the background task fulfills the expectation within the duration specified in the timeout parameter, this test method will pass.
172 |
173 | #### Unsuccessful Completion
174 | There are two ways for the test to fail:
175 | - The data returned to the completion handler is `nil`, causing `XCTAssertNotNil(_:_:file:line:)` to trigger a test failure.
176 | - The data task does not call its completion handler before the timeout expires, perhaps because of a slow network connection or other data retrieval problem. As a result, the expectation is not fulfilled before the wait timeout expires, triggering a test failure.
177 |
178 |
189 |
190 |
191 |
202 |
203 | ## In Class Activity I (60 min)
204 |
205 | ### Individually
206 | In the [starter app](https://github.com/Make-School-Labs/StarterApp-MOB-2.4-L10), a previous developer created a `testDownloadWebData()` function to unit test a background data task. However, that function is missing critical functionality.
207 |
208 | Your task is to complete the `testDownloadWebData()` function so that it successfully validates its targeted background task.
209 |
210 | 1. Complete the Code
211 |
212 | - find the `//TODO:`s left in the function and add or change whatever is needed (*see Example Scenario above for clues*)
213 |
214 | 2. Run the code and examine results
215 |
216 | - What happened? Why?
217 |
218 | 3. Apply any additional required fixes
219 |
220 | - Run it again...
221 |
222 | 4. Make it fail
223 |
224 | Review the Successful and Unsuccessful Completion notes in the Example Scenario above.
225 |
226 | - reduce timeout to 0.1
227 |
228 |
229 | ## Additional Resources
230 |
231 | 1. [Slides](https://docs.google.com/presentation/d/1rIQGcpl-siO-VelTIb3J8qH9fVIk3hNswbwjS02TK80/edit#slide=id.p)
232 | 2. [Testing Asynchronous Operations with Expectations - from Apple](https://developer.apple.com/documentation/xctest/asynchronous_tests_and_expectations/testing_asynchronous_operations_with_expectations)1
233 | 3. [XCTestExpectation - from Apple](https://developer.apple.com/documentation/xctest/xctestexpectation)
234 | 4. [iOS Unit Testing and UI Testing Tutorial - by raywenderlich](https://www.raywenderlich.com/960290-ios-unit-testing-and-ui-testing-tutorial)
235 |
--------------------------------------------------------------------------------
/Lessons/old_02-Grand-Central_Dispatch/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Make-School-Courses/MOB-2.3-Concurrency-Parallelism-in-iOS/0ae12a6aa027257fa2f2d34fb98a32d941586347/Lessons/old_02-Grand-Central_Dispatch/.DS_Store
--------------------------------------------------------------------------------
/Lessons/old_02-Grand-Central_Dispatch/assets/GCDPlay.playground/playground.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/Lessons/old_02-Grand-Central_Dispatch/assets/GCDPlay.playground/playground.xcworkspace/xcuserdata/thomas_vandegriff.xcuserdatad/UserInterfaceState.xcuserstate:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Make-School-Courses/MOB-2.3-Concurrency-Parallelism-in-iOS/0ae12a6aa027257fa2f2d34fb98a32d941586347/Lessons/old_02-Grand-Central_Dispatch/assets/GCDPlay.playground/playground.xcworkspace/xcuserdata/thomas_vandegriff.xcuserdatad/UserInterfaceState.xcuserstate
--------------------------------------------------------------------------------
/Lessons/old_04-xxx/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Make-School-Courses/MOB-2.3-Concurrency-Parallelism-in-iOS/0ae12a6aa027257fa2f2d34fb98a32d941586347/Lessons/old_04-xxx/.DS_Store
--------------------------------------------------------------------------------
/Lessons/old_04-xxx/Readme.md:
--------------------------------------------------------------------------------
1 | # Lesson Title
2 |
3 | ## Minute-by-Minute [OPTIONAL]
4 |
5 | | **Elapsed** | **Time** | **Activity** |
6 | | ----------- | --------- | ------------------------- |
7 | | 0:00 | 0:05 | Objectives |
8 | | 0:05 | 0:15 | Overview |
9 | | 0:20 | 0:45 | In Class Activity I |
10 | | 1:05 | 0:10 | BREAK |
11 | | 1:15 | 0:45 | In Class Activity II |
12 | | TOTAL | 2:00 | |
13 |
14 | ## Why you should know this or industry application (optional) (5 min)
15 |
16 | Explain why students should care to learn the material presented in this class.
17 |
18 | ## Learning Objectives (5 min)
19 |
20 | 1. Identify and describe
21 | 1. Define
22 | 1. Design
23 | 1. Implement
24 |
25 | ## Initial Exercise (15 min)
26 |
27 | - Funny comic
28 | - Prime the Pump (e.g. think and jot, think pair share, etc)
29 | - Productivity Tip/Tool
30 | - Review of current event (e.g. tech news relevant to your track/topic)
31 | - Quiz on homework or topic(s) of past class
32 | - Concept Test
33 |
34 | ## Overview/TT I (20 min)
35 |
36 |
47 |
48 |
49 | ##### Inferring QoS priority
50 |
51 |
52 |
53 | ### Creating Serial & Concurrent Queues
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 | < recall from previous lesson >
62 | It's easy to create a `DispatchQueue`. This example creates a new `DispatchQueue` called `myQueue` with a *label* (identifier) of `"com.makeschool.mycoolapp.networking"`:
63 |
64 | ```Swift
65 | let myQueue = DispatchQueue(label: "com.makeschool.mycoolapp.networking")
66 | ```
67 |
68 |
69 |
70 |
71 |
72 |
73 | ```Swift
74 | let myQueue = DispatchQueue(label: "com.makeschool.mycoolapp.networking", attributes: .concurrent)
75 | ```
76 |
77 |
78 | #### Custom Queues
79 |
80 |
81 | #### Default Queues
82 |
83 |
84 |
85 |
86 |
87 | #### Issues
88 |
89 |
90 |
91 |
94 |
95 |
96 | Another way that apps consume too many threads is by creating too many private concurrent dispatch queues. Because each dispatch queue consumes thread resources, creating additional concurrent dispatch queues exacerbates the thread consumption problem. Instead of creating private concurrent queues, submit tasks to one of the global concurrent dispatch queues. For serial tasks, set the target of your serial queue to one of the global concurrent queues. That way, you can maintain the serialized behavior of the queue while minimizing the number of separate queues creating threads.
97 |
98 | https://developer.apple.com/documentation/dispatch/dispatchqueue
99 |
100 |
101 |
104 |
105 |
106 | > Note — When designing tasks for concurrent execution, do not call methods that block the current thread of execution. When a task scheduled by a concurrent dispatch queue blocks a thread, the system creates additional threads to run other queued concurrent tasks. If too many tasks block, the system may run out of threads for your app.
107 |
108 | https://developer.apple.com/documentation/dispatch/dispatchqueue
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 | ## In Class Activity I (20 min)
119 |
120 |
123 |
124 |
125 |
126 |
127 | ## In Class Activity I (30 min)
128 |
129 | - I do, We do, You do
130 | - Reading & Discussion Questions in small groups
131 | - Draw a picture/diagram
132 | - Complete Challenges solo or in pair
133 | - Q&A about tutorials
134 | - Pair up and code review
135 | - Pair program
136 | - Formative assessment
137 | - Form into groups
138 | - etc (get creative :D)
139 |
140 | ## Overview/TT II (optional) (20 min)
141 |
142 | ## In Class Activity II (optional) (30 min)
143 |
144 | ## After Class
145 | 1. Research:
146 | -
147 | 2. Assignment:
148 | -
149 |
150 | ## Wrap Up (5 min)
151 |
152 | - Continue working on your current tutorial
153 | - Complete reading
154 | - Complete challenges
155 |
156 | ## Additional Resources
157 |
158 | 1. [Slides]()
159 | 2. []()
160 | 3. []()
161 | 4. []()
162 | 5. []()
163 |
--------------------------------------------------------------------------------
/Lessons/old_0x-Operations-Pt1/Readme.md:
--------------------------------------------------------------------------------
1 | # Operations (Part 1)
2 |
3 | ## Minute-by-Minute
4 |
5 | | **Elapsed** | **Time** | **Activity** |
6 | | ----------- | --------- | ------------------------- |
7 | | 0:00 | 0:05 | Objectives |
8 | | 0:05 | 0:20 | Intro to Operations (TT I) |
9 | | 0:20 | 0:45 | In Class Activity I |
10 | | 1:05 | 0:10 | BREAK |
11 | | 1:15 | 0:45 | In Class Activity II |
12 | | TOTAL | 2:00 | |
13 |
14 | ## Why you should know this
15 |
16 | From the start of this course, we've called out that Grand Central Dispatch (GCD) and Operations are the two built-in APIs from Apple that you use in iOS to manage concurrent tasks (as opposed to working with threads directly).
17 |
18 | We have also mentioned that...
19 |
20 | - Both technologies are designed to encapsulate units of work and dispatch them for execution.
21 | - Operations are build on top of GCD.
22 | - Apple advises developers to use the highest level of abstraction that is available (which is Operations).
23 | - Most developers implement a combination of GCD and Operations, depending on which suits their specific requirements.
24 |
25 | But Operations are not without their own challenges and pitfalls.
26 |
27 | As a developer, you need to know:
28 |
29 | - The benefits Operations offer — as well as their challenges and pitfalls.
30 | - The differences between GCD and Operations.
31 | - Under which circumstances might Operations be a better solution than GCD.
32 |
33 | ## Learning Objectives (5 min)
34 |
35 | 1. Identify and describe
36 | 1. Define
37 | 1. Design
38 | 1. Implement
39 |
40 |
48 |
49 |
50 | ## Initial Exercise (15 min)
51 |
52 |
58 |
59 | ## Intro to Operations (20 min)
60 |
61 | ### What are they?
62 |
63 | `Operation` (formerly called `NSOperation`) is a class that allows you to encapsulate (wrap) a unit of work into a package you can execute at some time in the future.
64 |
65 | `Operation` is an *abstract* class that represents the code and data associated with a single task.
66 |
67 | Key attributes of Operations:
68 | - Higher level of abstraction over GCD
69 | - Object-oriented (vs functions/closures in GCD)
70 | - Execute concurrently — but can be serial by using dependencies
71 | - An Operation describes a single unit of work
72 | - Offer more developer control (than GCD):
73 | - Can be cancelled
74 | - Have priorities (veryLow, Low, normal, high, veryHigh)
75 |
76 |
77 | ### Why use them?
78 | The Operation class offers a number of compelling benefits over GCD:
79 |
80 | **Dependencies** — Dependencies enables developers to execute tasks in a specific order. An operation is ready when every dependency has finished executing.
81 |
82 | By default, an operation object with dependencies is not considered ready until all of its dependent operation objects have finished executing. Once the last dependent operation finishes, the operation object becomes ready and able to execute.
83 |
84 | **KVO-Compliant** — `Operation` and `OperationQueue` classes have a number of properties that can be observed using KVO (Key Value Observing).
85 |
86 | This allows you to monitor the *state* 1 of an operation or operation queue.
87 |
88 | **Pause, Cancel, Resume** — Operations can be paused, resumed, and cancelled.
89 |
90 | Once you dispatch a task using Grand Central Dispatch, you no longer have control or insight into the execution of that task. The NSOperation API is more flexible in that respect, giving the developer control over the operation's life cycle.
91 |
92 | **Developer Control** — `Operation` and `OperationQueue` classes also give you, as a developer, more control:
93 |
94 | - For an `OperationQueue`, you can specify the __*maximum number of queued operations*__ that can run simultaneously. This makes it easy to (a) control how many operations run at the same time or (b) to create a serial operation queue.
95 |
96 | - For subclasses of `Operation`, you can configure the __*execution priority*__ level of an operation in an operation queue. 1
97 |
98 | 1 *Details on operation state, KVO properties, and priority levels coming up later...*
99 |
100 | ### How do Operations work?
101 | Because the Operation class is an abstract class, you do not use it directly. Instead, you subclass it or use one of the system-defined subclasses (`NSInvocationOperation` or `BlockOperation`) to perform the actual task.
102 |
103 | There are two ways to execute operations:
104 |
105 | **Operation Queues** — Typically, you execute operations by adding them to an operation queue — an instance of the `OperationQueue` class).
106 |
107 | An operation queue executes its operations either __*directly*__ — by running them on secondary threads — or __*indirectly*__ using the `libdispatch` library (aka, GCD).
108 |
109 | > *More on OperationQueues coming up...*
110 |
111 | **Start method** — You can also choose *not* to use an `OperationQueue` and execute an operation yourself by calling its `start()` method directly from your code.
112 |
113 | Because starting an operation that is not in the ready state triggers an exception, executing operations manually puts additional burden on your code to handle state changes if you choose to call an operation's `start()` method directly.
114 |
115 | > *Note that later we'll see that the `isReady` property reports on the operation’s readiness.*
116 |
117 | **Some things to note**
118 |
119 | - Despite being abstract, the base implementation of `Operation` does include significant logic to coordinate the safe execution of your task. The presence of this built-in logic allows you to focus on the actual implementation of your task, rather than on the glue code needed to ensure it works correctly with other system objects.
120 |
121 | - An operation object is a "single-shot object" — that is, it executes its task once and cannot be used to execute it again.
122 |
123 | ### How to use them?
124 |
125 |
126 |
127 |
128 |
129 |
133 |
134 |
135 |
136 |
137 |
156 |
157 |
158 |
159 | ## In Class Activity I (30 min)
160 |
161 | - I do, We do, You do
162 | - Reading & Discussion Questions in small groups
163 | - Draw a picture/diagram
164 | - Complete Challenges solo or in pair
165 | - Q&A about tutorials
166 | - Pair up and code review
167 | - Pair program
168 | - Formative assessment
169 | - Form into groups
170 | - etc (get creative :D)
171 |
172 | ## Overview/TT II (20 min)
173 |
174 | ## In Class Activity II (30 min)
175 |
176 |
177 |
178 | ## After Class
179 | 1. Research:
180 | -
181 | 2. Assignment:
182 | -
183 |
184 | ## Wrap Up (5 min)
185 |
186 |
187 | - Complete reading
188 | - Complete challenges
189 |
190 | ## Additional Resources
191 |
192 | 1. [Slides]()
193 | 2. [Operation - Apple docs](https://developer.apple.com/documentation/foundation/operation)
194 | 3. [OperationQueue - Apple docs](https://developer.apple.com/documentation/foundation/operationqueue)
195 | 4. [Queue Priority - Apple docs](https://developer.apple.com/documentation/foundation/operation/1411204-queuepriority)
196 | 5. []()
197 |
--------------------------------------------------------------------------------
/Lessons/old_bdd/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Make-School-Courses/MOB-2.3-Concurrency-Parallelism-in-iOS/0ae12a6aa027257fa2f2d34fb98a32d941586347/Lessons/old_bdd/.DS_Store
--------------------------------------------------------------------------------
/Lessons/old_bdd/Readme.md:
--------------------------------------------------------------------------------
1 | # Behavior Driven Development
2 |
3 |
4 | ## Class Materials
5 |
6 | [Sample BDD Project]()
7 |
--------------------------------------------------------------------------------
/Lessons/old_bdd/assets/bdd.key:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Make-School-Courses/MOB-2.3-Concurrency-Parallelism-in-iOS/0ae12a6aa027257fa2f2d34fb98a32d941586347/Lessons/old_bdd/assets/bdd.key
--------------------------------------------------------------------------------
/Lessons/old_challenges-with-concurrency/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Make-School-Courses/MOB-2.3-Concurrency-Parallelism-in-iOS/0ae12a6aa027257fa2f2d34fb98a32d941586347/Lessons/old_challenges-with-concurrency/.DS_Store
--------------------------------------------------------------------------------
/Lessons/old_challenges-with-concurrency/Readme.md:
--------------------------------------------------------------------------------
1 | # Challenges with Concurrency
2 |
3 | ## Topics
4 | - Deadlocks
5 | - Priority Inversion
6 | - Race conditions
7 | - Critical Section
8 | - Mutual exclusion
9 | - Locks(mutex, semaphore)
10 |
11 | ## Class Material
12 |
13 | Slides:
14 |
15 | [Challenges with Concurrency](assets/concurrency-challenges.key)
16 |
--------------------------------------------------------------------------------
/Lessons/old_challenges-with-concurrency/assets/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Make-School-Courses/MOB-2.3-Concurrency-Parallelism-in-iOS/0ae12a6aa027257fa2f2d34fb98a32d941586347/Lessons/old_challenges-with-concurrency/assets/.DS_Store
--------------------------------------------------------------------------------
/Lessons/old_challenges-with-concurrency/assets/concurrency-challenges.key:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Make-School-Courses/MOB-2.3-Concurrency-Parallelism-in-iOS/0ae12a6aa027257fa2f2d34fb98a32d941586347/Lessons/old_challenges-with-concurrency/assets/concurrency-challenges.key
--------------------------------------------------------------------------------
/Lessons/old_challenges-with-concurrency/assets/concurrency-challenges.playground/Pages/CriticalSection.xcplaygroundpage/Contents.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 |
3 | // Identify the critical section
4 |
5 | func sleepOnTheBed() {}
6 | var roomIsAvailable = true
7 |
8 | // We booking rooms in a hotel
9 | // Enter if the room is available
10 | // Thread A ---->
11 | // Thread B ---->
12 | if (roomIsAvailable) {
13 | // Room is ocupado
14 | roomIsAvailable = false
15 | sleepOnTheBed()
16 | roomIsAvailable = true
17 | } else {
18 | // Room is not available, wait or do something else
19 | }
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/Lessons/old_challenges-with-concurrency/assets/concurrency-challenges.playground/Pages/Untitled Page 2.xcplaygroundpage/Contents.swift:
--------------------------------------------------------------------------------
1 | //: [Previous](@previous)
2 |
3 | import Foundation
4 |
5 | var x: Int = 100
6 | var y: Int = 200
7 |
8 |
9 | let swap = { (x: inout Int, y: inout Int) in
10 |
11 | let temp = x
12 | x = y
13 | y = temp
14 |
15 | }
16 |
17 | swap(&x, &y)
18 |
19 | let thread2 = Thread {
20 | swap(&y, &x)
21 | print(x, y)
22 | }
23 |
24 | thread2.start()
25 |
26 | print("X: \(x), Y: \(y)")
27 | //: [Next](@next)
28 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/Lessons/old_challenges-with-concurrency/assets/concurrency-challenges.playground/Pages/Untitled Page 2.xcplaygroundpage/Sources/Sync.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 |
3 |
4 | public func syncResource(_ m: inout pthread_mutex_t, execute: () -> R) -> R {
5 | pthread_mutex_lock(&m)
6 | defer { pthread_mutex_unlock(&m) }
7 | return execute()
8 | }
9 |
--------------------------------------------------------------------------------
/Lessons/old_challenges-with-concurrency/assets/concurrency-challenges.playground/contents.xcplayground:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/Lessons/old_challenges-with-concurrency/assets/concurrency-challenges.playground/playground.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/Lessons/old_challenges-with-concurrency/assets/concurrency-challenges.playground/playground.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/Lessons/old_challenges-with-concurrency/assets/concurrency-challenges.playground/playground.xcworkspace/xcuserdata/gordoneliel.xcuserdatad/UserInterfaceState.xcuserstate:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Make-School-Courses/MOB-2.3-Concurrency-Parallelism-in-iOS/0ae12a6aa027257fa2f2d34fb98a32d941586347/Lessons/old_challenges-with-concurrency/assets/concurrency-challenges.playground/playground.xcworkspace/xcuserdata/gordoneliel.xcuserdatad/UserInterfaceState.xcuserstate
--------------------------------------------------------------------------------
/Lessons/old_challenges-with-concurrency/assets/concurrency-challenges.playground/playground.xcworkspace/xcuserdata/thomas_vandegriff.xcuserdatad/UserInterfaceState.xcuserstate:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Make-School-Courses/MOB-2.3-Concurrency-Parallelism-in-iOS/0ae12a6aa027257fa2f2d34fb98a32d941586347/Lessons/old_challenges-with-concurrency/assets/concurrency-challenges.playground/playground.xcworkspace/xcuserdata/thomas_vandegriff.xcuserdatad/UserInterfaceState.xcuserstate
--------------------------------------------------------------------------------
/Lessons/old_dispatch-queues/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Make-School-Courses/MOB-2.3-Concurrency-Parallelism-in-iOS/0ae12a6aa027257fa2f2d34fb98a32d941586347/Lessons/old_dispatch-queues/.DS_Store
--------------------------------------------------------------------------------
/Lessons/old_dispatch-queues/Readme.md:
--------------------------------------------------------------------------------
1 | # Dispatch Queues
2 |
3 |
4 | ## Topics
5 | - FIFO
6 | - DispatchQueue
7 | - Serial queues
8 | - Concurrent queues
9 | - Dispatch QOS
10 |
11 | ## Class Materials
12 |
13 | Slides:
14 |
15 | [Dispatch Queues, Challenges with Concurrency](assets/concurrency2.key)
16 |
17 |
18 | Grand Central Dispatch - Dispatch Queues & QOS:
19 |
20 | [Dispatch Queue - Playground](assets/GCDPlay.playground)
21 |
--------------------------------------------------------------------------------
/Lessons/old_dispatch-queues/assets/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Make-School-Courses/MOB-2.3-Concurrency-Parallelism-in-iOS/0ae12a6aa027257fa2f2d34fb98a32d941586347/Lessons/old_dispatch-queues/assets/.DS_Store
--------------------------------------------------------------------------------
/Lessons/old_dispatch-queues/assets/Concurrency2.key:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Make-School-Courses/MOB-2.3-Concurrency-Parallelism-in-iOS/0ae12a6aa027257fa2f2d34fb98a32d941586347/Lessons/old_dispatch-queues/assets/Concurrency2.key
--------------------------------------------------------------------------------
/Lessons/old_dispatch-queues/assets/GCDPlay.playground/Async Queue.xcplaygroundpage/Contents.swift:
--------------------------------------------------------------------------------
1 | //: [Previous](@previous)
2 |
3 | import Foundation
4 |
5 |
6 | let queue = DispatchQueue(label: "com.makeschool.queue")
7 |
8 | queue.sync {
9 | for i in 0..<10 {
10 | print("🍎 ", i)
11 | }
12 | }
13 |
14 | for i in 100..<110 {
15 | print("🐳 ", i)
16 | }
17 |
18 |
19 | //: [Next](@next)
20 |
--------------------------------------------------------------------------------
/Lessons/old_dispatch-queues/assets/GCDPlay.playground/AsyncBackgroundAndUtility.xcplaygroundpage/Contents.swift:
--------------------------------------------------------------------------------
1 | //: [Previous](@previous)
2 |
3 | import Foundation
4 |
5 | let queue1 = DispatchQueue(label: "com.makeschool.queue1", qos: .userInitiated)
6 | let queue2 = DispatchQueue(label: "com.makeschool.queue2", qos: .utility)
7 |
8 | queue1.async {
9 | for i in 0..<10 {
10 | print("🍎 ", i)
11 | }
12 | }
13 |
14 | queue2.async {
15 | for i in 0..<10 {
16 | print("🐳 ", i)
17 | }
18 | }
19 |
20 |
21 | //: [Next](@next)
22 |
--------------------------------------------------------------------------------
/Lessons/old_dispatch-queues/assets/GCDPlay.playground/Pages/Async Queue.xcplaygroundpage/Contents.swift:
--------------------------------------------------------------------------------
1 | //: [Previous](@previous)
2 |
3 | import Foundation
4 |
5 |
6 | let queue = DispatchQueue(label: "com.makeschool.queue")
7 |
8 | queue.async {
9 | for i in 0..<10 {
10 | print("🍎 ", i)
11 | }
12 | }
13 |
14 | for i in 100..<110 {
15 | print("🐳 ", i)
16 | }
17 |
18 |
19 | //: [Next](@next)
20 |
--------------------------------------------------------------------------------
/Lessons/old_dispatch-queues/assets/GCDPlay.playground/Pages/AsyncBackgroundAndUtility.xcplaygroundpage/Contents.swift:
--------------------------------------------------------------------------------
1 | //: [Previous](@previous)
2 |
3 | import Foundation
4 | import PlaygroundSupport
5 |
6 | PlaygroundPage.current.needsIndefiniteExecution = true
7 |
8 | let queue1 = DispatchQueue(label: "com.makeschool.queue1", qos: .background)
9 | let queue2 = DispatchQueue(label: "com.makeschool.queue2", qos: .utility)
10 |
11 | queue1.async {
12 | for i in 0..<10 {
13 | print("🍎 ", i)
14 | }
15 | }
16 |
17 | queue2.async {
18 | for i in 100..<110 {
19 | print("🐳 ", i)
20 | }
21 | }
22 |
23 |
24 | //: [Next](@next)
25 |
--------------------------------------------------------------------------------
/Lessons/old_dispatch-queues/assets/GCDPlay.playground/Pages/AsyncUserInitiated.xcplaygroundpage/Contents.swift:
--------------------------------------------------------------------------------
1 | //: [Previous](@previous)
2 |
3 | import Foundation
4 |
5 | let queue1 = DispatchQueue(label: "com.makeschool.queue1", qos: .userInitiated)
6 | let queue2 = DispatchQueue(label: "com.makeschool.queue2", qos: .userInitiated)
7 |
8 | queue1.async {
9 | for i in 0..<10 {
10 | print("🍎 ", i)
11 | }
12 | }
13 |
14 | queue2.async {
15 | for i in 100..<110 {
16 | print("🐳 ", i)
17 | }
18 | }
19 |
20 |
21 | //: [Next](@next)
22 |
--------------------------------------------------------------------------------
/Lessons/old_dispatch-queues/assets/GCDPlay.playground/Pages/AsyncUserInitiatedAndUtility.xcplaygroundpage/Contents.swift:
--------------------------------------------------------------------------------
1 | //: [Previous](@previous)
2 |
3 | import Foundation
4 |
5 | let queue1 = DispatchQueue(label: "com.makeschool.queue1", qos: .userInitiated)
6 | let queue2 = DispatchQueue(label: "com.makeschool.queue2", qos: .utility)
7 |
8 | queue1.async {
9 | for i in 0..<10 {
10 | print("🍎 ", i)
11 | }
12 | }
13 |
14 | queue2.async {
15 | for i in 100..<110 {
16 | print("🐳 ", i)
17 | }
18 | }
19 |
20 |
21 | //: [Next](@next)
22 |
--------------------------------------------------------------------------------
/Lessons/old_dispatch-queues/assets/GCDPlay.playground/Pages/AsyncUserInitiatedAndUtitlityAndMain.xcplaygroundpage/Contents.swift:
--------------------------------------------------------------------------------
1 | //: Playground - noun: a place where people can play
2 |
3 | import UIKit
4 |
5 | let queue1 = DispatchQueue(label: "com.makeschool.queue1", qos: .userInitiated)
6 | let queue2 = DispatchQueue(label: "com.makeschool.queue2", qos: .utility)
7 |
8 | queue1.async {
9 | for i in 0..<10 {
10 | print("🍎 ", i)
11 | }
12 | }
13 | queue2.async {
14 | for i in 100..<110 {
15 | print("🐳 ", i)
16 | }
17 | }
18 |
19 | for i in 100..<110 {
20 | print("🍑 ", i)
21 | }
22 |
23 | //: [Next](@next)
24 |
--------------------------------------------------------------------------------
/Lessons/old_dispatch-queues/assets/GCDPlay.playground/Pages/Concurrent.xcplaygroundpage/Contents.swift:
--------------------------------------------------------------------------------
1 | //: [Previous](@previous)
2 |
3 | import Foundation
4 |
5 | let queue = DispatchQueue(label: "sample.concurrent", qos: .utility, attributes: .concurrent)
6 |
7 | queue.async {
8 | for i in 0..<10 {
9 | print("🍎 ", i)
10 | }
11 | }
12 | queue.async {
13 | for i in 100..<110 {
14 | print("🐳 ", i)
15 | }
16 | }
17 |
18 | queue.async {
19 | for i in 1000..<1010 {
20 | print("🍑 ", i)
21 | }
22 | }
23 |
24 | //: [Next](@next)
25 |
--------------------------------------------------------------------------------
/Lessons/old_dispatch-queues/assets/GCDPlay.playground/Pages/DispatchQueueSync*.xcplaygroundpage/Contents.swift:
--------------------------------------------------------------------------------
1 | //: [Previous](@previous)
2 |
3 | import Foundation
4 | import UIKit
5 |
6 | let queue = DispatchQueue(
7 | label: "sample.concurrent",
8 | qos: .userInitiated,
9 | attributes: .concurrent
10 | )
11 |
12 | queue.async {
13 | print("I am \(Thread.current) an async thread")
14 | print(45)
15 | }
16 |
17 | queue.async {
18 | print("I am \(Thread.current) a sync thread")
19 | Thread.sleep(forTimeInterval: 10)
20 | }
21 |
22 | print("I am on the main thread - \(Thread.current)")
23 |
24 | //: [Next](@next)
25 |
--------------------------------------------------------------------------------
/Lessons/old_dispatch-queues/assets/GCDPlay.playground/Pages/SameQueueAsync.xcplaygroundpage/Contents.swift:
--------------------------------------------------------------------------------
1 | //: Playground - noun: a place where people can play
2 |
3 | import UIKit
4 |
5 | // Same (serial) queue of execution
6 | let queue = DispatchQueue(label: "com.makeschool.queue1", qos: .utility)
7 |
8 | queue.async {
9 | for i in 0..<10 {
10 | print("🍎 ", i)
11 | }
12 | }
13 | queue.async {
14 | for i in 100..<110 {
15 | print("🐳 ", i)
16 | }
17 | }
18 |
19 | queue.async {
20 | for i in 1000..<1010 {
21 | print("🍑 ", i)
22 | }
23 | }
24 |
25 | //: [Next](@next)
26 |
--------------------------------------------------------------------------------
/Lessons/old_dispatch-queues/assets/GCDPlay.playground/Pages/Sync Queue.xcplaygroundpage/Contents.swift:
--------------------------------------------------------------------------------
1 | //: [Previous](@previous)
2 |
3 | import Foundation
4 |
5 |
6 | let queue = DispatchQueue(label: "com.makeschool.queue")
7 |
8 | queue.sync {
9 | for i in 0..<10 {
10 | print("🍎 ", i)
11 | }
12 | }
13 |
14 | for i in 100..<110 {
15 | print("🐳 ", i)
16 | }
17 |
18 |
19 | //: [Next](@next)
20 |
--------------------------------------------------------------------------------
/Lessons/old_dispatch-queues/assets/GCDPlay.playground/contents.xcplayground:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/Lessons/old_dispatch-queues/assets/GCDPlay.playground/playground.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/Lessons/old_dispatch-queues/assets/GCDPlay.playground/playground.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/Lessons/old_dispatch-queues/assets/GCDPlay.playground/playground.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | BuildSystemType
6 | Latest
7 |
8 |
9 |
--------------------------------------------------------------------------------
/Lessons/old_dispatch-queues/assets/GCDPlay.playground/playground.xcworkspace/xcuserdata/adrianagonzalezmartinez.xcuserdatad/UserInterfaceState.xcuserstate:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Make-School-Courses/MOB-2.3-Concurrency-Parallelism-in-iOS/0ae12a6aa027257fa2f2d34fb98a32d941586347/Lessons/old_dispatch-queues/assets/GCDPlay.playground/playground.xcworkspace/xcuserdata/adrianagonzalezmartinez.xcuserdatad/UserInterfaceState.xcuserstate
--------------------------------------------------------------------------------
/Lessons/old_dispatch-queues/assets/GCDPlay.playground/playground.xcworkspace/xcuserdata/gordoneliel.xcuserdatad/UserInterfaceState.xcuserstate:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Make-School-Courses/MOB-2.3-Concurrency-Parallelism-in-iOS/0ae12a6aa027257fa2f2d34fb98a32d941586347/Lessons/old_dispatch-queues/assets/GCDPlay.playground/playground.xcworkspace/xcuserdata/gordoneliel.xcuserdatad/UserInterfaceState.xcuserstate
--------------------------------------------------------------------------------
/Lessons/old_dispatch-queues/assets/GCDPlay.playground/playground.xcworkspace/xcuserdata/gordoneliel.xcuserdatad/WorkspaceSettings.xcsettings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | BuildLocationStyle
6 | UseAppPreferences
7 | BuildSystemType
8 | Latest
9 | CustomBuildLocationType
10 | RelativeToDerivedData
11 | DerivedDataLocationStyle
12 | Default
13 | EnabledFullIndexStoreVisibility
14 |
15 | IssueFilterStyle
16 | ShowActiveSchemeOnly
17 | LiveSourceIssuesEnabled
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/Lessons/old_dispatch-queues/assets/GCDPlay.playground/playground.xcworkspace/xcuserdata/thomas_vandegriff.xcuserdatad/UserInterfaceState.xcuserstate:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Make-School-Courses/MOB-2.3-Concurrency-Parallelism-in-iOS/0ae12a6aa027257fa2f2d34fb98a32d941586347/Lessons/old_dispatch-queues/assets/GCDPlay.playground/playground.xcworkspace/xcuserdata/thomas_vandegriff.xcuserdatad/UserInterfaceState.xcuserstate
--------------------------------------------------------------------------------
/Lessons/old_executing-work-gcd/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Make-School-Courses/MOB-2.3-Concurrency-Parallelism-in-iOS/0ae12a6aa027257fa2f2d34fb98a32d941586347/Lessons/old_executing-work-gcd/.DS_Store
--------------------------------------------------------------------------------
/Lessons/old_executing-work-gcd/Readme.md:
--------------------------------------------------------------------------------
1 | # Executing Work in GCD
2 |
3 |
4 | ## Class Material
5 |
6 | Slides:
7 |
8 | [Executing Work in GCD](assets/executing-work-gcd.key)
9 |
--------------------------------------------------------------------------------
/Lessons/old_executing-work-gcd/assets/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Make-School-Courses/MOB-2.3-Concurrency-Parallelism-in-iOS/0ae12a6aa027257fa2f2d34fb98a32d941586347/Lessons/old_executing-work-gcd/assets/.DS_Store
--------------------------------------------------------------------------------
/Lessons/old_executing-work-gcd/assets/executing-work-gcd.key:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Make-School-Courses/MOB-2.3-Concurrency-Parallelism-in-iOS/0ae12a6aa027257fa2f2d34fb98a32d941586347/Lessons/old_executing-work-gcd/assets/executing-work-gcd.key
--------------------------------------------------------------------------------
/Lessons/old_interview-practice-problem-concurrency/Readme.md:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Make-School-Courses/MOB-2.3-Concurrency-Parallelism-in-iOS/0ae12a6aa027257fa2f2d34fb98a32d941586347/Lessons/old_interview-practice-problem-concurrency/Readme.md
--------------------------------------------------------------------------------
/Lessons/old_intro-to-testing/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Make-School-Courses/MOB-2.3-Concurrency-Parallelism-in-iOS/0ae12a6aa027257fa2f2d34fb98a32d941586347/Lessons/old_intro-to-testing/.DS_Store
--------------------------------------------------------------------------------
/Lessons/old_intro-to-testing/Readme.md:
--------------------------------------------------------------------------------
1 | # Introduction to Testing
2 |
3 | We learnt from our last lesson that tests are targets in an Xcode project. We are going to learn how to add tests to and existing Xcode project.
4 |
5 | ## Class Materials
6 |
7 | Slides:
8 |
9 | [Introduction to Testing](assets/intro-to-testing.key)
10 |
11 | ## Challenges
12 |
13 | Clone this repo and add tests:
14 |
15 | [Testing Sample Project](https://github.com/Product-College-Labs/basic-testing.git)
16 |
--------------------------------------------------------------------------------
/Lessons/old_intro-to-testing/assets/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Make-School-Courses/MOB-2.3-Concurrency-Parallelism-in-iOS/0ae12a6aa027257fa2f2d34fb98a32d941586347/Lessons/old_intro-to-testing/assets/.DS_Store
--------------------------------------------------------------------------------
/Lessons/old_intro-to-testing/assets/intro-testing.key:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Make-School-Courses/MOB-2.3-Concurrency-Parallelism-in-iOS/0ae12a6aa027257fa2f2d34fb98a32d941586347/Lessons/old_intro-to-testing/assets/intro-testing.key
--------------------------------------------------------------------------------
/Lessons/old_intro-to-testing/assets/target-membership.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Make-School-Courses/MOB-2.3-Concurrency-Parallelism-in-iOS/0ae12a6aa027257fa2f2d34fb98a32d941586347/Lessons/old_intro-to-testing/assets/target-membership.png
--------------------------------------------------------------------------------
/Lessons/old_intro-to-testing/assets/testable-import.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Make-School-Courses/MOB-2.3-Concurrency-Parallelism-in-iOS/0ae12a6aa027257fa2f2d34fb98a32d941586347/Lessons/old_intro-to-testing/assets/testable-import.png
--------------------------------------------------------------------------------
/Lessons/old_operations_1/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Make-School-Courses/MOB-2.3-Concurrency-Parallelism-in-iOS/0ae12a6aa027257fa2f2d34fb98a32d941586347/Lessons/old_operations_1/.DS_Store
--------------------------------------------------------------------------------
/Lessons/old_operations_1/Readme.md:
--------------------------------------------------------------------------------
1 | # Operations
2 |
3 | ## Topics
4 |
5 | - (NS)Operation
6 | - Operation Queues
7 | - Subclassing Operations
8 | - Custom Operation Queues
9 | - GCD vs Operations
10 |
11 | ## Class Materials
12 |
13 | Slides for class:
14 |
15 | [Operations Slides](assets/operations.key)
16 |
17 | Operations Playground:
18 |
19 | [Operations Playground](assets/operations.playground)
20 |
21 |
22 | ## Challenges
23 |
24 | [GCDAsyncImage](https://github.com/Product-College-Labs/GCDAsyncImage)
25 |
--------------------------------------------------------------------------------
/Lessons/old_operations_1/assets/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Make-School-Courses/MOB-2.3-Concurrency-Parallelism-in-iOS/0ae12a6aa027257fa2f2d34fb98a32d941586347/Lessons/old_operations_1/assets/.DS_Store
--------------------------------------------------------------------------------
/Lessons/old_operations_1/assets/operations.key:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Make-School-Courses/MOB-2.3-Concurrency-Parallelism-in-iOS/0ae12a6aa027257fa2f2d34fb98a32d941586347/Lessons/old_operations_1/assets/operations.key
--------------------------------------------------------------------------------
/Lessons/old_operations_1/assets/operations.playground/Contents.swift:
--------------------------------------------------------------------------------
1 | import UIKit
2 | import PlaygroundSupport
3 |
4 | PlaygroundPage.current.needsIndefiniteExecution = true
5 |
6 | // Queues
7 | let operationQueue = OperationQueue()
8 | operationQueue.qualityOfService = .userInitiated
9 |
10 | // Equivalent of GCD main queue
11 | let mainOp = OperationQueue.main
12 |
13 | // Using blocks with OperationQueue
14 | // Scheduling one off tasks
15 | // Cant observe individual operations, like with a completion handler for finished
16 |
17 | operationQueue.addOperation {
18 | //Expensive op
19 | Thread.sleep(forTimeInterval: 3)
20 | print("Doing 1")
21 | }
22 |
23 | operationQueue.addOperation {
24 | Thread.sleep(forTimeInterval: 2)
25 | print("Doing 2")
26 | }
27 |
28 | operationQueue.operationCount
29 |
30 | /*:
31 | # BlockOperations
32 | # Can observe when operation is completed through completion blocks
33 | */
34 |
35 | let downloadQueue = OperationQueue()
36 |
37 | let downloadOperation = BlockOperation {
38 | // perform download here
39 | Thread.sleep(forTimeInterval: 2)
40 | print("downloading")
41 | }
42 | downloadOperation.queuePriority = .high
43 |
44 | downloadOperation.addExecutionBlock {
45 | Thread.sleep(forTimeInterval: 2)
46 | print("parsing JSON")
47 | }
48 |
49 | let updateDBOperation = BlockOperation {
50 | // update DB here
51 | Thread.sleep(forTimeInterval: 4)
52 | print("update DB")
53 | }
54 |
55 | // update DB after download completes
56 | updateDBOperation.addDependency(downloadOperation)
57 | // add operations to queue to get them started
58 | downloadQueue.addOperations([downloadOperation, updateDBOperation], waitUntilFinished: false)
59 |
60 |
61 | //: Subclassing Operations
62 |
63 | class MyOperation: Operation {
64 |
65 | override func main() {
66 | Thread.sleep(forTimeInterval: 3)
67 | if !self.isCancelled {
68 | print("MyOp Started")
69 | Thread.sleep(forTimeInterval: 5)
70 | print(Thread.current)
71 | }else {
72 | print("My Op Cancelled")
73 | }
74 | }
75 | }
76 |
77 | let myOp = MyOperation()
78 |
79 | myOp.completionBlock = {
80 | print("MyOp Completed")
81 | }
82 |
83 | operationQueue.addOperation(myOp)
84 |
85 | //myOp.cancel()
86 |
87 | //: [Next Page] @(next)
88 |
89 |
--------------------------------------------------------------------------------
/Lessons/old_operations_1/assets/operations.playground/contents.xcplayground:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/Lessons/old_operations_1/assets/operations.playground/playground.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/Lessons/old_operations_1/assets/operations.playground/playground.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/Lessons/old_operations_1/assets/operations.playground/playground.xcworkspace/xcuserdata/gordoneliel.xcuserdatad/UserInterfaceState.xcuserstate:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Make-School-Courses/MOB-2.3-Concurrency-Parallelism-in-iOS/0ae12a6aa027257fa2f2d34fb98a32d941586347/Lessons/old_operations_1/assets/operations.playground/playground.xcworkspace/xcuserdata/gordoneliel.xcuserdatad/UserInterfaceState.xcuserstate
--------------------------------------------------------------------------------
/Lessons/old_operations_1/assets/operations.playground/playground.xcworkspace/xcuserdata/thomas_vandegriff.xcuserdatad/UserInterfaceState.xcuserstate:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Make-School-Courses/MOB-2.3-Concurrency-Parallelism-in-iOS/0ae12a6aa027257fa2f2d34fb98a32d941586347/Lessons/old_operations_1/assets/operations.playground/playground.xcworkspace/xcuserdata/thomas_vandegriff.xcuserdatad/UserInterfaceState.xcuserstate
--------------------------------------------------------------------------------
/Lessons/old_operations_1/assets/operations.playground/timeline.xctimeline:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/Lessons/old_operations_2/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Make-School-Courses/MOB-2.3-Concurrency-Parallelism-in-iOS/0ae12a6aa027257fa2f2d34fb98a32d941586347/Lessons/old_operations_2/.DS_Store
--------------------------------------------------------------------------------
/Lessons/old_operations_2/assets/operations.playground/playground.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/Lessons/old_operations_2/assets/operations.playground/playground.xcworkspace/xcuserdata/thomas_vandegriff.xcuserdatad/UserInterfaceState.xcuserstate:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Make-School-Courses/MOB-2.3-Concurrency-Parallelism-in-iOS/0ae12a6aa027257fa2f2d34fb98a32d941586347/Lessons/old_operations_2/assets/operations.playground/playground.xcworkspace/xcuserdata/thomas_vandegriff.xcuserdatad/UserInterfaceState.xcuserstate
--------------------------------------------------------------------------------
/Lessons/old_xcode-project-management/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Make-School-Courses/MOB-2.3-Concurrency-Parallelism-in-iOS/0ae12a6aa027257fa2f2d34fb98a32d941586347/Lessons/old_xcode-project-management/.DS_Store
--------------------------------------------------------------------------------
/Lessons/old_xcode-project-management/Readme.md:
--------------------------------------------------------------------------------
1 | # Xcode Project Management
2 |
3 | Have you every wanted to switch between your development, staging and production server in a click of a button?
4 | Have you ever wanted to have a free and paid version of your app using the same codebase? Do you need to create an internal test build?
5 |
6 | This lesson covers the basics of Xcode project infrastructure. We will learn about Xcode Schemes & Targets and leverage various tools in Xcode to improve our projects.
7 |
8 | ## Topics
9 | - Managing Schemes
10 | - Xcode project & workspace
11 | - Xcode Targets
12 | - xcconfig files
13 |
14 | ## Class Materials
15 |
16 | Slides:
17 |
18 | [Xcode Project Infrastructure](assets/xcode-project.key)
19 |
20 | ## Xcode Projects
21 |
22 | Each Xcode project is made up of a few components.
23 |
24 |
25 | ### Workspace
26 | This contains one or more related `projects`.
27 |
28 | 
29 |
30 | ### Project
31 | Projects contain source code, resources files, etc.
32 | Each project can contain one or more targets.
33 |
34 | ### Targets
35 |
36 | Targets define a list of build settings for a project.
37 | They contain a list of classes, resources, custom build scripts etc.. to include use when building a project.
38 | Targets are also used to separate different distributions channels for a project. Eg. I can have a project that has a production, development and testing target.
39 |
40 | *Target Use Case Example*
41 | For example, I can have a project with two targets a "free" build and an "paid" build that has extra features and capabilities like background iCloud syncing/healthkit/homekit integration.
42 |
43 | Targets offer a few benefits including:
44 |
45 | - A target can have multiple build time settings for separate distribution requirements.
46 | - Picking which classes or resources are added to which target.
47 | - Adding tests introduces a new target. This means you can pick and choose which files/resources to include for testing.
48 |
49 |
50 | *Examples of Targets*
51 | - Test targets
52 | - Application targets (Apps, Games)
53 | - Extension targets (Siri, Keyboard, Today)
54 | - Framework/Library
55 |
56 | ### Schemes
57 |
58 | A scheme defines what happens when you "Build", "Test", "Profile", etc.
59 | Every `target` has at least one scheme to `execute` a target.
60 | Schemes allow you to define environment variables and launch arguements.
61 | Schemes are tied to a build configuration file.
62 |
63 | A build scheme is a blueprint for an entire build process, a way of telling Xcode what build configurations you want to use to create the development, unit test, and production builds for a given target (framework or app bundle).
64 |
65 | A `Build configuration` is a specific group of build settings that can be applied to a target.
66 |
67 | *System Default Scheme and Build settings*
68 |
69 | Most app projects come with two build configurations and one build scheme. You get the debug and release build configurations along with a build scheme that runs the debug configuration for debugging purposes and the release configuration for archiving/submission.
70 |
71 | You can auto-create schemes for your targets by going to `Product > Scheme > Manage Schemes` and pressing "Autocreate Schemes Now"
72 |
73 | ## Activity
74 |
75 | Discuss use cases for using multiple schemes and targets.
76 |
77 |
78 |
79 | ## Challenges
80 |
81 | Create an iOS app with a Today Extension as an extra target.
82 |
83 |
84 | ## Resources
85 |
86 | [Xcode Schemes & Build Settings Tutorial - Julia Alumni](https://hackernoon.com/a-cleaner-way-to-organize-your-ios-debug-development-and-release-distributions-6b5eb6a48356)
87 |
--------------------------------------------------------------------------------
/Lessons/old_xcode-project-management/assets/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Make-School-Courses/MOB-2.3-Concurrency-Parallelism-in-iOS/0ae12a6aa027257fa2f2d34fb98a32d941586347/Lessons/old_xcode-project-management/assets/.DS_Store
--------------------------------------------------------------------------------
/Lessons/old_xcode-project-management/assets/target-membership.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Make-School-Courses/MOB-2.3-Concurrency-Parallelism-in-iOS/0ae12a6aa027257fa2f2d34fb98a32d941586347/Lessons/old_xcode-project-management/assets/target-membership.png
--------------------------------------------------------------------------------
/Lessons/old_xcode-project-management/assets/xcode-project.key:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Make-School-Courses/MOB-2.3-Concurrency-Parallelism-in-iOS/0ae12a6aa027257fa2f2d34fb98a32d941586347/Lessons/old_xcode-project-management/assets/xcode-project.key
--------------------------------------------------------------------------------
/Lessons/old_xcode-project-management/assets/xcworkspace.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Make-School-Courses/MOB-2.3-Concurrency-Parallelism-in-iOS/0ae12a6aa027257fa2f2d34fb98a32d941586347/Lessons/old_xcode-project-management/assets/xcworkspace.png
--------------------------------------------------------------------------------
/Lessons/old_xcode-project-management/assets/xcworkspace01.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Make-School-Courses/MOB-2.3-Concurrency-Parallelism-in-iOS/0ae12a6aa027257fa2f2d34fb98a32d941586347/Lessons/old_xcode-project-management/assets/xcworkspace01.png
--------------------------------------------------------------------------------
/Lessons/operations/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Make-School-Courses/MOB-2.3-Concurrency-Parallelism-in-iOS/0ae12a6aa027257fa2f2d34fb98a32d941586347/Lessons/operations/.DS_Store
--------------------------------------------------------------------------------
/Lessons/operations/assets/operations.playground/playground.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/Lessons/operations/assets/operations.playground/playground.xcworkspace/xcuserdata/thomas_vandegriff.xcuserdatad/UserInterfaceState.xcuserstate:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Make-School-Courses/MOB-2.3-Concurrency-Parallelism-in-iOS/0ae12a6aa027257fa2f2d34fb98a32d941586347/Lessons/operations/assets/operations.playground/playground.xcworkspace/xcuserdata/thomas_vandegriff.xcuserdatad/UserInterfaceState.xcuserstate
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # MOB-2.3 - Concurrency & Parallelism in iOS
2 |
3 | ## Course Description
4 | This course covers concurrency and parallelism in iOS to optimize programming performance on mobile devices built with multiple cores. You will learn the foundation of Grand Central Dispatch, Operations and other tools to build applications that run multiple tasks simultaneously, optimizing resources.
5 |
6 | ## Prerequisites:
7 |
8 | [MOB 2.1](https://github.com/Make-School-Courses/MOB-2.1-Local-Persistence-in-iOS)
9 |
10 | ## Course Specifics
11 |
12 | **Course Delivery**: online | 7 weeks | 14 sessions
13 |
14 | **Course Credits**: 3 units | 37.5 Seat Hours | 75 Total Hours
15 |
16 | ## Learning Outcomes
17 |
18 | By the end of this course, you will be able to ...
19 |
20 | 1. Define and distinguish concurrency from parallelism
21 | 1. Work with GCD Dispatch Queues and Operation Queues
22 | 1. Identify the most common pitfalls and challenges that come with concurrency.
23 | 1. Understand and apply Semaphores to solve synchronization problems.
24 | 1. Practice common iOS interview projects & questions
25 |
26 | ## Schedule
27 |
28 | **Course Dates:** Thursday, October 22 – Thursday, December 10, 2020 (8 weeks)
29 |
30 | **Class Times:** Tuesday and Thursday at 2:30–5:15pm (13 class sessions)
31 |
32 | | Class | Date | Topics |
33 | |:-----:|:----------------------:|:---------------------------------------:|
34 | | 1 | Thu, Oct 22 | [Introduction to Concurrency & Parallelism]|
35 | | 2 | Tue, Oct 27 | [Grand Central Dispatch (Pt 1)] |
36 | | 3 | Thu, Oct 29 | [Grand Central Dispatch (Pt 2)] |
37 | | - | Tue, Nov 3 | **Vote! - Civic Responsibility Break** |
38 | | 4 | Thu, Nov 5 | [Grand Central Dispatch (Pt 3)]|
39 | | 5 | Tue, Nov 10 | [Semaphores] |
40 | | 6 | Thu, Nov 12 | Project Introduction & Workshop |
41 | | 7 | Tue, Nov 17 | [Operations (Pt 1)] |
42 | | 8 | Thu, Nov 19 | [Operations (Pt 2)] |
43 | | 9 | Tue, Nov 24 | [Operations (Pt 3)] |
44 | | - | Thu, Nov 26 | **Holiday- Thanksgiving** |
45 | | 10 | Tue, Dec 1 | [Pitfalls & Challenges] |
46 | | 11 | Thu, Dec 3 | [Libraries + Tools + Testing] |
47 | | 12 | Tue, Dec 8 | Final Exam |
48 | | 13 | Thu, Dec 10 | Presentations |
49 |
50 | [Introduction to Concurrency & Parallelism]: Lessons/01-Intro-Concurrency-&-Parallelism/Lesson1.md
51 | [Grand Central Dispatch (Pt 1)]: Lessons/02-Grand-Central_Dispatch-Pt1/Lesson2.md
52 | [Grand Central Dispatch (Pt 2)]: Lessons/03-Grand-Central_Dispatch-Pt2/Lesson3.md
53 | [Grand Central Dispatch (Pt 3)]: Lessons/04-Grand-Central_Dispatch-Pt3/Lesson4.md
54 | [Semaphores]: Lessons/05-Semaphores/Lesson5.md
55 | [Operations (Pt 1)]: Lessons/06-Operations-Pt1/Lesson6.md
56 | [Operations (Pt 2)]: Lessons/07-Operations-Pt2/Lesson7.md
57 | [Operations (Pt 3)]:Lessons/08-Operations-Pt3/Lesson8.md
58 | [Pitfalls & Challenges]: Lessons/09-Pitfalls-Challenges/Lesson9.md
59 | [Libraries + Tools + Testing]: Lessons/10-Course-Review-and-Workshop/Lesson10.md
60 |
61 |
62 | ## Assignment Schedule
63 |
64 | All except the final project are grade based on completion.
65 |
66 | | Assignment | Date Assigned | Due Date | Submission Form |
67 | |:-------------------------------------:|:-------------:|:------------:|:-----------------:|
68 | | [GCD RW Tutorial] | Oct 29 | Nov 5 | Gradescope |
69 | | [Janky Table Fix] | Nov 5 | Nov 12 | Gradescope |
70 | | [Semaphore Challenge] | Nov 10 | Nov 12 | Gradescope |
71 | | [Final Project] | Nov 12 | Dec 10 | Gradescope |
72 |
73 | [GCD RW Tutorial]: https://www.raywenderlich.com/5370-grand-central-dispatch-tutorial-for-swift-4-part-1-2
74 | [Janky Table Fix]: https://github.com/Make-School-Labs/iOS-JankyTable_starter
75 | [Semaphore Challenge]:Lessons/05-Semaphores/Lesson5.md
76 | [Final Project]: Assignments/Project.md
77 |
78 |
79 | ### Projects
80 |
81 | - [Project](Assignments/Project.md)
82 |
83 | ## Evaluation
84 |
85 | To pass this course you must meet the following requirements:
86 |
87 | - Complete all assignments listed in the Schedule
88 | - Pass the final project according to the associated project rubric (>=70 pts)
89 | - Pass the final summative assessment according to the rubric as specified in this class (>=70 pts)
90 | - This will be further explained in the [study guide](StudyGuide.md)
91 | - Actively participate in class and abide by the attendance policy
92 | - Make up all classwork from all absences
93 |
94 | ## Information Resources
95 |
96 | Any additional resources you may need (online books, etc.) can be found here. You can also find additional resources through the library linked below:
97 |
98 | - [make.sc/library](http://make.sc/library)
99 |
100 | ## Make School Course Policies
101 |
102 | - [Program Learning Outcomes](https://make.sc/program-learning-outcomes) - What you will achieve after finishing Make School, all courses are designed around these outcomes.
103 | - [Grading System](https://make.sc/grading-system) - How grading is done at Make School
104 | - [Code of Conduct, Equity, and Inclusion](https://make.sc/code-of-conduct) - Learn about Diversity and Inclusion at Make School
105 | - [Academic Honesty](https://make.sc/academic-honesty-policy) - Our policies around plagerism, cheating, and other forms of academic misconduct
106 | - [Attendance Policy](https://make.sc/attendance-policy) - What we expect from you in terms of attendance for all classes at Make School
107 | - [Course Credit Policy](https://make.sc/course-credit-policy) - Our policy for how you obtain credit for your courses
108 | - [Disability Services (Academic Accommodations)](https://make.sc/disability-services) - Services and accommodations we provide for students
109 | - [Online Learning Tutorial](https://make.sc/online-learning-tutorial) - How to succeed in online learning at Make School
110 | - [Student Handbook](https://make.sc/student-handbook) - Guidelines, policies, and resources for all Make School students
--------------------------------------------------------------------------------
/StudyGuide.md:
--------------------------------------------------------------------------------
1 | # Study Guide for MOB 2.3 Final Assessment
2 | **Overview**: Your final exam will focus on the learning outcomes for this course. Review each outcome thoroughly and ask questions if you are unclear about the outcome or your level of understanding.
3 |
4 | **Final Exam Format:** Your final exam will be on July 2nd.
5 |
6 | **Outcome:** Define and distinguish concurrency from parallelism
7 |
8 | - *Ways we learned about this in the course*
9 | - Class 1 covered both technical terms with examples.
10 | - Throughout the rest of the lessons you learned how different tools helped you achieve concurrency and paralellism in iOS.
11 |
12 | - *Ways you can demonstrate your skill / knowledge level of this outcome*
13 | - Define both terms.
14 | - Explain how you can have one without the other, or both together.
15 | - Explain how you can achieve concurrency and parallelism in iOS.
16 | - Give examples of situations in which you would benefit from implementing either in a project.
17 |
18 | **Outcome:** Work with GCD Dispatch Queues and Operation Queues.
19 |
20 | - *Ways we learned about this in the course*
21 | - Classes 2, 3 and 4 coverend GCD.
22 | - Classes 6, 7 and 8 covered Operations.
23 |
24 | - *Ways you can demonstrate your skill / knowledge level of this outcome*
25 | - Explain how GCD works.
26 | - Explain how queues are managed by GCD.
27 | - Identify when is the best situation to use GCD.
28 | - Describe the levels of priority for queues.
29 | - Explain how Operations work.
30 | - Explain how Operations can be managed.
31 | - Identify when is the best situation to use Operations.
32 |
33 |
34 | **Outcome:** Identify the most common pitfalls and challenges that come with concurrency.
35 |
36 | - *Ways we learned about this in the course*
37 | - In class 11 we saw how deadlock happened.
38 | - Class 9 covered Priority Inversion and Race Condition.
39 | - The Dining Philosophers problem could potentially end in deadlock or starvation.
40 |
41 | - *Ways you can demonstrate your skill / knowledge level of this outcome*
42 | - Identify when each situation occurs.
43 | - Propose solutions for the pitfalls.
44 |
45 | **Outcome:** Understand and apply Semaphores to solve syncrhonization problems.
46 |
47 | - *Ways we learned about this in the course*
48 | - Class 5 covered semaphores.
49 |
50 | - *Ways you can demonstrate your skill / knowledge level of this outcome*
51 | - Define a semaphore.
52 | - How does the class DispatchSemaphore work
53 | - Solve a synchronization problem with semaphores (rendez vous, mutex, etc.)
54 |
55 |
56 | **Outcome:** Practice common iOS interview projects and questions.
57 |
58 | - *Ways we learned about this in the course*
59 | - Janky table app demonstrates how you can use the content of the course to improve the performance of an app.
60 | - Class 9 had interview questions you should be comfortable answering.
61 |
62 | - *Ways you can demonstrate your skill / knowledge level of this outcome*
63 | - Make sure you can work your way around an app that need to improve its performance by either using GCD or Operations.
64 | - Correctly answer the questions in the activity from class 9.
65 |
--------------------------------------------------------------------------------
/Web/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Make-School-Courses/MOB-2.3-Concurrency-Parallelism-in-iOS/0ae12a6aa027257fa2f2d34fb98a32d941586347/Web/.DS_Store
--------------------------------------------------------------------------------
/Web/.nojekyll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Make-School-Courses/MOB-2.3-Concurrency-Parallelism-in-iOS/0ae12a6aa027257fa2f2d34fb98a32d941586347/Web/.nojekyll
--------------------------------------------------------------------------------
/Web/logo-icononly.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/Web/style.css:
--------------------------------------------------------------------------------
1 | :root {
2 | --base-font-weight: 400;
3 | --base-color: white;
4 | --base-font-size: 14px;
5 |
6 | --sidebar-width: 22rem;
7 | --sidebar-nav-link-before-content: "";
8 | --sidebar-nav-link-before-content-l3: "";
9 | --sidebar-name-font-weight: 500;
10 |
11 | --search-result-heading-font-size: 1em;
12 | --search-result-item-font-size: 0.9em;
13 | --search-result-heading-font-weight: 400;
14 | --search-result-heading-margin: 0 0 0.1em;
15 |
16 | --heading-font-weight: 500;
17 | --heading-h1-font-weight: 700;
18 | --heading-h1-font-size: 2.5em;
19 |
20 | --notice-font-style: italic;
21 | --notice-font-weight: 500;
22 |
23 | --blockquote-em-font-style: normal;
24 | --blockquote-em-font-weight: 700;
25 |
26 | --blockquote-font-style: italic;
27 | --blockquote-font-weight: 500;
28 |
29 | --code-font-size: 1em;
30 | --code-font-weight: 500;
31 | --code-tab-size: 2;
32 | }
33 |
34 | .sidebar>h1 {
35 | margin: 2.3rem auto 1rem;
36 | }
37 |
38 | .sidebar>h1>a>img {
39 | height: auto;
40 | }
41 |
42 | .markdown-section {
43 | max-width: 840px;
44 | }
45 |
46 | .markdown-section a:hover {
47 | border-bottom: 1px dashed rgba(255, 255, 255, 0.5);
48 | padding-bottom: 3px;
49 | }
50 |
51 | .sidebar-nav>ul:nth-child(1)>li>a.section-link,
52 | .sidebar-nav>ul:nth-child(1)>li>ul.children>li>a.section-link {
53 | display: block;
54 | }
55 |
56 | #main>h1:nth-child(1) {
57 | display: none;
58 | }
59 |
60 | #main>h1:nth-child(1)[id] {
61 | display: block;
62 | }
63 |
64 | .sidebar ul li a {
65 | color: #333;
66 | font-size: 14px;
67 | font-weight: 400;
68 | overflow: hidden;
69 | text-decoration: none;
70 | text-overflow: ellipsis;
71 | white-space: nowrap;
72 | }
73 |
74 | .sidebar ul li strong a {
75 | font-weight: 700;
76 | }
77 |
78 | .sidebar ul li ul.app-sub-sidebar li a {
79 | font-weight: 400;
80 | }
81 |
82 | .sidebar ul li ul.app-sub-sidebar li a.active {
83 | font-weight: 700;
84 | }
85 |
86 | body .docsify-copy-code-button {
87 | background: none !important;
88 | line-height: 1.5rem;
89 | position: absolute;
90 | word-wrap: normal;
91 | color: #ccc;
92 | font-size: .7rem;
93 | font-weight: 700;
94 | left: 0;
95 | height: 25px;
96 | top: -4px;
97 | text-align: center;
98 | }
99 |
100 | body .docsify-copy-code-button.success {
101 | color: #11A31B;
102 | }
103 |
104 | body .docsify-copy-code-button::after {}
105 |
106 | .app-name-link img {
107 | height: 150px;
108 | width: 150px;
109 | }
110 |
111 | table>tbody>tr>td::before {
112 | display: none;
113 | }
114 |
115 | .btn-edit-on-github {
116 | transition: background-color 0.5s ease;
117 | border: none;
118 | border-radius: 3px;
119 | background-color: var(--theme-color);
120 | position: absolute;
121 | top: var(--sidebar-toggle-offset-top);
122 | right: 0;
123 | margin-right: 45px;
124 | padding: 6px 10px 6px 5px;
125 | height: var(--sidebar-toggle-height);
126 | }
127 |
128 | .btn-edit-on-github a,
129 | .btn-edit-on-github svg {
130 | transition: color 0.5s ease;
131 | color: white;
132 | }
133 |
134 | .btn-edit-on-github a {
135 | text-decoration: none;
136 | position: relative;
137 | font-weight: 700;
138 | top: -1px;
139 | padding-left: 5px;
140 | }
141 |
142 | .btn-edit-on-github:hover {
143 | cursor: pointer;
144 | background-color: var(--mono-tint2);
145 | }
146 |
147 | .btn-edit-on-github:hover svg,
148 | .btn-edit-on-github:hover a {
149 | text-decoration: none;
150 | color: white;
151 | }
152 |
--------------------------------------------------------------------------------
/Web/sw.js:
--------------------------------------------------------------------------------
1 | /* ===========================================================
2 | * docsify sw.js
3 | * ===========================================================
4 | * Copyright 2016 @huxpro
5 | * Licensed under Apache 2.0
6 | * Register service worker.
7 | * ========================================================== */
8 |
9 | const RUNTIME = 'docsify'
10 | const HOSTNAME_WHITELIST = [
11 | self.location.hostname,
12 | 'fonts.gstatic.com',
13 | 'fonts.googleapis.com',
14 | 'unpkg.com',
15 | 'github.com',
16 | 'github.io',
17 | 'makeschool.com'
18 | ]
19 |
20 | // The Util Function to hack URLs of intercepted requests
21 | const getFixedUrl = (req) => {
22 | var now = Date.now()
23 | var url = new URL(req.url)
24 |
25 | // 1. fixed http URL
26 | // Just keep syncing with location.protocol
27 | // fetch(httpURL) belongs to active mixed content.
28 | // And fetch(httpRequest) is not supported yet.
29 | url.protocol = self.location.protocol
30 |
31 | // 2. add query for caching-busting.
32 | // Github Pages served with Cache-Control: max-age=600
33 | // max-age on mutable content is error-prone, with SW life of bugs can even extend.
34 | // Until cache mode of Fetch API landed, we have to workaround cache-busting with query string.
35 | // Cache-Control-Bug: https://bugs.chromium.org/p/chromium/issues/detail?id=453190
36 | if (url.hostname === self.location.hostname) {
37 | url.search += (url.search ? '&' : '?') + 'cache-bust=' + now
38 | }
39 | return url.href
40 | }
41 |
42 | /**
43 | * @Lifecycle Activate
44 | * New one activated when old isnt being used.
45 | *
46 | * waitUntil(): activating ====> activated
47 | */
48 | self.addEventListener('activate', event => {
49 | event.waitUntil(self.clients.claim())
50 | })
51 |
52 | /**
53 | * @Functional Fetch
54 | * All network requests are being intercepted here.
55 | *
56 | * void respondWith(Promise r)
57 | */
58 | self.addEventListener('fetch', event => {
59 | // Skip some of cross-origin requests, like those for Google Analytics.
60 | if (HOSTNAME_WHITELIST.indexOf(new URL(event.request.url).hostname) > -1) {
61 | // Stale-while-revalidate
62 | // similar to HTTP's stale-while-revalidate: https://www.mnot.net/blog/2007/12/12/stale
63 | // Upgrade from Jake's to Surma's: https://gist.github.com/surma/eb441223daaedf880801ad80006389f1
64 | const cached = caches.match(event.request)
65 | const fixedUrl = getFixedUrl(event.request)
66 | const fetched = fetch(fixedUrl, {
67 | cache: 'no-store'
68 | })
69 | const fetchedCopy = fetched.then(resp => resp.clone())
70 |
71 | // Call respondWith() with whatever we get first.
72 | // If the fetch fails (e.g disconnected), wait for the cache.
73 | // If there’s nothing in cache, wait for the fetch.
74 | // If neither yields a response, return offline pages.
75 | event.respondWith(
76 | Promise.race([fetched.catch(_ => cached), cached])
77 | .then(resp => resp || fetched)
78 | .catch(_ => {
79 | /* eat any errors */
80 | })
81 | )
82 |
83 | // Update the cache with the version we fetched (only for ok status)
84 | event.waitUntil(
85 | Promise.all([fetchedCopy, caches.open(RUNTIME)])
86 | .then(([response, cache]) => response.ok && cache.put(event.request, response))
87 | .catch(_ => {
88 | /* eat any errors */
89 | })
90 | )
91 | }
92 | })
93 |
--------------------------------------------------------------------------------
/_navbar.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | * **[Syllabus](README.md)**
4 | * **[Tracker](https://make.sc/mob2.3-tracker)**
5 | * [Make School](https://www.makeschool.com)
6 |
--------------------------------------------------------------------------------
/_sidebar.md:
--------------------------------------------------------------------------------
1 | - **[MOB 2.3 - Concurrency & Parallelism](README.md)**
2 | - **[Day 1: Intro](Lessons/01-Intro-Concurrency-&-Parallelism/Lesson1.md)**
3 | - **[Day 2: GCD Pt.1](Lessons/02-Grand-Central_Dispatch-Pt1/Lesson2.md)**
4 | - **[Day 3: GCD Pt.2](Lessons/03-Grand-Central_Dispatch-Pt2/Lesson3.md)**
5 | - **[Day 4: GCD Pt.3](Lessons/04-Grand-Central_Dispatch-Pt3/Lesson4.md)**
6 | - **[Day 5: Semaphores](Lessons/05-Semaphores/Lesson5.md)**
7 | - **[Day 6: Operations Pt.1](Lessons/06-Operations-Pt1/Lesson6.md)**
8 | - **[Day 7: Operations Pt.2](Lessons/07-Operations-Pt2/Lesson7.md)**
9 | - **[Day 8: Operations Pt.3](Lessons/08-Operations-Pt3/Lesson8.md)**
10 | - **[Day 9: Pitfalls ](Lessons/09-Pitfalls-Challenges/Lesson9.md)**
11 | - Day 10: Libraries and tools
12 | - Day 11: Lab day
13 | - **[Day 12: Review](Lessons/10-Course-Review-and-Workshop/Lesson10.md)**
14 | - Day 12: Final Exam
15 |
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
19 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
111 |
112 |
113 |
--------------------------------------------------------------------------------