@@ -34,10 +34,9 @@ chan.write(1) // happens immediately
34
34
let x1 = chan.read ()
35
35
36
36
/// But if we read from an empty Channel the read blocks until we write to the Channel again.
37
- let time = dispatch_time (DISPATCH_TIME_NOW, 1 * Double (NSEC_PER_SEC))
38
- dispatch_after (time, dispatch_get_global_queue (DISPATCH_QUEUE_PRIORITY_HIGH, 0 ), {
39
- chan.write (2 ) // Causes the read to suceed and unblocks the reading thread.
40
- })
37
+ DispatchQueue.global ().asyncAfter (deadline : .now () + .seconds (1 )) {
38
+ chan.write (2 ) // Causes the read to suceed and unblocks the reading thread.
39
+ }
41
40
42
41
let x2 = chan.read () // Blocks until the dispatch block is executed and the Channel becomes non-empty.
43
42
```
@@ -48,26 +47,26 @@ be accessed concurrently in an MVar.
48
47
``` swift
49
48
import class Concurrent .MVar
50
49
51
- /// An MVar (Mutable Variable) is a thread-safe synchronizing variable that can be used for
50
+ /// An MVar (Mutable Variable) is a thread-safe synchronizing variable that can be used for
52
51
/// communication between threads.
53
- ///
52
+ ///
54
53
/// This MVar is currently empty. Any reads or writes to it will block until it becomes "full".
55
54
let counter : MVar<Int > = MVar ()
56
55
57
- /// Attempt to increment the counter from 3 different threads. Because the counter is empty,
56
+ /// Attempt to increment the counter from 3 different threads. Because the counter is empty,
58
57
/// all of these writes will block until a value is put into the MVar.
59
- dispatch_async ( dispatch_get_global_queue (DISPATCH_QUEUE_PRIORITY_HIGH, 0 ), {
60
- counter.modify_ ( + 1 )
61
- println (" Modifier #1" )
62
- })
63
- dispatch_async ( dispatch_get_global_queue (DISPATCH_QUEUE_PRIORITY_HIGH, 0 ), {
64
- counter.modify_ ( + 1 )
65
- println (" Modifier #2" )
66
- })
67
- dispatch_async ( dispatch_get_global_queue (DISPATCH_QUEUE_PRIORITY_HIGH, 0 ), {
68
- counter.modify_ ( + 1 )
69
- println (" Modifier #3" )
70
- })
58
+ DispatchQueue. global (). async {
59
+ counter.modify_ { $0 + 1 }
60
+ print (" Modifier #1" )
61
+ }
62
+ DispatchQueue. global (). async {
63
+ counter.modify_ { $0 + 1 }
64
+ print (" Modifier #2" )
65
+ }
66
+ DispatchQueue. global (). async {
67
+ counter.modify_ { $0 + 1 }
68
+ print (" Modifier #3" )
69
+ }
71
70
72
71
/// All the writes will now proceed and unblock each thread in turn. The order of writes
73
72
/// is determined by the order in which each thread called `modify(_ :)`.
@@ -82,7 +81,7 @@ counter.put(0)
82
81
///
83
82
/// Because our take occured after the put, all of the modifications we made before will
84
83
/// complete before we read the final value.
85
- println (counter.take ()) // 3
84
+ print (counter.take ()) // 3
86
85
```
87
86
88
87
` MVar ` s can also be used purely as a synchronization point between multiple threads:
@@ -97,19 +96,19 @@ let done = MVar<()>() // The synchronization point
97
96
/// Puts a value into the now-empty ping variable then blocks waiting for the
98
97
/// pong variable to have a value put into it. Once we have read the pong variable,
99
98
/// we unblock the done MVar, and in doing so, unblock the main thread.
100
- dispatch_async ( dispatch_get_global_queue (DISPATCH_QUEUE_PRIORITY_HIGH, 0 )) {
101
- pingvar.put (" ping" )
102
- let contents = pongvar.take ()
103
- done.put (())
99
+ DispatchQueue. global (). async {
100
+ pingvar.put (" ping" )
101
+ _ = pongvar.take ()
102
+ done.put (())
104
103
}
105
104
106
105
/// Takes the contents of the ping variable then puts a value into the pong variable
107
106
/// to unblock the take we just performed.
108
- dispatch_async ( dispatch_get_global_queue (DISPATCH_QUEUE_PRIORITY_HIGH, 0 )) {
109
- let contents = pingvar.take ()
110
- pongvar.put (" pong" )
107
+ DispatchQueue. global (). async {
108
+ _ = pingvar.take ()
109
+ pongvar.put (" pong" )
111
110
}
112
-
111
+
113
112
/// Blocks until all work has completed.
114
113
done.take ()
115
114
```
@@ -123,27 +122,28 @@ typealias Account = TVar<UInt>
123
122
124
123
/// Some atomic operations
125
124
func withdraw (from account : Account, amount : UInt ) -> STM<()> {
126
- return account.read ().flatMap { balance in
127
- if balance > amount {
128
- return account.write (balance - amount)
129
- }
130
- return STM < () > . pure (())
131
- }
125
+ return account.read ().flatMap { balance in
126
+ if balance > amount {
127
+ return account.write (balance - amount)
128
+ }
129
+ throw TransactionError. insufficientFunds
130
+ }
132
131
}
132
+
133
133
func deposit (into account : Account, amount : UInt ) -> STM<()> {
134
- return account.read ().flatMap { balance in
135
- return account.write (balance + amount)
136
- }
134
+ return account.read ().flatMap { balance in
135
+ return account.write (balance + amount)
136
+ }
137
137
}
138
138
139
139
func transfer (from : Account, to : Account, amount : UInt ) -> STM<()> {
140
- return from.read ().flatMap { fromBalance in
141
- if fromBalance > amount {
142
- return withdraw (from : from, amount : amount)
143
- .then (deposit (into : to, amount : amount))
144
- }
145
- return STM< ()> .pure (())
140
+ return from.read ().flatMap { fromBalance in
141
+ if fromBalance > amount {
142
+ return withdraw (from : from, amount : amount)
143
+ .then (deposit (into : to, amount : amount))
146
144
}
145
+ throw TransactionError.insufficientFunds
146
+ }
147
147
}
148
148
149
149
/// Here are some bank accounts represented as TVars - transactional memory
@@ -155,8 +155,8 @@ let bob = Account(100)
155
155
/// Either all of the effects of this transaction apply to the accounts or
156
156
/// everything is completely rolled back and it was as if nothing ever happened.
157
157
let finalStatement =
158
- transfer (from : alice, to : bob, 100 )
159
- .then (transfer (from : bob, to : alice, 20 ))
158
+ transfer (from : alice, to : bob, amount : 100 )
159
+ .then (transfer (from : bob, to : alice, amount : 20 ))
160
160
.then (deposit (into : bob, amount : 1000 ))
161
161
.then (transfer (from : bob, to : alice, amount : 500 ))
162
162
.atomically ()
0 commit comments