You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
@@ -104,7 +104,7 @@ And now we can run our program!
104
104
ending!
105
105
fork number 3
106
106
107
-
[See the whole program.](./Ex1Threads.hs)
107
+
[See the whole program.](./Threads.hs)
108
108
109
109
## Thread synchronisation with MVars
110
110
@@ -133,12 +133,12 @@ main = do
133
133
134
134
Running this, you should see the following output:
135
135
136
-
$ runhaskell Ex2MVars.hs
136
+
$ runhaskell MVars.hs
137
137
Waiting...
138
138
Calculated result!
139
139
The answer is: 42
140
140
141
-
[See the whole program.](./Ex2MVars.hs)
141
+
[See the whole program.](./MVars.hs)
142
142
143
143
## Sharing state with MVars
144
144
@@ -153,14 +153,16 @@ In the presence of race conditions, errors will mean often the final result isn'
153
153
main =do
154
154
counter <- newMVar 0
155
155
156
-
let increment = modifyMVar_ counter (\c ->return$! c +1)
157
-
let incrementer =do
158
-
replicateM 1000 increment
159
-
return()
156
+
let increment =do
157
+
count <- takeMVar counter
158
+
putMVar counter $! count +1
159
+
incrementer =do
160
+
replicateM 1000 increment
161
+
return()
160
162
161
163
threads <- replicateM 5 (forkIO incrementer)
162
164
163
-
sleepMs 10
165
+
sleepMs 100
164
166
count <- takeMVar counter
165
167
print count
166
168
```
@@ -175,6 +177,13 @@ Note that in this case, our application is essentially single-threaded, because
175
177
So we gain no _time_ efficiency from using strict application (`$!`) - we could just as easily build up a huge thunk, then have the main thread evaluate it when we `print count`.
176
178
However, this costs memory, so evaluating the counter strictly at every step makes the program more _space_ efficient.
177
179
180
+
Let's give this example a go:
181
+
182
+
$ runhaskell MVarSharedState.hs
183
+
5000
184
+
185
+
[See the whole program.](./MVarSharedState.hs)
186
+
178
187
## Channels
179
188
180
189
Now that we've talked about `MVar`s, let's get up to speed with channels in Haskell.
@@ -225,7 +234,7 @@ Or, more concisely:
225
234
> I won't go into too much depth here.
226
235
> If you need a gentler and more in-depth introduction to `IO` actions, have a read of [this excellent article](http://blog.jle.im/entry/first-class-statements).
227
236
228
-
[See the whole program.](./Ex3Channels.hs)
237
+
[See the whole program.](./Channels.hs)
229
238
230
239
## Duplicating channels
231
240
@@ -275,7 +284,7 @@ main = do
275
284
sleepMs 5
276
285
```
277
286
278
-
$ runhaskell Ex4DuplicatingChannels.hs
287
+
$ runhaskell DuplicatingChannels.hs
279
288
First read: Hi!
280
289
Third read: Bye!
281
290
Fourth read: Bye!
@@ -284,7 +293,7 @@ Note that sometimes you may see `Second` getting `Hi!`, or you may see `Hi!` bei
284
293
This is due to the vagaries of thread execution, since we didn't do any synchronisation in these examples.
285
294
(It's also why I added a `sleepMs` in there - just to make sure the main thread waits for all the messages to filter through.)
286
295
287
-
[See the whole program.](./Ex4DuplicatingChannels.hs)
296
+
[See the whole program.](./DuplicatingChannels.hs)
0 commit comments