Skip to content

Commit 4d1fbde

Browse files
Update code examples to match package sources (#51)
1 parent cf0f0a1 commit 4d1fbde

File tree

1 file changed

+31
-32
lines changed

1 file changed

+31
-32
lines changed

Guide.docc/CommonProblems.md

+31-32
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ without any help from the compiler.
3030
### Sendable Types
3131

3232
```swift
33-
var islandsInTheSea = 42
33+
var supportedStyleCount = 42
3434
```
3535

3636
Here, we have defined a global variable.
@@ -39,61 +39,61 @@ isolation domain. Compiling the above code in Swift 6 mode
3939
produces an error message:
4040

4141
```
42-
1 | var islandsInTheSea = 42
43-
| |- error: global variable 'islandsInTheSea' is not concurrency-safe because it is non-isolated global shared mutable state
44-
| |- note: convert 'islandsInTheSea' to a 'let' constant to make the shared state immutable
45-
| |- note: restrict 'islandsInTheSea' to the main actor if it will only be accessed from the main thread
46-
| |- note: unsafely mark 'islandsInTheSea' as concurrency-safe if all accesses are protected by an external synchronization mechanism
42+
1 | var supportedStyleCount = 42
43+
| |- error: global variable 'supportedStyleCount' is not concurrency-safe because it is non-isolated global shared mutable state
44+
| |- note: convert 'supportedStyleCount' to a 'let' constant to make the shared state immutable
45+
| |- note: restrict 'supportedStyleCount' to the main actor if it will only be accessed from the main thread
46+
| |- note: unsafely mark 'supportedStyleCount' as concurrency-safe if all accesses are protected by an external synchronization mechanism
4747
2 |
4848
```
4949

5050
Two functions with different isolation domains accessing this
51-
variable risks a data race. In the following code, `printIslands()`
51+
variable risks a data race. In the following code, `printSupportedStyles()`
5252
could be running on the main actor concurrently with a call to
53-
`addIsland()` from another isolation domain:
53+
`addNewStyle()` from another isolation domain:
5454

5555
```swift
5656
@MainActor
57-
func printIslands() {
58-
print("Islands in the sea of concurrency: ", islandsInTheSea)
57+
func printSupportedStyles() {
58+
print("Supported styles: ", supportedStyleCount)
5959
}
6060

61-
func addIsland() {
62-
let island = Island()
61+
func addNewStyle() {
62+
let style = Style()
6363

64-
islandsInTheSea += 1
64+
supportedStyleCount += 1
6565

66-
addToMap(island)
66+
storeStyle(style)
6767
}
6868
```
6969

7070
One way to address the problem is by changing variable's isolation.
7171

7272
```swift
7373
@MainActor
74-
var islandsInTheSea = 42
74+
var supportedStyleCount = 42
7575
```
7676

7777
The variable remains mutable, but has been isolated to a global actor.
7878
All accesses can now only happen in one isolation domain, and the synchronous
79-
access within `addIsland` would be invalid at compile time.
79+
access within `addNewStyle` would be invalid at compile time.
8080

8181
If the variable is meant to be constant and is never mutated,
8282
a straight-forward solution is to express this to the compiler.
8383
By changing the `var` to a `let`, the compiler can statically
8484
disallow mutation, guaranteeing safe read-only access.
8585

8686
```swift
87-
let islandsInTheSea = 42
87+
let supportedStyleCount = 42
8888
```
8989

9090
If there is synchronization in place that protects this variable in a way that
9191
is invisible to the compiler, you can disable all isolation checking for
92-
`islandsInTheSea` using the `nonisolated(unsafe)` keyword:
92+
`supportedStyleCount` using the `nonisolated(unsafe)` keyword:
9393

9494
```swift
95-
/// This value is only ever accessed while holding `islandLock`.
96-
nonisolated(unsafe) var islandsInTheSea = 42
95+
/// This value is only ever accessed while holding `styleLock`.
96+
nonisolated(unsafe) var supportedStyleCount = 42
9797
```
9898

9999
Only use `nonisolated(unsafe)` when you are carefully guarding all access to
@@ -108,36 +108,35 @@ Global _reference_ types present an additional challenge, because they
108108
are typically not `Sendable`.
109109

110110
```swift
111-
class Chicken {
112-
let name: String
113-
var currentHunger: HungerLevel
111+
class WindowStyler {
112+
var background: ColorComponents
114113

115-
static let prizedHen = Chicken()
114+
static let defaultStyler = WindowStyler()
116115
}
117116
```
118117

119118
The problem with this `static let` declaration is not related to the
120119
mutability of the variable.
121-
The issue is `Chicken` is a non-Sendable type, making its internal state
120+
The issue is `WindowStyler` is a non-`Sendable` type, making its internal state
122121
unsafe to share across isolation domains.
123122

124123
```swift
125-
func feedPrizedHen() {
126-
Chicken.prizedHen.currentHunger = .wellFed
124+
func resetDefaultStyle() {
125+
WindowStyler.defaultStyler.background = ColorComponents(red: 1.0, green: 1.0, blue: 1.0)
127126
}
128127

129128
@MainActor
130-
class ChickenValley {
131-
var flock: [Chicken]
129+
class StyleStore {
130+
var stylers: [WindowStyler]
132131

133-
func compareHunger() -> Bool {
134-
flock.contains { $0.currentHunger > Chicken.prizedHen.currentHunger }
132+
func hasDefaultBackground() -> Bool {
133+
stylers.contains { $0.background == WindowStyler.defaultStyler.background }
135134
}
136135
}
137136
```
138137

139138
Here, we see two functions that could access the internal state of the
140-
`Chicken.prizedHen` concurrently.
139+
`WindowStyler.defaultStyler` concurrently.
141140
The compiler only permits these kinds of cross-isolation accesses with
142141
`Sendable` types.
143142
One option is to isolate the variable to a single domain using a global actor.

0 commit comments

Comments
 (0)