-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.swift
137 lines (115 loc) · 4.94 KB
/
main.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
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
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
//
// main.swift
// AsyncCancellation
//
// Created by Doug on 10/31/18.
//
import Foundation
public enum WebResourceError: Error {
case invalidResult
}
/// URLSession example
func appleRequestExample() {
func performAppleSearch() /* async */ throws -> String {
let urlSession = URLSession(configuration: .default)
let request = URLRequest(url: URL(string: "https://itunes.apple.com/search")!)
let result = /* await */ try urlSession.asyncDataTask(with: request)
if let resultString = String(data: result.data, encoding: .utf8) {
return resultString
}
throw WebResourceError.invalidResult
}
// Execute the URLSession example
// Set a timeout (seconds) to prevent hangs
let cancelScope = CancelScope(timeout: 30.0)
let appleError: (Error) -> () = { error in
print("Apple search error: \(error)")
}
do {
try beginAsync(context: cancelScope, error: appleError) {
let result = try performAppleSearch()
print("Apple search result: \(result)")
}
} catch {
// Error is handled by the beginAsync 'error' callback
}
// Uncomment to see cancellation behavior
// cancelScope.cancel()
// Uncomment to see suspend behavior
// cancelScope.suspendTasks()
}
appleRequestExample()
/***********************************************************************************
Image loading example from 'Async/Await for Swift' by Chris Lattner and Joe Groff
https://gist.github.com/dougzilla32/ce47a72067f9344742e10020ad4c8c41
***********************************************************************************/
func imageLoadingExample() {
/// For the purpose of this example, send a simple web request rather than loading actual image data
func loadWebResource(_ name: String) throws -> String {
let urlSession = URLSession(configuration: .default)
let request = URLRequest(url: URL(string: "https://itunes.apple.com/search")!)
let result = /* await */ try urlSession.asyncDataTask(with: request)
if let resultString = String(data: result.data, encoding: .utf8) {
return resultString
}
throw WebResourceError.invalidResult
}
/// For the purpose of this example, concat two strings in another thread rather than decoding image data
func decodeImage(_ profile: String, _ data: String) throws -> String {
return /* await */ try suspendAsync { continuation, error in
let task = DispatchWorkItem {
continuation("\(profile)+\(data)")
}
if let cancelScope: CancelScope = getCoroutineContext() {
cancelScope.add(cancellable: task)
}
if let dispatchQueue: DispatchQueue = getCoroutineContext() {
dispatchQueue.asyncAfter(deadline: DispatchTime.now() + 0.5, execute: task)
}
}
}
/// For the purpose of this example, condense all the whitespace in the 'image' string
func dewarpAndCleanupImage(_ image: String) throws -> String {
return /* await */ try suspendAsync { continuation, error in
let task = DispatchWorkItem {
let components = image.components(separatedBy: .whitespacesAndNewlines)
let condensedImage = components.filter { !$0.isEmpty }.joined(separator: " ")
continuation(condensedImage)
}
if let cancelScope: CancelScope = getCoroutineContext() {
cancelScope.add(cancellable: task)
}
if let dispatchQueue: DispatchQueue = getCoroutineContext() {
dispatchQueue.asyncAfter(deadline: DispatchTime.now() + 0.5, execute: task)
}
}
}
/// Image loading example
func processImageData1a() /* async */ throws -> String {
let dataResource = Future { /* await */ try loadWebResource("dataprofile.txt") }
let imageResource = Future { /* await */ try loadWebResource("imagedata.dat") }
// ... other stuff can go here to cover load latency...
let imageTmp = /* await */ try decodeImage(try dataResource.get(), try imageResource.get())
let imageResult = /* await */ try dewarpAndCleanupImage(imageTmp)
return imageResult
}
// Set a timeout (seconds) to prevent hangs
let cancelScope = CancelScope(timeout: 30.0)
let queue = DispatchQueue.global(qos: .default)
let imageError: (Error) -> () = { error in
print("Image loading error: \(error)")
}
do {
try beginAsync(context: [cancelScope, queue], error: imageError) {
let result = try processImageData1a()
print("Image result: \(result)")
}
} catch {
// Error is handled by the beginAsync 'error' callback
}
// Uncomment to see cancellation behavior
// cancelScope.cancel()
}
imageLoadingExample()
// Wait long enough for everything to complete
RunLoop.current.run(until: Date() + 5.0)